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