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