00001
00006 #include "system.h"
00007 #include "rpmlib.h"
00008 #include "rpmmacro.h"
00009 #include "debug.h"
00010
00011 #define MNT_DEV_PREFIX "/mnt/"
00012 #define MNT_DEV_PREFIX_LENGTH (sizeof(MNT_DEV_PREFIX)-1)
00013
00014
00015
00016 struct fsinfo {
00017 const char * mntPoint;
00018 dev_t dev;
00019 int rdonly;
00020 };
00021
00022
00023 static struct fsinfo * filesystems = NULL;
00024
00025 static const char ** fsnames = NULL;
00026
00027 static int numFilesystems = 0;
00028
00029 void freeFilesystems(void)
00030 {
00031 if (filesystems) {
00032 int i;
00033 for (i = 0; i < numFilesystems; i++)
00034 filesystems[i].mntPoint = _free(filesystems[i].mntPoint);
00035 filesystems = _free(filesystems);
00036 }
00037 if (fsnames) {
00038 #if 0
00039 free(fsnames);
00040 #endif
00041 fsnames = NULL;
00042 }
00043 numFilesystems = 0;
00044 }
00045
00046 #if HAVE_MNTCTL
00047
00048
00049
00050 #include <sys/mntctl.h>
00051 #include <sys/vmount.h>
00052
00053
00054
00055
00056
00057 int mntctl(int command, int size, char *buffer);
00058
00064 static int getFilesystemList(void)
00065
00066 {
00067 int size;
00068 void * buf;
00069 struct vmount * vm;
00070 struct stat sb;
00071 int rdonly = 0;
00072 int num;
00073 int fsnameLength;
00074 int i;
00075
00076 num = mntctl(MCTL_QUERY, sizeof(size), (char *) &size);
00077 if (num < 0) {
00078 rpmError(RPMERR_MTAB, _("mntctl() failed to return size: %s\n"),
00079 strerror(errno));
00080 return 1;
00081 }
00082
00083
00084
00085
00086
00087
00088 size *= 2;
00089
00090 buf = alloca(size);
00091 num = mntctl(MCTL_QUERY, size, buf);
00092 if ( num <= 0 ) {
00093 rpmError(RPMERR_MTAB, _("mntctl() failed to return mount points: %s\n"),
00094 strerror(errno));
00095 return 1;
00096 }
00097
00098 numFilesystems = num;
00099
00100 filesystems = xcalloc((numFilesystems + 1), sizeof(*filesystems));
00101 fsnames = xcalloc((numFilesystems + 1), sizeof(char *));
00102
00103 for (vm = buf, i = 0; i < num; i++) {
00104 char *fsn;
00105 fsnameLength = vm->vmt_data[VMT_STUB].vmt_size;
00106 fsn = xmalloc(fsnameLength + 1);
00107 strncpy(fsn, (char *)vm + vm->vmt_data[VMT_STUB].vmt_off,
00108 fsnameLength);
00109
00110 filesystems[i].mntPoint = fsnames[i] = fsn;
00111 if (strncmp(mntdir, MNT_DEV_PREFIX, MNT_DEV_PREFIX_LENGTH)) {
00112 if (stat(filesystems[i].mntPoint, &sb)) {
00113 rpmError(RPMERR_STAT, _("failed to stat %s: %s\n"), fsnames[i],
00114 strerror(errno));
00115
00116 freeFilesystems();
00117 return 1;
00118 }
00119 } else
00120 sb.st_dev = 0;
00121
00122 filesystems[i].dev = sb.st_dev;
00123 filesystems[i].rdonly = rdonly;
00124
00125
00126 vm = (struct vmount *)((char *)vm + vm->vmt_length);
00127 }
00128
00129 filesystems[i].mntPoint = NULL;
00130 fsnames[i] = NULL;
00131
00132 return 0;
00133 }
00134
00135 #else
00136
00142 static int getFilesystemList(void)
00143
00144
00145 {
00146 int numAlloced = 10;
00147 struct stat sb;
00148 int i;
00149 const char * mntdir;
00150 int rdonly = 0;
00151
00152 # if GETMNTENT_ONE || GETMNTENT_TWO
00153 our_mntent item;
00154 FILE * mtab;
00155
00156 mtab = fopen(MOUNTED, "r");
00157 if (!mtab) {
00158 rpmError(RPMERR_MTAB, _("failed to open %s: %s\n"), MOUNTED,
00159 strerror(errno));
00160 return 1;
00161 }
00162 # elif HAVE_GETMNTINFO_R
00163 struct statfs * mounts = NULL;
00164 int mntCount = 0, bufSize = 0, flags = MNT_NOWAIT;
00165 int nextMount = 0;
00166
00167 getmntinfo_r(&mounts, flags, &mntCount, &bufSize);
00168 # endif
00169
00170 filesystems = xcalloc((numAlloced + 1), sizeof(*filesystems));
00171
00172 numFilesystems = 0;
00173 while (1) {
00174 # if GETMNTENT_ONE
00175
00176
00177 our_mntent * itemptr = getmntent(mtab);
00178 if (!itemptr) break;
00179 item = *itemptr;
00180 mntdir = item.our_mntdir;
00181 #if defined(MNTOPT_RO)
00182
00183 if (hasmntopt(itemptr, MNTOPT_RO) != NULL)
00184 rdonly = 1;
00185
00186 #endif
00187
00188 # elif GETMNTENT_TWO
00189
00190 if (getmntent(mtab, &item)) break;
00191 mntdir = item.our_mntdir;
00192 # elif HAVE_GETMNTINFO_R
00193 if (nextMount == mntCount) break;
00194 mntdir = mounts[nextMount++].f_mntonname;
00195 # endif
00196
00197 #ifdef our_mnttype
00198 if ( item.our_mnttype && *item.our_mnttype && !strcmp( "supermount", item.our_mnttype ) )
00199 continue;
00200 #endif
00201
00202 if (stat(mntdir, &sb)) {
00203 rpmError(RPMERR_STAT, _("failed to stat %s: %s\n"), mntdir,
00204 strerror(errno));
00205
00206 freeFilesystems();
00207 return 1;
00208 }
00209
00210 numFilesystems++;
00211 if ((numFilesystems + 1) == numAlloced) {
00212 numAlloced += 10;
00213 filesystems = xrealloc(filesystems,
00214 sizeof(*filesystems) * (numAlloced + 1));
00215 }
00216
00217 filesystems[numFilesystems-1].dev = sb.st_dev;
00218 filesystems[numFilesystems-1].mntPoint = xstrdup(mntdir);
00219 filesystems[numFilesystems-1].rdonly = rdonly;
00220 }
00221
00222 # if GETMNTENT_ONE || GETMNTENT_TWO
00223 (void) fclose(mtab);
00224 # elif HAVE_GETMNTINFO_R
00225 mounts = _free(mounts);
00226 # endif
00227
00228 filesystems[numFilesystems].dev = 0;
00229 filesystems[numFilesystems].mntPoint = NULL;
00230 filesystems[numFilesystems].rdonly = 0;
00231
00232 fsnames = xcalloc((numFilesystems + 1), sizeof(*fsnames));
00233 for (i = 0; i < numFilesystems; i++)
00234 fsnames[i] = filesystems[i].mntPoint;
00235 fsnames[numFilesystems] = NULL;
00236
00237 return 0;
00238 }
00239 #endif
00240
00241 int rpmGetFilesystemList(const char *** listptr, int * num)
00242 {
00243 if (!fsnames)
00244 if (getFilesystemList())
00245 return 1;
00246
00247 if (listptr) *listptr = fsnames;
00248 if (num) *num = numFilesystems;
00249
00250 return 0;
00251 }
00252
00253 int rpmGetFilesystemUsage(const char ** fileList, int_32 * fssizes, int numFiles,
00254 uint_32 ** usagesPtr, int flags)
00255 {
00256 int_32 * usages;
00257 int i, len, j;
00258 char * buf, * dirName;
00259 char * chptr;
00260 int maxLen;
00261 char * lastDir;
00262 const char * sourceDir;
00263 int lastfs = 0;
00264 int lastDev = -1;
00265 struct stat sb;
00266
00267 if (!fsnames)
00268 if (getFilesystemList())
00269 return 1;
00270
00271 usages = xcalloc(numFilesystems, sizeof(usages));
00272
00273 sourceDir = rpmGetPath("%{_sourcedir}", NULL);
00274
00275 maxLen = strlen(sourceDir);
00276 for (i = 0; i < numFiles; i++) {
00277 len = strlen(fileList[i]);
00278 if (maxLen < len) maxLen = len;
00279 }
00280
00281 buf = alloca(maxLen + 1);
00282 lastDir = alloca(maxLen + 1);
00283 dirName = alloca(maxLen + 1);
00284 *lastDir = '\0';
00285
00286
00287 for (i = 0; i < numFiles; i++) {
00288 if (*fileList[i] == '/') {
00289 strcpy(buf, fileList[i]);
00290 chptr = buf + strlen(buf) - 1;
00291 while (*chptr != '/') chptr--;
00292 if (chptr == buf)
00293 buf[1] = '\0';
00294 else
00295 *chptr-- = '\0';
00296 } else {
00297
00298 strcpy(buf, sourceDir);
00299 }
00300
00301 if (strcmp(lastDir, buf)) {
00302 strcpy(dirName, buf);
00303 chptr = dirName + strlen(dirName) - 1;
00304 while (stat(dirName, &sb)) {
00305 if (errno != ENOENT) {
00306 rpmError(RPMERR_STAT, _("failed to stat %s: %s\n"), buf,
00307 strerror(errno));
00308 sourceDir = _free(sourceDir);
00309 usages = _free(usages);
00310 return 1;
00311 }
00312
00313
00314 while (*chptr != '/') chptr--;
00315
00316 if (chptr == dirName)
00317 dirName[1] = '\0';
00318 else
00319 *chptr-- = '\0';
00320 }
00321
00322 if (lastDev != sb.st_dev) {
00323 for (j = 0; j < numFilesystems; j++)
00324 if (filesystems && filesystems[j].dev == sb.st_dev)
00325 break;
00326
00327 if (j == numFilesystems) {
00328 rpmError(RPMERR_BADDEV,
00329 _("file %s is on an unknown device\n"), buf);
00330 sourceDir = _free(sourceDir);
00331 usages = _free(usages);
00332 return 1;
00333 }
00334
00335 lastfs = j;
00336 lastDev = sb.st_dev;
00337 }
00338 }
00339
00340 strcpy(lastDir, buf);
00341 usages[lastfs] += fssizes[i];
00342 }
00343
00344 sourceDir = _free(sourceDir);
00345
00346
00347 if (usagesPtr)
00348 *usagesPtr = usages;
00349 else
00350 usages = _free(usages);
00351
00352
00353 return 0;
00354 }
00355
00356