xref: /aosp_15_r20/external/mtools/mdu.c (revision d5c9a868b113e0ec0db2f27bc2ce8a253e77c4b0)
1 /*  Copyright 1997,2000-2002,2009 Alain Knaff.
2  *  This file is part of mtools.
3  *
4  *  Mtools is free software: you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation, either version 3 of the License, or
7  *  (at your option) any later version.
8  *
9  *  Mtools is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with Mtools.  If not, see <http://www.gnu.org/licenses/>.
16  *
17  * mdu.c:
18  * Display the space occupied by an MSDOS directory
19  */
20 
21 #include "sysincludes.h"
22 #include "msdos.h"
23 #include "vfat.h"
24 #include "mtools.h"
25 #include "file.h"
26 #include "mainloop.h"
27 #include "fs.h"
28 #include "codepage.h"
29 
30 
31 typedef struct Arg_t {
32 	int all;
33 	int inDir;
34 	int summary;
35 	struct Arg_t *parent;
36 	char *target;
37 	char *path;
38 	unsigned int blocks;
39 	MainParam_t mp;
40 } Arg_t;
41 
42 static void usage(int ret) NORETURN;
usage(int ret)43 static void usage(int ret)
44 {
45 		fprintf(stderr, "Mtools version %s, dated %s\n",
46 			mversion, mdate);
47 		fprintf(stderr, "Usage: %s: msdosdirectory\n",
48 			progname);
49 		exit(ret);
50 }
51 
file_mdu(direntry_t * entry,MainParam_t * mp)52 static int file_mdu(direntry_t *entry, MainParam_t *mp)
53 {
54 	unsigned int blocks;
55 	Arg_t * arg = (Arg_t *) (mp->arg);
56 
57 	blocks = countBlocks(entry->Dir,getStart(entry->Dir, &entry->dir));
58 	if(arg->all || !arg->inDir) {
59 		fprintPwd(stdout, entry,0);
60 		printf(" %d\n", blocks);
61 	}
62 	arg->blocks += blocks;
63 	return GOT_ONE;
64 }
65 
66 
dir_mdu(direntry_t * entry,MainParam_t * mp)67 static int dir_mdu(direntry_t *entry, MainParam_t *mp)
68 {
69 	Arg_t *parentArg = (Arg_t *) (mp->arg);
70 	Arg_t arg;
71 	int ret;
72 
73 	arg = *parentArg;
74 	arg.mp.arg = (void *) &arg;
75 	arg.parent = parentArg;
76 	arg.inDir = 1;
77 
78 	/* account for the space occupied by the directory itself */
79 	if(!isRootDir(entry->Dir)) {
80 		arg.blocks = countBlocks(entry->Dir,
81 					 getStart(entry->Dir, &entry->dir));
82 	} else {
83 		arg.blocks = 0;
84 	}
85 
86 	/* recursion */
87 	ret = mp->loop(mp->File, &arg.mp, "*");
88 	if(!arg.summary || !parentArg->inDir) {
89 		fprintPwd(stdout, entry,0);
90 		printf(" %d\n", arg.blocks);
91 	}
92 	arg.parent->blocks += arg.blocks;
93 	return ret;
94 }
95 
96 void mdu(int argc, char **argv, int type UNUSEDP) NORETURN;
mdu(int argc,char ** argv,int type UNUSEDP)97 void mdu(int argc, char **argv, int type UNUSEDP)
98 {
99 	Arg_t arg;
100 	int c;
101 
102 	arg.all = 0;
103 	arg.inDir = 0;
104 	arg.summary = 0;
105 	if(helpFlag(argc, argv))
106 		usage(0);
107 	while ((c = getopt(argc, argv, "i:ash")) != EOF) {
108 		switch (c) {
109 			case 'i':
110 				set_cmd_line_image(optarg);
111 				break;
112 			case 'a':
113 				arg.all = 1;
114 				break;
115 			case 's':
116 				arg.summary = 1;
117 				break;
118 			case 'h':
119 				usage(0);
120 			case '?':
121 				usage(1);
122 		}
123 	}
124 
125 	if (optind >= argc)
126 		usage(1);
127 
128 	if(arg.summary && arg.all) {
129 		fprintf(stderr,"-a and -s options are mutually exclusive\n");
130 		usage(1);
131 	}
132 
133 	init_mp(&arg.mp);
134 	arg.mp.callback = file_mdu;
135 	arg.mp.openflags = O_RDONLY;
136 	arg.mp.dirCallback = dir_mdu;
137 
138 	arg.mp.arg = (void *) &arg;
139 	arg.mp.lookupflags = ACCEPT_PLAIN | ACCEPT_DIR | DO_OPEN_DIRS | NO_DOTS;
140 	exit(main_loop(&arg.mp, argv + optind, argc - optind));
141 }
142