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 int i;
00029
00030
00031 if (filesystems)
00032 for (i = 0; i < numFilesystems; i++)
00033 filesystems[i].mntPoint = _free(filesystems[i].mntPoint);
00034
00035
00036 filesystems = _free(filesystems);
00037 fsnames = _free(fsnames);
00038 numFilesystems = 0;
00039 }
00040
00041 #if HAVE_MNTCTL
00042
00043
00044
00045 #include <sys/mntctl.h>
00046 #include <sys/vmount.h>
00047
00048
00049
00050
00051
00052 int mntctl(int command, int size, char *buffer);
00053
00059 static int getFilesystemList(void)
00060
00061 {
00062 int size;
00063 void * buf;
00064 struct vmount * vm;
00065 struct stat sb;
00066 int rdonly = 0;
00067 int num;
00068 int fsnameLength;
00069 int i;
00070
00071 num = mntctl(MCTL_QUERY, sizeof(size), (char *) &size);
00072 if (num < 0) {
00073 rpmError(RPMERR_MTAB, _("mntctl() failed to return size: %s\n"),
00074 strerror(errno));
00075 return 1;
00076 }
00077
00078
00079
00080
00081
00082
00083 size *= 2;
00084
00085 buf = alloca(size);
00086 num = mntctl(MCTL_QUERY, size, buf);
00087 if ( num <= 0 ) {
00088 rpmError(RPMERR_MTAB, _("mntctl() failed to return mount points: %s\n"),
00089 strerror(errno));
00090 return 1;
00091 }
00092
00093 numFilesystems = num;
00094
00095 filesystems = xcalloc((numFilesystems + 1), sizeof(*filesystems));
00096 fsnames = xcalloc((numFilesystems + 1), sizeof(char *));
00097
00098 for (vm = buf, i = 0; i < num; i++) {
00099 char *fsn;
00100 fsnameLength = vm->vmt_data[VMT_STUB].vmt_size;
00101 fsn = xmalloc(fsnameLength + 1);
00102 strncpy(fsn, (char *)vm + vm->vmt_data[VMT_STUB].vmt_off,
00103 fsnameLength);
00104
00105 filesystems[i].mntPoint = fsnames[i] = fsn;
00106
00107 if (stat(filesystems[i].mntPoint, &sb)) {
00108 rpmError(RPMERR_STAT, _("failed to stat %s: %s\n"), fsnames[i],
00109 strerror(errno));
00110
00111 freeFilesystems();
00112 return 1;
00113 }
00114
00115 filesystems[i].dev = sb.st_dev;
00116 filesystems[i].rdonly = rdonly;
00117
00118
00119 vm = (struct vmount *)((char *)vm + vm->vmt_length);
00120 }
00121
00122 filesystems[i].mntPoint = NULL;
00123 fsnames[i] = NULL;
00124
00125 return 0;
00126 }
00127
00128 #else
00129
00135 static int getFilesystemList(void)
00136
00137
00138 {
00139 int numAlloced = 10;
00140 struct stat sb;
00141 int i;
00142 const char * mntdir;
00143 int rdonly = 0;
00144
00145 # if GETMNTENT_ONE || GETMNTENT_TWO
00146 our_mntent item;
00147 FILE * mtab;
00148
00149 mtab = fopen(MOUNTED, "r");
00150 if (!mtab) {
00151 rpmError(RPMERR_MTAB, _("failed to open %s: %s\n"), MOUNTED,
00152 strerror(errno));
00153 return 1;
00154 }
00155 # elif HAVE_GETMNTINFO_R
00156 struct statfs * mounts = NULL;
00157 int mntCount = 0, bufSize = 0, flags = MNT_NOWAIT;
00158 int nextMount = 0;
00159
00160 getmntinfo_r(&mounts, flags, &mntCount, &bufSize);
00161 # endif
00162
00163 filesystems = xcalloc((numAlloced + 1), sizeof(*filesystems));
00164
00165 numFilesystems = 0;
00166 while (1) {
00167 # if GETMNTENT_ONE
00168
00169
00170 our_mntent * itemptr = getmntent(mtab);
00171 if (!itemptr) break;
00172
00173 item = *itemptr;
00174
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
00223 fsnames = xcalloc((numFilesystems + 1), sizeof(*fsnames));
00224 for (i = 0; i < numFilesystems; i++)
00225 fsnames[i] = filesystems[i].mntPoint;
00226 fsnames[numFilesystems] = NULL;
00227
00228
00229 return 0;
00230 }
00231 #endif
00232
00233 int rpmGetFilesystemList(const char *** listptr, int * num)
00234 {
00235 if (!fsnames)
00236 if (getFilesystemList())
00237 return 1;
00238
00239
00240 if (listptr) *listptr = fsnames;
00241 if (num) *num = numFilesystems;
00242
00243
00244 return 0;
00245 }
00246
00247 int rpmGetFilesystemUsage(const char ** fileList, int_32 * fssizes, int numFiles,
00248 uint_32 ** usagesPtr, int flags)
00249 {
00250 int_32 * usages;
00251 int i, len, j;
00252 char * buf, * dirName;
00253 char * chptr;
00254 int maxLen;
00255 char * lastDir;
00256 const char * sourceDir;
00257 int lastfs = 0;
00258 int lastDev = -1;
00259 struct stat sb;
00260
00261 if (!fsnames)
00262 if (getFilesystemList())
00263 return 1;
00264
00265 usages = xcalloc(numFilesystems, sizeof(usages));
00266
00267 sourceDir = rpmGetPath("%{_sourcedir}", NULL);
00268
00269 maxLen = strlen(sourceDir);
00270
00271 for (i = 0; i < numFiles; i++) {
00272 len = strlen(fileList[i]);
00273 if (maxLen < len) maxLen = len;
00274 }
00275
00276
00277
00278 buf = alloca(maxLen + 1);
00279 lastDir = alloca(maxLen + 1);
00280 dirName = alloca(maxLen + 1);
00281 *lastDir = '\0';
00282
00283
00284 for (i = 0; i < numFiles; i++) {
00285 if (*fileList[i] == '/') {
00286 strcpy(buf, fileList[i]);
00287 chptr = buf + strlen(buf) - 1;
00288 while (*chptr != '/') chptr--;
00289 if (chptr == buf)
00290 buf[1] = '\0';
00291 else
00292 *chptr-- = '\0';
00293 } else {
00294
00295 strcpy(buf, sourceDir);
00296 }
00297
00298 if (strcmp(lastDir, buf)) {
00299 strcpy(dirName, buf);
00300 chptr = dirName + strlen(dirName) - 1;
00301 while (stat(dirName, &sb)) {
00302 if (errno != ENOENT) {
00303 rpmError(RPMERR_STAT, _("failed to stat %s: %s\n"), buf,
00304 strerror(errno));
00305 sourceDir = _free(sourceDir);
00306 usages = _free(usages);
00307 return 1;
00308 }
00309
00310
00311 while (*chptr != '/') chptr--;
00312
00313 if (chptr == dirName)
00314 dirName[1] = '\0';
00315 else
00316 *chptr-- = '\0';
00317 }
00318
00319 if (lastDev != sb.st_dev) {
00320 for (j = 0; j < numFilesystems; j++)
00321 if (filesystems && filesystems[j].dev == sb.st_dev)
00322 break;
00323
00324 if (j == numFilesystems) {
00325 rpmError(RPMERR_BADDEV,
00326 _("file %s is on an unknown device\n"), buf);
00327 sourceDir = _free(sourceDir);
00328 usages = _free(usages);
00329 return 1;
00330 }
00331
00332 lastfs = j;
00333 lastDev = sb.st_dev;
00334 }
00335 }
00336
00337 strcpy(lastDir, buf);
00338 usages[lastfs] += fssizes[i];
00339 }
00340
00341
00342 sourceDir = _free(sourceDir);
00343
00344
00345
00346 if (usagesPtr)
00347 *usagesPtr = usages;
00348 else
00349 usages = _free(usages);
00350
00351
00352
00353 return 0;
00354 }
00355
00356