⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 df.c

📁 linux 中df命令的实现c语言源码
💻 C
字号:
/*********************************************************************Copyright (c)	:	 free software.*Filename		:	df.c*Author			:	gxg*Version		:	1.0*History		:	Create this file . To show files description .*Data			:	2008.09.22*Description	:	*Other			:	*********************************************************************/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <mntent.h>#include <sys/vfs.h>#include <stdarg.h>#include <getopt.h>#include <assert.h>#include <linux/stat.h>#include <sys/stat.h>#include <sys/types.h>#include <dirent.h>#include <limits.h>#include <dirent.h>#include "df.h"int bb_default_error_retval = EXIT_FAILURE;//const char bb_path_mtab_file[] = "/etc/mtab";const char bb_path_mtab_file[] = "/proc/mounts";static const struct option bb_default_long_options[] = {/*      { "help", 0, NULL, '?' }, */	{ 0, 0, 0, 0 }};const struct option *bb_applet_long_options = bb_default_long_options;static const char msg_enomem[] = "memory exhausted";void usage(char *prog){	fprintf(stderr,		"Usage: %s [ -q ] [ -o offset ] [ -f frequency ] [ -p timeconstant ] [ -t tick ]\n",		prog);}#define bb_show_usage() usage(argv[0])void bb_verror_msg(const char *s, va_list p){	fflush(stdout);	//fprintf(stderr, "%s: ", bb_applet_name);	vfprintf(stderr, s, p);}void bb_error_msg_and_die(const char *s, ...){	va_list p;	va_start(p, s);	bb_verror_msg(s, p);	va_end(p);	putc('\n', stderr);	exit(bb_default_error_retval);}char * bb_xstrdup (const char *s){	char *t;	if (s == NULL)		return NULL;	t = strdup (s);	if (t == NULL)		bb_error_msg_and_die(msg_enomem);	return t;}/* inline realization for fast works */static inline void *xmalloc(size_t size){	void *p = malloc(size);	if(p == NULL)		fprintf(stderr, "%s: ", msg_enomem);	return p;}llist_t *llist_add_to(llist_t *old_head, char *new_item){	llist_t *new_head;	new_head = xmalloc(sizeof(llist_t));	new_head->data = new_item;	new_head->link = old_head;	return (new_head);}extern int bb_vfprintf(FILE * __restrict stream,					   const char * __restrict format,					   va_list arg){	int rv;	if ((rv = vfprintf(stream, format, arg)) < 0) {		//SET_FERROR_UNLOCKED(stream);		;	}	return rv;}int bb_printf(const char * __restrict format, ...){	va_list arg;	int rv;	va_start(arg, format);	rv = bb_vfprintf(stdout, format, arg);	va_end(arg);	return rv;}//this function had some memory leak,	had malloc but no freeunsigned longbb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...){	unsigned long flags = 0;	unsigned long requires = 0;	t_complementally complementally[sizeof(flags) * 8 + 1];	int c;	const unsigned char *s;	t_complementally *on_off;	va_list p;	const struct option *l_o;	unsigned long trigger;#ifdef CONFIG_PS	char **pargv = NULL;#endif	int min_arg = 0;	int max_arg = -1;#define SHOW_USAGE_IF_ERROR     1#define ALL_ARGV_IS_OPTS        2#define FIRST_ARGV_IS_OPT       4#define FREE_FIRST_ARGV_IS_OPT  8	int spec_flgs = 0;	va_start (p, applet_opts);	c = 0;	on_off = complementally;	memset(on_off, 0, sizeof(complementally));	/* skip GNU extension */	s = (const unsigned char *)applet_opts;	if(*s == '+' || *s == '-')		s++;	for (; *s; s++) {		if(c >= (int)(sizeof(flags)*8))			break;		on_off->opt = *s;		on_off->switch_on = (1 << c);		if (s[1] == ':') {			on_off->optarg = va_arg (p, void **);			do				s++;			while (s[1] == ':');		}		on_off++;		c++;	}	for(l_o = bb_applet_long_options; l_o->name; l_o++) {		if(l_o->flag)			continue;		for(on_off = complementally; on_off->opt != 0; on_off++)			if(on_off->opt == l_o->val)				break;		if(on_off->opt == 0) {			if(c >= (int)(sizeof(flags)*8))				break;			on_off->opt = l_o->val;			on_off->switch_on = (1 << c);			if(l_o->has_arg != no_argument)				on_off->optarg = va_arg (p, void **);			c++;		}	}	for (s = (const unsigned char *)bb_opt_complementally; s && *s; s++) {		t_complementally *pair;		unsigned long *pair_switch;		if (*s == ':')			continue;		c = s[1];		if(*s == '?') {			if(c < '0' || c > '9') {				spec_flgs |= SHOW_USAGE_IF_ERROR;			} else {				max_arg = c - '0';				s++;			}			continue;		}		if(*s == '-') {			if(c < '0' || c > '9') {				if(c == '-') {					spec_flgs |= FIRST_ARGV_IS_OPT;					s++;				} else					spec_flgs |= ALL_ARGV_IS_OPTS;			} else {				min_arg = c - '0';				s++;			}			continue;		}		for (on_off = complementally; on_off->opt; on_off++)			if (on_off->opt == *s)				break;		if(c == ':' && s[2] == ':') {			on_off->list_flg++;			continue;		}		if(c == ':' || c == '\0') {			requires |= on_off->switch_on;			continue;		}		if(c == '-' && (s[2] == ':' || s[2] == '\0')) {			flags |= on_off->switch_on;			on_off->incongruously |= on_off->switch_on;			s++;			continue;		}		if(c == *s) {			on_off->counter = va_arg (p, int *);			s++;		}		pair = on_off;		pair_switch = &(pair->switch_on);		for(s++; *s && *s != ':'; s++) {			if(*s == '?') {				pair_switch = &(pair->requires);			} else if (*s == '-') {				if(pair_switch == &(pair->switch_off))					pair_switch = &(pair->incongruously);				else					pair_switch = &(pair->switch_off);			} else {			    for (on_off = complementally; on_off->opt; on_off++)				if (on_off->opt == *s) {				    *pair_switch |= on_off->switch_on;				    break;				}			}		}		s--;	}	va_end (p);#if defined(CONFIG_AR) || defined(CONFIG_TAR)	if((spec_flgs & FIRST_ARGV_IS_OPT)) {		if(argv[1] && argv[1][0] != '-' && argv[1][0] != '\0') {			argv[1] = bb_xasprintf("-%s", argv[1]);			if(ENABLE_FEATURE_CLEAN_UP)				spec_flgs |= FREE_FIRST_ARGV_IS_OPT;		}	}#endif	while ((c = getopt_long (argc, argv, applet_opts,				 bb_applet_long_options, NULL)) >= 0) {#ifdef CONFIG_PSloop_arg_is_opt:#endif		for (on_off = complementally; on_off->opt != c; on_off++) {			/* c==0 if long opt have non NULL flag */			if(on_off->opt == 0 && c != 0)				bb_show_usage ();		}		if(flags & on_off->incongruously) {			if((spec_flgs & SHOW_USAGE_IF_ERROR))				bb_show_usage ();			flags |= BB_GETOPT_ERROR;		}		trigger = on_off->switch_on & on_off->switch_off;		flags &= ~(on_off->switch_off ^ trigger);		flags |= on_off->switch_on ^ trigger;		flags ^= trigger;		if(on_off->counter)			(*(on_off->counter))++;		if(on_off->list_flg) {			*(llist_t **)(on_off->optarg) =			  llist_add_to(*(llist_t **)(on_off->optarg), optarg);		} else if (on_off->optarg) {			*(char **)(on_off->optarg) = optarg;		}#ifdef CONFIG_PS		if(pargv != NULL)			break;#endif	}#ifdef CONFIG_PS	if((spec_flgs & ALL_ARGV_IS_OPTS)) {		/* process argv is option, for example "ps" applet */		if(pargv == NULL)			pargv = argv + optind;		while(*pargv) {			c = **pargv;			if(c == '\0') {				pargv++;			} else {				(*pargv)++;				goto loop_arg_is_opt;			}		}	}#endif#if (defined(CONFIG_AR) || defined(CONFIG_TAR)) && \				defined(CONFIG_FEATURE_CLEAN_UP)	if((spec_flgs & FREE_FIRST_ARGV_IS_OPT))		free(argv[1]);#endif	/* check depending requires for given options */	for (on_off = complementally; on_off->opt; on_off++) {		if(on_off->requires && (flags & on_off->switch_on) &&					(flags & on_off->requires) == 0)			bb_show_usage ();	}	if(requires && (flags & requires) == 0)		bb_show_usage ();	argc -= optind;	if(argc < min_arg || (max_arg >= 0 && argc > max_arg))		bb_show_usage ();	return flags;}#ifndef CONFIG_FEATURE_HUMAN_READABLEstatic long kscale(long b, long bs){	return ( b * (long long) bs + KILOBYTE/2 ) / KILOBYTE;}#endifstruct mntent *find_mount_point(const char *name, const char *table){	struct stat s;	dev_t mountDevice;	FILE *mountTable;	struct mntent *mountEntry;	if (stat(name, &s) != 0)		return 0;	if ((s.st_mode & S_IFMT) == S_IFBLK)		mountDevice = s.st_rdev;	else		mountDevice = s.st_dev;	if ((mountTable = setmntent(table ? table : bb_path_mtab_file, "r")) == 0)		return 0;	while ((mountEntry = getmntent(mountTable)) != 0) {			if(strcmp(name, mountEntry->mnt_dir) == 0			|| strcmp(name, mountEntry->mnt_fsname) == 0)	/* String match. */			break;		if (stat(mountEntry->mnt_fsname, &s) == 0 && s.st_rdev == mountDevice)	/* Match the device. */			break;		if (stat(mountEntry->mnt_dir, &s) == 0 && s.st_dev == mountDevice)	/* Match the directory's mount point. */			break;	}	endmntent(mountTable);	return mountEntry;}char *find_block_device(char *path){	DIR *dir;	struct dirent *entry;	struct stat st;	dev_t dev;	char *retpath=NULL;	if(stat(path, &st) || !(dir = opendir("/dev"))) return NULL;	dev = (st.st_mode & S_IFMT) == S_IFBLK ? st.st_rdev : st.st_dev;	while((entry = readdir(dir)) != NULL) {		char devpath[PATH_MAX];		sprintf(devpath,"/dev/%s", entry->d_name);		if(!stat(devpath, &st) && S_ISBLK(st.st_mode) && st.st_rdev == dev) {			retpath = bb_xstrdup(devpath);			break;		}	}	closedir(dir);	return retpath;}#ifdef  CONFIG_FEATURE_HUMAN_READABLEconst char *make_human_readable_str(unsigned long long size,	unsigned long block_size, unsigned long display_unit){	/* The code will adjust for additional (appended) units. */	static const char zero_and_units[] = { '0', 0, 'k', 'M', 'G', 'T' };	static const char fmt[] = "%Lu";	static const char fmt_tenths[] = "%Lu.%d%c";	static char str[21];		/* Sufficient for 64 bit unsigned integers. */	unsigned long long val;	int frac;	const char *u;	const char *f;	u = zero_and_units;	f = fmt;	frac = 0;	val = size * block_size;	if (val == 0) {		return u;	}	if (display_unit) {		val += display_unit/2;	/* Deal with rounding. */		val /= display_unit;	/* Don't combine with the line above!!! */	} else {		++u;		while ((val >= KILOBYTE)			   && (u < zero_and_units + sizeof(zero_and_units) - 1)) {			f = fmt_tenths;			++u;			frac = ((((int)(val % KILOBYTE)) * 10) + (KILOBYTE/2)) / KILOBYTE;			val /= KILOBYTE;		}		if (frac >= 10) {		/* We need to round up here. */			++val;			frac = 0;		}#if 0		/* Sample code to omit decimal point and tenths digit. */		if ( /* no_tenths */ 1 ) {			if ( frac >= 5 ) {				++val;			}			f = "%Lu%*c" /* fmt_no_tenths */ ;			frac = 1;		}#endif	}	/* If f==fmt then 'frac' and 'u' are ignored. */	snprintf(str, sizeof(str), f, val, frac, *u);	return str;}#endifint df_proc(int argc, char **argv){	long blocks_used;	long blocks_percent_used;	char *pfree = NULL;	//用于释放strdup分配的空间,以免造成内存泄露#ifdef CONFIG_FEATURE_HUMAN_READABLE	unsigned long df_disp_hr = KILOBYTE;#endif	int status = EXIT_SUCCESS;	unsigned long opt;	FILE *mount_table;	struct mntent *mount_entry;	struct statfs s;	static const char hdr_1k[] = "1k-blocks"; /* default display is kilobytes */	const char *disp_units_hdr = hdr_1k;#ifdef CONFIG_FEATURE_HUMAN_READABLE	bb_opt_complementally = "h-km:k-hm:m-hk";	//opt = bb_getopt_ulflags(argc, argv, "hmk");	//this function had some memory leak ,comment by gxg	opt = 1;  //add by gxg	if(opt & 1) {				df_disp_hr = 0;				disp_units_hdr = "     Size";	}	if(opt & 2) {				df_disp_hr = MEGABYTE;				disp_units_hdr = "1M-blocks";	}#else	opt = bb_getopt_ulflags(argc, argv, "k");#endif	printf("Filesystem%11s%-15sUsed Available Use%% Mounted on\n",			  "", disp_units_hdr);	optind = 2;		//add by gxg	mount_table = NULL;	argv += optind;	if (optind >= argc) {		if (!(mount_table = setmntent(bb_path_mtab_file, "r"))) {				fflush(stdout);				fprintf(stderr, "%s: ", bb_path_mtab_file);		}	}	do {		const char *device;		const char *mount_point;		if(NULL != pfree)		{			free(pfree);			pfree = NULL;		}		if (mount_table) {			if (!(mount_entry = getmntent(mount_table))) {				endmntent(mount_table);				break;			}		} else {			if (!(mount_point = *argv++)) {				break;			}			if (!(mount_entry = find_mount_point((char *)mount_point, bb_path_mtab_file))) {				printf("%p: can't find mount point.", mount_point);			SET_ERROR:				status = EXIT_FAILURE;				continue;			}		}		device = mount_entry->mnt_fsname;		mount_point = mount_entry->mnt_dir;		if (statfs(mount_point, &s) != 0) {			//bb_perror_msg("%s", mount_point);			goto SET_ERROR;		}		if ((s.f_blocks > 0) || !mount_table){			blocks_used = s.f_blocks - s.f_bfree;			blocks_percent_used = 0;			if (blocks_used + s.f_bavail) {				blocks_percent_used = (((long long) blocks_used) * 100									   + (blocks_used + s.f_bavail)/2									   ) / (blocks_used + s.f_bavail);			}			if (strcmp(device, "rootfs") == 0) {				continue;			} else if (strcmp(device, "/dev/root") == 0) {				/* Adjusts device to be the real root device,				* or leaves device alone if it can't find it */				if ((device = find_block_device("/")) == NULL) {					goto SET_ERROR;				}else					pfree = device;			}#ifdef CONFIG_FEATURE_HUMAN_READABLE			bb_printf("%-20s %9s ", device,					  make_human_readable_str(s.f_blocks, s.f_bsize, df_disp_hr));			bb_printf("%9s ",					  make_human_readable_str( (s.f_blocks - s.f_bfree),											  s.f_bsize, df_disp_hr));			bb_printf("%9s %3ld%% %s\n",					  make_human_readable_str(s.f_bavail, s.f_bsize, df_disp_hr),					  blocks_percent_used, mount_point);#else			bb_printf("%-20s %9ld %9ld %9ld %3ld%% %s\n",  					  device,					  kscale(s.f_blocks, s.f_bsize),					  kscale(s.f_blocks-s.f_bfree, s.f_bsize),					  kscale(s.f_bavail, s.f_bsize),					  blocks_percent_used, mount_point);#endif		}	} while (1);	//flush stdout and exit	if (fflush(stdout)) {		status = bb_default_error_retval;	}	return (status);	}int main(int argc, char * * argv){#if 0	int iCount;	char flag = 0;	printf("%d\n",argc);	for(iCount = 0; iCount <64; iCount ++){		if(argv[iCount] == NULL)		{			if(flag == 0)			{				flag = 1;				continue;			}else				break;		}		printf("%s:\n",argv[iCount]);	}#endif	df_proc(argc, argv);	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -