home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 February / CHIP_2_98.iso / misc / src / rpm / lib / fs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-09-17  |  6.1 KB  |  282 lines

  1. #include "miscfn.h"
  2.  
  3. #if HAVE_ALLOCA_H
  4. # include <alloca.h>
  5. #endif
  6.  
  7. #include <errno.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <sys/stat.h>
  12. #include <sys/types.h>
  13.  
  14. #include "header.h"
  15. #include "intl.h"
  16. #include "rpmlib.h"
  17.  
  18. struct fsinfo {
  19.     char * mntPoint;
  20.     dev_t dev;
  21. };
  22.  
  23. static struct fsinfo * filesystems;
  24. static char ** fsnames;
  25. static int numFilesystems;
  26.  
  27. static int getFilesystemList(void);
  28.  
  29. #if HAVE_MNTCTL
  30.  
  31. /* modeled after sample code from Till Bubeck */
  32.  
  33. #include <sys/mntctl.h>
  34. #include <sys/vmount.h>
  35.  
  36. /* 
  37.  * There is NO mntctl prototype in any header file of AIX 3.2.5! 
  38.  * So we have to declare it by ourself...
  39.  */
  40. int mntctl(int command, int size, char *buffer);
  41.  
  42. static int getFilesystemList(void) {
  43.     int size;
  44.     void * buf;
  45.     struct vmount * vm;
  46.     struct stat sb;
  47.     int num;
  48.     int fsnameLength;
  49.     int i;
  50.  
  51.     num = mntctl(MCTL_QUERY, sizeof(size), (char *) &size);
  52.     if (num < 0) {
  53.     rpmError(RPMERR_MTAB, _("mntctl() failed to return fugger size: %s"), 
  54.          strerror(errno));
  55.     return 1;
  56.     }
  57.  
  58.     /*
  59.      * Double the needed size, so that even when the user mounts a 
  60.      * filesystem between the previous and the next call to mntctl
  61.      * the buffer still is large enough.
  62.      */
  63.     size *= 2;
  64.  
  65.     buf = alloca(size);
  66.     num = mntctl(MCTL_QUERY, size, buf);
  67.     if ( num <= 0 ) {
  68.         rpmError(RPMERR_MTAB, "mntctl() failed to return mount points: %s", 
  69.          strerror(errno));
  70.     return 1;
  71.     }
  72.  
  73.     numFilesystems = num;
  74.  
  75.     filesystems = malloc(sizeof(*filesystems) * (numFilesystems + 1));
  76.     fsnames = malloc(sizeof(char *) * (numFilesystems + 1));
  77.     
  78.     for (vm = buf, i = 0; i < num; i++) {
  79.     fsnameLength = vm->vmt_data[VMT_STUB].vmt_size;
  80.     fsnames[i] = malloc(fsnameLength + 1);
  81.     strncpy(fsnames[i],(char *)vm + vm->vmt_data[VMT_STUB].vmt_off, 
  82.         fsnameLength);
  83.  
  84.     filesystems[i].mntPoint = fsnames[i];
  85.     
  86.     if (stat(filesystems[i].mntPoint, &sb)) {
  87.         rpmError(RPMERR_STAT, "failed to stat %s: %s", fsnames[i],
  88.             strerror(errno));
  89.  
  90.         for (i = 0; i < num; i++)
  91.         free(filesystems[i].mntPoint);
  92.         free(filesystems);
  93.         free(fsnames);
  94.  
  95.         filesystems = NULL;
  96.     }
  97.     
  98.     filesystems[i].dev = sb.st_dev;
  99.  
  100.     /* goto the next vmount structure: */
  101.     vm = (struct vmount *)((char *)vm + vm->vmt_length);
  102.     }
  103.  
  104.     filesystems[i].mntPoint = NULL;
  105.     fsnames[i]              = NULL;
  106.  
  107.     return 0;
  108. }
  109. #else 
  110. static int getFilesystemList(void) {
  111.     int numAlloced = 10;
  112.     int num = 0;
  113.     struct stat sb;
  114.     int i;
  115.     char * mntdir;
  116.     #if GETMNTENT_ONE || GETMNTENT_TWO
  117.     our_mntent item, * itemptr;
  118.     FILE * mtab;
  119.     #elif HAVE_GETMNTINFO_R
  120.     struct statfs * mounts = NULL;
  121.     int mntCount = 0, bufSize = 0, flags = MNT_NOWAIT;
  122.     int nextMount = 0;
  123.     #endif
  124.  
  125.     #if GETMNTENT_ONE || GETMNTENT_TWO
  126.     mtab = fopen(MOUNTED, "r");
  127.     if (!mtab) {
  128.         rpmError(RPMERR_MTAB, _("failed to open %s: %s"), MOUNTED, 
  129.              strerror(errno));
  130.         return 1;
  131.     }
  132.     #elif HAVE_GETMNTINFO_R
  133.     getmntinfo_r(&mounts, flags, &mntCount, &bufSize);
  134.     #endif
  135.  
  136.     filesystems = malloc(sizeof(*filesystems) * (numAlloced + 1));
  137.  
  138.     while (1) {
  139.     #if GETMNTENT_ONE
  140.         /* this is Linux */
  141.         itemptr = getmntent(mtab);
  142.         if (!itemptr) break;
  143.         item = *itemptr;
  144.         mntdir = item.our_mntdir;
  145.     #elif GETMNTENT_TWO
  146.         /* Solaris, maybe others */
  147.         if (getmntent(mtab, &item)) break;
  148.         mntdir = item.our_mntdir;
  149.     #elif HAVE_GETMNTINFO_R
  150.         if (nextMount == mntCount) break;
  151.         mntdir = mounts[nextMount++].f_mntonname;
  152.     #endif
  153.  
  154.     if (stat(mntdir, &sb)) {
  155.         rpmError(RPMERR_STAT, "failed to stat %s: %s", mntdir,
  156.             strerror(errno));
  157.  
  158.         for (i = 0; i < num; i++)
  159.         free(filesystems[i].mntPoint);
  160.         free(filesystems);
  161.  
  162.         filesystems = NULL;
  163.     }
  164.  
  165.     if (num == numAlloced) {
  166.         numAlloced += 10;
  167.         filesystems = realloc(filesystems, 
  168.                   sizeof(*filesystems) * (numAlloced + 1));
  169.     }
  170.  
  171.     filesystems[num].dev = sb.st_dev;
  172.     filesystems[num++].mntPoint = strdup(mntdir);
  173.     }
  174.  
  175.     #if GETMNTENT_ONE || GETMNTENT_TWO
  176.     fclose(mtab);
  177.     #elif HAVE_GETMNTINFO_R
  178.     free(mounts);
  179.     #endif
  180.  
  181.     filesystems[num].mntPoint = NULL;
  182.  
  183.     fsnames = malloc(sizeof(*fsnames) * (num + 1));
  184.     for (i = 0; i < num; i++)
  185.     fsnames[i] = filesystems[i].mntPoint;
  186.     fsnames[num] = NULL;
  187.  
  188.     numFilesystems = num;
  189.  
  190.     return 0; 
  191. }
  192. #endif
  193.  
  194. int rpmGetFilesystemList(char *** listptr, int * num) {
  195.     if (!fsnames) 
  196.     if (getFilesystemList())
  197.         return 1;
  198.  
  199.     if (listptr) *listptr = fsnames;
  200.     if (num) *num = numFilesystems;
  201.  
  202.     return 0;
  203. }
  204.  
  205. int rpmGetFilesystemUsage(char ** fileList, int_32 * fssizes, int numFiles,
  206.               uint_32 ** usagesPtr, int flags) {
  207.     int_32 * usages;
  208.     int i, len, j;
  209.     char * buf, * dirName;
  210.     char * chptr;
  211.     int maxLen;
  212.     char * lastDir;
  213.     int lastfs = 0;
  214.     int lastDev = -1;        /* I hope nobody uses -1 for a st_dev */
  215.     struct stat sb;
  216.  
  217.     if (!fsnames) 
  218.     if (getFilesystemList())
  219.         return 1;
  220.  
  221.     usages = calloc(numFilesystems, sizeof(usages));
  222.  
  223.     maxLen = 0;
  224.     for (i = 0; i < numFiles; i++) {
  225.     len = strlen(fileList[i]);
  226.     if (maxLen < len) maxLen = len;
  227.     }
  228.     
  229.     buf = alloca(maxLen + 1);
  230.     lastDir = alloca(maxLen + 1);
  231.     dirName = alloca(maxLen + 1);
  232.     *lastDir = '\0';
  233.  
  234.     for (i = 0; i < numFiles; i++) {
  235.     strcpy(buf, fileList[i]);
  236.     chptr = buf + strlen(buf) - 1;
  237.     while (*chptr != '/') chptr--;
  238.     if (chptr == buf)
  239.         buf[1] = '\0';
  240.     else
  241.         *chptr-- = '\0';
  242.  
  243.     if (strcmp(lastDir, buf)) {
  244.         strcpy(dirName, buf);
  245.         chptr = dirName + strlen(dirName) - 1;
  246.         while (stat(dirName, &sb)) {
  247.         if (errno != ENOENT) {
  248.             rpmError(RPMERR_STAT, "failed to stat %s: %s", buf,
  249.                 strerror(errno));
  250.             free(usages);
  251.             return 1;
  252.         }
  253.  
  254.         while (*chptr != '/') chptr--;
  255.         *chptr-- = '\0';
  256.         }
  257.  
  258.         if (lastDev != sb.st_dev) {
  259.         for (j = 0; j < numFilesystems; j++)
  260.             if (filesystems[j].dev == sb.st_dev) break;
  261.  
  262.         if (j == numFilesystems) {
  263.             rpmError(RPMERR_BADDEV, 
  264.                 "file %s is on an unknown device", buf);
  265.             free(usages);
  266.             return 1;
  267.         }
  268.  
  269.         lastfs = j;
  270.         lastDev = sb.st_dev;
  271.         }
  272.     }
  273.  
  274.     strcpy(lastDir, buf);
  275.     usages[lastfs] += fssizes[i];
  276.     }
  277.  
  278.     *usagesPtr = usages;
  279.  
  280.     return 0;
  281. }
  282.