1998-07-26 05:00:26 +08:00
|
|
|
#include "system.h"
|
1997-05-31 05:57:31 +08:00
|
|
|
|
|
|
|
#include "rpmlib.h"
|
|
|
|
|
|
|
|
struct fsinfo {
|
|
|
|
char * mntPoint;
|
|
|
|
dev_t dev;
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct fsinfo * filesystems;
|
|
|
|
static char ** fsnames;
|
|
|
|
static int numFilesystems;
|
|
|
|
|
|
|
|
static int getFilesystemList(void);
|
|
|
|
|
1997-06-17 22:49:07 +08:00
|
|
|
#if HAVE_MNTCTL
|
|
|
|
|
|
|
|
/* modeled after sample code from Till Bubeck */
|
|
|
|
|
|
|
|
#include <sys/mntctl.h>
|
|
|
|
#include <sys/vmount.h>
|
|
|
|
|
1997-06-19 21:13:50 +08:00
|
|
|
/*
|
|
|
|
* There is NO mntctl prototype in any header file of AIX 3.2.5!
|
|
|
|
* So we have to declare it by ourself...
|
|
|
|
*/
|
|
|
|
int mntctl(int command, int size, char *buffer);
|
|
|
|
|
1997-06-17 22:49:07 +08:00
|
|
|
static int getFilesystemList(void) {
|
|
|
|
int size;
|
|
|
|
void * buf;
|
|
|
|
struct vmount * vm;
|
1997-06-19 21:13:50 +08:00
|
|
|
struct stat sb;
|
1997-06-17 22:49:07 +08:00
|
|
|
int num;
|
|
|
|
int fsnameLength;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
num = mntctl(MCTL_QUERY, sizeof(size), (char *) &size);
|
|
|
|
if (num < 0) {
|
|
|
|
rpmError(RPMERR_MTAB, _("mntctl() failed to return fugger size: %s"),
|
|
|
|
strerror(errno));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
1997-06-19 21:13:50 +08:00
|
|
|
/*
|
|
|
|
* Double the needed size, so that even when the user mounts a
|
|
|
|
* filesystem between the previous and the next call to mntctl
|
|
|
|
* the buffer still is large enough.
|
|
|
|
*/
|
|
|
|
size *= 2;
|
|
|
|
|
1997-06-17 22:49:07 +08:00
|
|
|
buf = alloca(size);
|
|
|
|
num = mntctl(MCTL_QUERY, size, buf);
|
1997-06-19 21:13:50 +08:00
|
|
|
if ( num <= 0 ) {
|
|
|
|
rpmError(RPMERR_MTAB, "mntctl() failed to return mount points: %s",
|
|
|
|
strerror(errno));
|
|
|
|
return 1;
|
|
|
|
}
|
1997-06-17 22:49:07 +08:00
|
|
|
|
|
|
|
numFilesystems = num;
|
|
|
|
|
1997-06-19 21:17:56 +08:00
|
|
|
filesystems = malloc(sizeof(*filesystems) * (numFilesystems + 1));
|
|
|
|
fsnames = malloc(sizeof(char *) * (numFilesystems + 1));
|
1997-06-17 22:49:07 +08:00
|
|
|
|
|
|
|
for (vm = buf, i = 0; i < num; i++) {
|
|
|
|
fsnameLength = vm->vmt_data[VMT_STUB].vmt_size;
|
|
|
|
fsnames[i] = malloc(fsnameLength + 1);
|
|
|
|
strncpy(fsnames[i],(char *)vm + vm->vmt_data[VMT_STUB].vmt_off,
|
1997-06-19 21:13:50 +08:00
|
|
|
fsnameLength);
|
1997-06-17 22:49:07 +08:00
|
|
|
|
|
|
|
filesystems[i].mntPoint = fsnames[i];
|
1997-06-19 21:13:50 +08:00
|
|
|
|
|
|
|
if (stat(filesystems[i].mntPoint, &sb)) {
|
1998-09-28 06:03:52 +08:00
|
|
|
rpmError(RPMERR_STAT, _("failed to stat %s: %s"), fsnames[i],
|
1997-06-17 22:49:07 +08:00
|
|
|
strerror(errno));
|
|
|
|
|
|
|
|
for (i = 0; i < num; i++)
|
|
|
|
free(filesystems[i].mntPoint);
|
|
|
|
free(filesystems);
|
1997-06-19 21:13:50 +08:00
|
|
|
free(fsnames);
|
1997-06-17 22:49:07 +08:00
|
|
|
|
|
|
|
filesystems = NULL;
|
|
|
|
}
|
|
|
|
|
1997-06-19 21:13:50 +08:00
|
|
|
filesystems[i].dev = sb.st_dev;
|
1997-06-17 22:49:07 +08:00
|
|
|
|
|
|
|
/* goto the next vmount structure: */
|
|
|
|
vm = (struct vmount *)((char *)vm + vm->vmt_length);
|
|
|
|
}
|
|
|
|
|
1997-06-19 21:13:50 +08:00
|
|
|
filesystems[i].mntPoint = NULL;
|
|
|
|
fsnames[i] = NULL;
|
|
|
|
|
1997-06-17 22:49:07 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#else
|
1997-05-31 05:57:31 +08:00
|
|
|
static int getFilesystemList(void) {
|
|
|
|
int numAlloced = 10;
|
|
|
|
int num = 0;
|
|
|
|
struct stat sb;
|
|
|
|
int i;
|
1997-06-20 06:18:02 +08:00
|
|
|
char * mntdir;
|
1998-03-05 00:52:59 +08:00
|
|
|
# if GETMNTENT_ONE || GETMNTENT_TWO
|
1997-06-20 06:18:02 +08:00
|
|
|
our_mntent item, * itemptr;
|
|
|
|
FILE * mtab;
|
1998-03-05 00:52:59 +08:00
|
|
|
# elif HAVE_GETMNTINFO_R
|
1997-06-20 06:18:02 +08:00
|
|
|
struct statfs * mounts = NULL;
|
|
|
|
int mntCount = 0, bufSize = 0, flags = MNT_NOWAIT;
|
|
|
|
int nextMount = 0;
|
1998-03-05 00:52:59 +08:00
|
|
|
# endif
|
1997-06-20 06:18:02 +08:00
|
|
|
|
1998-03-05 00:52:59 +08:00
|
|
|
# if GETMNTENT_ONE || GETMNTENT_TWO
|
1997-06-20 06:18:02 +08:00
|
|
|
mtab = fopen(MOUNTED, "r");
|
|
|
|
if (!mtab) {
|
|
|
|
rpmError(RPMERR_MTAB, _("failed to open %s: %s"), MOUNTED,
|
|
|
|
strerror(errno));
|
|
|
|
return 1;
|
|
|
|
}
|
1998-03-05 00:52:59 +08:00
|
|
|
# elif HAVE_GETMNTINFO_R
|
1997-06-20 06:18:02 +08:00
|
|
|
getmntinfo_r(&mounts, flags, &mntCount, &bufSize);
|
1998-03-05 00:52:59 +08:00
|
|
|
# endif
|
1997-05-31 05:57:31 +08:00
|
|
|
|
|
|
|
filesystems = malloc(sizeof(*filesystems) * (numAlloced + 1));
|
|
|
|
|
|
|
|
while (1) {
|
1998-03-05 00:52:59 +08:00
|
|
|
# if GETMNTENT_ONE
|
1997-05-31 05:57:31 +08:00
|
|
|
/* this is Linux */
|
|
|
|
itemptr = getmntent(mtab);
|
|
|
|
if (!itemptr) break;
|
|
|
|
item = *itemptr;
|
1997-06-20 06:18:02 +08:00
|
|
|
mntdir = item.our_mntdir;
|
1998-03-05 00:52:59 +08:00
|
|
|
# elif GETMNTENT_TWO
|
1997-05-31 05:57:31 +08:00
|
|
|
/* Solaris, maybe others */
|
|
|
|
if (getmntent(mtab, &item)) break;
|
1997-06-20 06:18:02 +08:00
|
|
|
mntdir = item.our_mntdir;
|
1998-03-05 00:52:59 +08:00
|
|
|
# elif HAVE_GETMNTINFO_R
|
1997-06-20 06:18:02 +08:00
|
|
|
if (nextMount == mntCount) break;
|
|
|
|
mntdir = mounts[nextMount++].f_mntonname;
|
1998-03-05 00:52:59 +08:00
|
|
|
# endif
|
1997-05-31 05:57:31 +08:00
|
|
|
|
1997-06-20 06:18:02 +08:00
|
|
|
if (stat(mntdir, &sb)) {
|
|
|
|
rpmError(RPMERR_STAT, "failed to stat %s: %s", mntdir,
|
1997-05-31 05:57:31 +08:00
|
|
|
strerror(errno));
|
|
|
|
|
|
|
|
for (i = 0; i < num; i++)
|
|
|
|
free(filesystems[i].mntPoint);
|
|
|
|
free(filesystems);
|
|
|
|
|
|
|
|
filesystems = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (num == numAlloced) {
|
|
|
|
numAlloced += 10;
|
|
|
|
filesystems = realloc(filesystems,
|
|
|
|
sizeof(*filesystems) * (numAlloced + 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
filesystems[num].dev = sb.st_dev;
|
1997-06-20 06:18:02 +08:00
|
|
|
filesystems[num++].mntPoint = strdup(mntdir);
|
1997-05-31 05:57:31 +08:00
|
|
|
}
|
|
|
|
|
1998-03-05 00:52:59 +08:00
|
|
|
# if GETMNTENT_ONE || GETMNTENT_TWO
|
1997-06-20 06:18:02 +08:00
|
|
|
fclose(mtab);
|
1998-03-05 00:52:59 +08:00
|
|
|
# elif HAVE_GETMNTINFO_R
|
1997-06-20 06:18:02 +08:00
|
|
|
free(mounts);
|
1998-03-05 00:52:59 +08:00
|
|
|
# endif
|
1997-06-20 06:18:02 +08:00
|
|
|
|
1997-05-31 05:57:31 +08:00
|
|
|
filesystems[num].mntPoint = NULL;
|
|
|
|
|
|
|
|
fsnames = malloc(sizeof(*fsnames) * (num + 1));
|
|
|
|
for (i = 0; i < num; i++)
|
|
|
|
fsnames[i] = filesystems[i].mntPoint;
|
|
|
|
fsnames[num] = NULL;
|
|
|
|
|
|
|
|
numFilesystems = num;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
1997-06-17 22:49:07 +08:00
|
|
|
#endif
|
1997-05-31 05:57:31 +08:00
|
|
|
|
1997-08-21 09:20:16 +08:00
|
|
|
int rpmGetFilesystemList(char *** listptr, int * num) {
|
1997-05-31 05:57:31 +08:00
|
|
|
if (!fsnames)
|
|
|
|
if (getFilesystemList())
|
|
|
|
return 1;
|
|
|
|
|
1997-08-21 09:20:16 +08:00
|
|
|
if (listptr) *listptr = fsnames;
|
|
|
|
if (num) *num = numFilesystems;
|
|
|
|
|
1997-05-31 05:57:31 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int rpmGetFilesystemUsage(char ** fileList, int_32 * fssizes, int numFiles,
|
|
|
|
uint_32 ** usagesPtr, int flags) {
|
|
|
|
int_32 * usages;
|
|
|
|
int i, len, j;
|
|
|
|
char * buf, * dirName;
|
|
|
|
char * chptr;
|
|
|
|
int maxLen;
|
|
|
|
char * lastDir;
|
|
|
|
int lastfs = 0;
|
|
|
|
int lastDev = -1; /* I hope nobody uses -1 for a st_dev */
|
|
|
|
struct stat sb;
|
|
|
|
|
|
|
|
if (!fsnames)
|
|
|
|
if (getFilesystemList())
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
usages = calloc(numFilesystems, sizeof(usages));
|
|
|
|
|
|
|
|
maxLen = 0;
|
|
|
|
for (i = 0; i < numFiles; i++) {
|
|
|
|
len = strlen(fileList[i]);
|
|
|
|
if (maxLen < len) maxLen = len;
|
|
|
|
}
|
|
|
|
|
|
|
|
buf = alloca(maxLen + 1);
|
|
|
|
lastDir = alloca(maxLen + 1);
|
|
|
|
dirName = alloca(maxLen + 1);
|
|
|
|
*lastDir = '\0';
|
|
|
|
|
1998-04-03 01:48:34 +08:00
|
|
|
/* cut off last filename */
|
1997-05-31 05:57:31 +08:00
|
|
|
for (i = 0; i < numFiles; i++) {
|
|
|
|
strcpy(buf, fileList[i]);
|
|
|
|
chptr = buf + strlen(buf) - 1;
|
|
|
|
while (*chptr != '/') chptr--;
|
|
|
|
if (chptr == buf)
|
|
|
|
buf[1] = '\0';
|
|
|
|
else
|
|
|
|
*chptr-- = '\0';
|
|
|
|
|
|
|
|
if (strcmp(lastDir, buf)) {
|
|
|
|
strcpy(dirName, buf);
|
|
|
|
chptr = dirName + strlen(dirName) - 1;
|
|
|
|
while (stat(dirName, &sb)) {
|
|
|
|
if (errno != ENOENT) {
|
1998-09-28 06:03:52 +08:00
|
|
|
rpmError(RPMERR_STAT, _("failed to stat %s: %s"), buf,
|
1997-05-31 05:57:31 +08:00
|
|
|
strerror(errno));
|
|
|
|
free(usages);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
1998-04-03 01:48:34 +08:00
|
|
|
/* cut off last directory part, because it was not found. */
|
1997-05-31 05:57:31 +08:00
|
|
|
while (*chptr != '/') chptr--;
|
1998-04-03 01:48:34 +08:00
|
|
|
|
|
|
|
if (chptr == dirName)
|
|
|
|
dirName[1] = '\0';
|
|
|
|
else
|
|
|
|
*chptr-- = '\0';
|
1997-05-31 05:57:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (lastDev != sb.st_dev) {
|
|
|
|
for (j = 0; j < numFilesystems; j++)
|
|
|
|
if (filesystems[j].dev == sb.st_dev) break;
|
|
|
|
|
|
|
|
if (j == numFilesystems) {
|
|
|
|
rpmError(RPMERR_BADDEV,
|
1998-09-28 06:03:52 +08:00
|
|
|
_("file %s is on an unknown device"), buf);
|
1997-05-31 05:57:31 +08:00
|
|
|
free(usages);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
lastfs = j;
|
|
|
|
lastDev = sb.st_dev;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
strcpy(lastDir, buf);
|
|
|
|
usages[lastfs] += fssizes[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
*usagesPtr = usages;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|