Imported Upstream version 4.0.18
[platform/upstream/mtools.git] / mdu.c
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;
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
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
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)
97 {
98         Arg_t arg;
99         int c;
100
101         arg.all = 0;
102         arg.inDir = 0;
103         arg.summary = 0;
104         if(helpFlag(argc, argv))
105                 usage(0);
106         while ((c = getopt(argc, argv, "i:ash")) != EOF) {
107                 switch (c) {
108                         case 'i':
109                                 set_cmd_line_image(optarg);
110                                 break;
111                         case 'a':
112                                 arg.all = 1;
113                                 break;
114                         case 's':
115                                 arg.summary = 1;
116                                 break;
117                         case 'h':
118                                 usage(0);
119                         case '?':
120                                 usage(1);
121                 }
122         }
123
124         if (optind >= argc)
125                 usage(1);
126
127         if(arg.summary && arg.all) {
128                 fprintf(stderr,"-a and -s options are mutually exclusive\n");
129                 usage(1);
130         }
131
132         init_mp(&arg.mp);
133         arg.mp.callback = file_mdu;
134         arg.mp.openflags = O_RDONLY;
135         arg.mp.dirCallback = dir_mdu;
136
137         arg.mp.arg = (void *) &arg;
138         arg.mp.lookupflags = ACCEPT_PLAIN | ACCEPT_DIR | DO_OPEN_DIRS | NO_DOTS;
139         exit(main_loop(&arg.mp, argv + optind, argc - optind));
140 }