#include<stdio.h>
#include<mntent.h>
#include<sys/vfs.h>
#include<error.h>
#include<sys/types.h>
#include<stdlib.h>
#include<string.h>
#define Gsize (1024.00*1024.00*1024.00)
#define Msize (1024.00*1024.00)
#ifndef EXT2_SUPER_MAGIC
#define EXT2_SUPER_MAGIC 0xef53
#endif
#define MOUNTED "/etc/mtab"
#ifndef ME_DUMMY
#define ME_DUMMY(Fs_name, Fs_type) (!strcmp (Fs_type, "autofs") /* for Irix 6.5 */ || !strcmp (Fs_type, "ignore"))
#endif
#undef STREQ
#define STREQ(a, b) (strcmp ((a), (b)) == 0)
#ifndef ME_REMOTE
/* A file system is `remote' if its Fs_name contains a `:'
or if (it is of type smbfs and its Fs_name starts with `//'). */
# define ME_REMOTE(Fs_name, Fs_type) (strchr ((Fs_name), ':') != 0 || ((Fs_name)[0] == '/' && (Fs_name)[1] == '/' && STREQ (Fs_type, "smbfs")))
#endif
struct mount_entry
{
char *me_devname; /* Device node pathname, including "/dev/". */
char *me_mountdir; /* Mount point directory pathname */
char *me_type; /* "nfs", "4.2", etc. */
dev_t me_dev; /* Device number of me_mountdir. */
unsigned int me_dummy : 1; /* Nonzero for dummy filesystems. */
unsigned int me_remote : 1; /* Nonzero for remote fileystems. */
unsigned int me_type_malloced :1; /* Nonzero if me_type was malloced. */
struct mount_entry *me_next;
};
void free_mount_entry_node(struct mount_entry *node)
{
if( node == NULL )
return ;
free(node->me_devname);
free(node->me_mountdir);
free(node->me_type);
free(node);
}
void free_mount_entry_list(struct mount_entry *head)
{
struct mount_entry * tmp = NULL;
while( head != NULL )
{
tmp = head;
head = head->me_next;
free_mount_entry_node(tmp);
}
}
char* xstrdup(char *str)
{
char *dupstr;
dupstr = (char*)malloc(sizeof(char)*(strlen(str) + 1 ));
strcpy(dupstr, str);
return dupstr;
}
static int xatoi (char *cp)
{
int val;
val = 0;
while (*cp)
{
if (*cp >= 'a' && *cp <= 'f')
val = val * 16 + *cp - 'a' + 10;
else if (*cp >= 'A' && *cp <= 'F')
val = val * 16 + *cp - 'A' + 10;
else if (*cp >= '0' && *cp <= '9')
val = val * 16 + *cp - '0';
else
break;
cp++;
}
return val;
}
struct mount_entry * get_mount_entry_list(void)
{
struct mntent *mnt;
char *table = MOUNTED;
FILE *fp;
char *devopt;
struct mount_entry *mount_list;
struct mount_entry *me;
struct mount_entry **mtail = &mount_list;
fp = setmntent (table, "r");
if (fp == NULL)
return NULL;
while ((mnt = getmntent (fp)))
{
me = (struct mount_entry*)malloc (sizeof(struct mount_entry));
me->me_devname = xstrdup (mnt->mnt_fsname);
me->me_mountdir = xstrdup (mnt->mnt_dir);
me->me_type = xstrdup (mnt->mnt_type);
me->me_type_malloced = 1;
me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
devopt = (char*)strstr (mnt->mnt_opts, "dev=");
if (devopt)
{
if (devopt[4] == '0' && (devopt[5] == 'x' || devopt[5] == 'X'))
me->me_dev = xatoi (devopt + 6);
else
me->me_dev = xatoi (devopt + 4);
}
else
me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
/* Add to the linked list. */
*mtail = me;
mtail = &me->me_next;
}
if (endmntent (fp) == 0)
{
free_mount_entry_list(mount_list);
mount_list = NULL;
return NULL;
}
mtail = NULL;
return mount_list;
}
char* HDInfo()
{
long long blocks,bfree;
struct statfs fs;
struct mount_entry *head,*thead;
char *ret,*tret;
int count=0;
tret=ret=(char*)malloc(sizeof(char)*1024);
thead=head = get_mount_entry_list();
if( head == NULL )
{
fprintf(stderr, "get mount list error!\n");
return NULL;
}
while( head != NULL )
{
//we want real and local filesystem
if( head->me_devname != NULL
&& strcmp(head->me_devname, "none") != 0
&& head->me_dummy == 0
&& head->me_remote == 0
&& head->me_devname[0] == '/')
{
count=sprintf(tret,"%s\t%s\t%s\t%d\t%d\t%d",
head->me_devname,
head->me_mountdir,
head->me_type,
head->me_dummy,
head->me_remote,
head->me_type_malloced);
if(count==-1)return NULL;
tret+=count/sizeof(char);
if(statfs(head->me_mountdir,&fs)<0)
{
perror("statfs");
return NULL;
}
blocks=fs.f_blocks;
bfree=fs.f_bfree;
if(fs.f_type==EXT2_SUPER_MAGIC)
{
count=sprintf(tret,"\tTotal size is %fM",blocks*fs.f_bsize/Msize);
if(count==-1)return NULL;
tret+=count/sizeof(char);
count=sprintf(tret,"\tFree size is %fM",bfree*fs.f_bsize/Msize);
if(count==-1)return NULL;
tret+=count/sizeof(char);
}
count=sprintf(tret,"\r\n");
if(count==-1)return NULL;
tret+=count/sizeof(char);
}
head=head->me_next;
}
free_mount_entry_list(thead);
printf("%s",ret);
return ret;
}