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