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