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