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 rpmError(RPMERR_STAT, _("failed to stat %s: %s\n"), fsnames[i],
00113 strerror(errno));
00114
00115 freeFilesystems();
00116 return 1;
00117 }
00118
00119 filesystems[i].dev = sb.st_dev;
00120 filesystems[i].rdonly = rdonly;
00121
00122
00123 vm = (struct vmount *)((char *)vm + vm->vmt_length);
00124 }
00125
00126 filesystems[i].mntPoint = NULL;
00127 fsnames[i] = NULL;
00128
00129 return 0;
00130 }
00131
00132 #else
00133
00139 static int getFilesystemList(void)
00140
00141
00142
00143
00144 {
00145 int numAlloced = 10;
00146 struct stat sb;
00147 int i;
00148 const char * mntdir;
00149 int rdonly = 0;
00150
00151 # if GETMNTENT_ONE || GETMNTENT_TWO
00152 our_mntent item;
00153 FILE * mtab;
00154
00155 mtab = fopen(MOUNTED, "r");
00156 if (!mtab) {
00157 rpmError(RPMERR_MTAB, _("failed to open %s: %s\n"), MOUNTED,
00158 strerror(errno));
00159 return 1;
00160 }
00161 # elif HAVE_GETMNTINFO_R
00162
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 # elif HAVE_GETMNTINFO
00169
00170 struct statfs * mounts = NULL;
00171 int mntCount = 0, flags = MNT_NOWAIT;
00172 int nextMount = 0;
00173
00174
00175 mntCount = getmntinfo(&mounts, flags);
00176 # endif
00177
00178 filesystems = xcalloc((numAlloced + 1), sizeof(*filesystems));
00179
00180 numFilesystems = 0;
00181 while (1) {
00182 # if GETMNTENT_ONE
00183
00184
00185 our_mntent * itemptr = getmntent(mtab);
00186 if (!itemptr) break;
00187
00188 item = *itemptr;
00189
00190 mntdir = item.our_mntdir;
00191 #if defined(MNTOPT_RO)
00192
00193 if (hasmntopt(itemptr, MNTOPT_RO) != NULL)
00194 rdonly = 1;
00195
00196 #endif
00197
00198 # elif GETMNTENT_TWO
00199
00200 if (getmntent(mtab, &item)) break;
00201 mntdir = item.our_mntdir;
00202 # elif HAVE_GETMNTINFO_R
00203
00204 if (nextMount == mntCount) break;
00205 mntdir = mounts[nextMount++].f_mntonname;
00206 # elif HAVE_GETMNTINFO
00207
00208 if (nextMount == mntCount) break;
00209 mntdir = mounts[nextMount++].f_mntonname;
00210 # endif
00211
00212 if (stat(mntdir, &sb)) {
00213 rpmError(RPMERR_STAT, _("failed to stat %s: %s\n"), mntdir,
00214 strerror(errno));
00215
00216 freeFilesystems();
00217 return 1;
00218 }
00219
00220 if ((numFilesystems + 2) == numAlloced) {
00221 numAlloced += 10;
00222 filesystems = xrealloc(filesystems,
00223 sizeof(*filesystems) * (numAlloced + 1));
00224 }
00225
00226 filesystems[numFilesystems].dev = sb.st_dev;
00227 filesystems[numFilesystems].mntPoint = xstrdup(mntdir);
00228 filesystems[numFilesystems].rdonly = rdonly;
00229 #if 0
00230 rpmMessage(RPMMESS_DEBUG, _("%5d 0x%04x %s %s\n"),
00231 numFilesystems,
00232 (unsigned) filesystems[numFilesystems].dev,
00233 (filesystems[numFilesystems].rdonly ? "ro" : "rw"),
00234 filesystems[numFilesystems].mntPoint);
00235 #endif
00236 numFilesystems++;
00237 }
00238
00239 # if GETMNTENT_ONE || GETMNTENT_TWO
00240 (void) fclose(mtab);
00241 # elif HAVE_GETMNTINFO_R
00242 mounts = _free(mounts);
00243 # endif
00244
00245 filesystems[numFilesystems].dev = 0;
00246 filesystems[numFilesystems].mntPoint = NULL;
00247 filesystems[numFilesystems].rdonly = 0;
00248
00249
00250 fsnames = xcalloc((numFilesystems + 1), sizeof(*fsnames));
00251 for (i = 0; i < numFilesystems; i++)
00252 fsnames[i] = filesystems[i].mntPoint;
00253 fsnames[numFilesystems] = NULL;
00254
00255
00256
00257 return 0;
00258
00259 }
00260 #endif
00261
00262 int rpmGetFilesystemList(const char *** listptr, int * num)
00263 {
00264 if (!fsnames)
00265 if (getFilesystemList())
00266 return 1;
00267
00268
00269 if (listptr) *listptr = fsnames;
00270 if (num) *num = numFilesystems;
00271
00272
00273 return 0;
00274 }
00275
00276 int rpmGetFilesystemUsage(const char ** fileList, int_32 * fssizes, int numFiles,
00277 uint_32 ** usagesPtr, int flags)
00278 {
00279 int_32 * usages;
00280 int i, len, j;
00281 char * buf, * dirName;
00282 char * chptr;
00283 int maxLen;
00284 char * lastDir;
00285 const char * sourceDir;
00286 int lastfs = 0;
00287 int lastDev = -1;
00288 struct stat sb;
00289
00290 if (!fsnames)
00291 if (getFilesystemList())
00292 return 1;
00293
00294 usages = xcalloc(numFilesystems, sizeof(usages));
00295
00296 sourceDir = rpmGetPath("%{_sourcedir}", NULL);
00297
00298 maxLen = strlen(sourceDir);
00299
00300 for (i = 0; i < numFiles; i++) {
00301 len = strlen(fileList[i]);
00302 if (maxLen < len) maxLen = len;
00303 }
00304
00305
00306
00307 buf = alloca(maxLen + 1);
00308 lastDir = alloca(maxLen + 1);
00309 dirName = alloca(maxLen + 1);
00310 *lastDir = '\0';
00311
00312
00313 for (i = 0; i < numFiles; i++) {
00314 if (*fileList[i] == '/') {
00315 strcpy(buf, fileList[i]);
00316 chptr = buf + strlen(buf) - 1;
00317 while (*chptr != '/') chptr--;
00318 if (chptr == buf)
00319 buf[1] = '\0';
00320 else
00321 *chptr-- = '\0';
00322 } else {
00323
00324 strcpy(buf, sourceDir);
00325 }
00326
00327 if (strcmp(lastDir, buf)) {
00328 strcpy(dirName, buf);
00329 chptr = dirName + strlen(dirName) - 1;
00330 while (stat(dirName, &sb)) {
00331 if (errno != ENOENT) {
00332 rpmError(RPMERR_STAT, _("failed to stat %s: %s\n"), buf,
00333 strerror(errno));
00334 sourceDir = _free(sourceDir);
00335 usages = _free(usages);
00336 return 1;
00337 }
00338
00339
00340 while (*chptr != '/') chptr--;
00341
00342 if (chptr == dirName)
00343 dirName[1] = '\0';
00344 else
00345 *chptr-- = '\0';
00346 }
00347
00348 if (lastDev != sb.st_dev) {
00349 for (j = 0; j < numFilesystems; j++)
00350 if (filesystems && filesystems[j].dev == sb.st_dev)
00351 break;
00352
00353 if (j == numFilesystems) {
00354 rpmError(RPMERR_BADDEV,
00355 _("file %s is on an unknown device\n"), buf);
00356 sourceDir = _free(sourceDir);
00357 usages = _free(usages);
00358 return 1;
00359 }
00360
00361 lastfs = j;
00362 lastDev = sb.st_dev;
00363 }
00364 }
00365
00366 strcpy(lastDir, buf);
00367 usages[lastfs] += fssizes[i];
00368 }
00369
00370
00371 sourceDir = _free(sourceDir);
00372
00373
00374
00375 if (usagesPtr)
00376 *usagesPtr = usages;
00377 else
00378 usages = _free(usages);
00379
00380
00381
00382 return 0;
00383 }
00384