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 rpmError(RPMERR_STAT, _("failed to stat %s: %s\n"), mntdir,
00220 strerror(errno));
00221
00222 freeFilesystems();
00223 return 1;
00224 }
00225
00226 if ((numFilesystems + 2) == numAlloced) {
00227 numAlloced += 10;
00228 filesystems = xrealloc(filesystems,
00229 sizeof(*filesystems) * (numAlloced + 1));
00230 }
00231
00232 filesystems[numFilesystems].dev = sb.st_dev;
00233 filesystems[numFilesystems].mntPoint = xstrdup(mntdir);
00234 filesystems[numFilesystems].rdonly = rdonly;
00235 #if 0
00236 rpmMessage(RPMMESS_DEBUG, _("%5d 0x%04x %s %s\n"),
00237 numFilesystems,
00238 (unsigned) filesystems[numFilesystems].dev,
00239 (filesystems[numFilesystems].rdonly ? "ro" : "rw"),
00240 filesystems[numFilesystems].mntPoint);
00241 #endif
00242 numFilesystems++;
00243 }
00244
00245 # if GETMNTENT_ONE || GETMNTENT_TWO
00246 (void) fclose(mtab);
00247 # elif HAVE_GETMNTINFO_R
00248 mounts = _free(mounts);
00249 # endif
00250
00251 filesystems[numFilesystems].dev = 0;
00252 filesystems[numFilesystems].mntPoint = NULL;
00253 filesystems[numFilesystems].rdonly = 0;
00254
00255
00256 fsnames = xcalloc((numFilesystems + 1), sizeof(*fsnames));
00257 for (i = 0; i < numFilesystems; i++)
00258 fsnames[i] = filesystems[i].mntPoint;
00259 fsnames[numFilesystems] = NULL;
00260
00261
00262
00263 return 0;
00264
00265 }
00266 #endif
00267
00268 int rpmGetFilesystemList(const char *** listptr, int * num)
00269 {
00270 if (!fsnames)
00271 if (getFilesystemList())
00272 return 1;
00273
00274
00275 if (listptr) *listptr = fsnames;
00276 if (num) *num = numFilesystems;
00277
00278
00279 return 0;
00280 }
00281
00282 int rpmGetFilesystemUsage(const char ** fileList, int_32 * fssizes, int numFiles,
00283 uint_32 ** usagesPtr, int flags)
00284 {
00285 int_32 * usages;
00286 int i, len, j;
00287 char * buf, * dirName;
00288 char * chptr;
00289 int maxLen;
00290 char * lastDir;
00291 const char * sourceDir;
00292 int lastfs = 0;
00293 int lastDev = -1;
00294 struct stat sb;
00295
00296 if (!fsnames)
00297 if (getFilesystemList())
00298 return 1;
00299
00300 usages = xcalloc(numFilesystems, sizeof(usages));
00301
00302 sourceDir = rpmGetPath("%{_sourcedir}", NULL);
00303
00304 maxLen = strlen(sourceDir);
00305
00306 for (i = 0; i < numFiles; i++) {
00307 len = strlen(fileList[i]);
00308 if (maxLen < len) maxLen = len;
00309 }
00310
00311
00312
00313 buf = alloca(maxLen + 1);
00314 lastDir = alloca(maxLen + 1);
00315 dirName = alloca(maxLen + 1);
00316 *lastDir = '\0';
00317
00318
00319 for (i = 0; i < numFiles; i++) {
00320 if (*fileList[i] == '/') {
00321 strcpy(buf, fileList[i]);
00322 chptr = buf + strlen(buf) - 1;
00323 while (*chptr != '/') chptr--;
00324 if (chptr == buf)
00325 buf[1] = '\0';
00326 else
00327 *chptr-- = '\0';
00328 } else {
00329
00330 strcpy(buf, sourceDir);
00331 }
00332
00333 if (strcmp(lastDir, buf)) {
00334 strcpy(dirName, buf);
00335 chptr = dirName + strlen(dirName) - 1;
00336 while (stat(dirName, &sb)) {
00337 if (errno != ENOENT) {
00338 rpmError(RPMERR_STAT, _("failed to stat %s: %s\n"), buf,
00339 strerror(errno));
00340 sourceDir = _free(sourceDir);
00341 usages = _free(usages);
00342 return 1;
00343 }
00344
00345
00346 while (*chptr != '/') chptr--;
00347
00348 if (chptr == dirName)
00349 dirName[1] = '\0';
00350 else
00351 *chptr-- = '\0';
00352 }
00353
00354 if (lastDev != sb.st_dev) {
00355 for (j = 0; j < numFilesystems; j++)
00356 if (filesystems && filesystems[j].dev == sb.st_dev)
00357 break;
00358
00359 if (j == numFilesystems) {
00360 rpmError(RPMERR_BADDEV,
00361 _("file %s is on an unknown device\n"), buf);
00362 sourceDir = _free(sourceDir);
00363 usages = _free(usages);
00364 return 1;
00365 }
00366
00367 lastfs = j;
00368 lastDev = sb.st_dev;
00369 }
00370 }
00371
00372 strcpy(lastDir, buf);
00373 usages[lastfs] += fssizes[i];
00374 }
00375
00376
00377 sourceDir = _free(sourceDir);
00378
00379
00380
00381 if (usagesPtr)
00382 *usagesPtr = usages;
00383 else
00384 usages = _free(usages);
00385
00386
00387
00388 return 0;
00389 }
00390