source: trunk/minix/commands/simple/mkproto.c@ 15

Last change on this file since 15 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 5.9 KB
Line 
1/* mkproto - make an mkfs prototype Author: Andrew Cagney */
2
3/* Submitted by: cagney@chook.ua.oz (Andrew Cagney - aka Noid) */
4
5#include <sys/types.h>
6#include <sys/stat.h>
7#include <limits.h>
8#include <dirent.h>
9#include <stdlib.h>
10#include <string.h>
11#include <stdio.h>
12#include <unistd.h>
13
14/* The default values for the prototype file */
15#define DEF_UID 2 /* bin */
16#define DEF_GID 1 /* daemon group */
17#define DEF_PROT 0555 /* a=re */
18#define DEF_BLOCKS 360
19#define DEF_INODES 63
20#define DEF_INDENTSTR "\t"
21
22#ifndef major
23#define major(x) ( (x>>8) & 0377)
24#define minor(x) (x & 0377)
25#endif
26
27/* Globals. */
28int count, origlen, tabs;
29int gid, uid, prot, same_uid, same_gid, same_prot, blocks, inodes;
30int block_given, inode_given, dprot;
31char *indentstr;
32char *proto_file, *top;
33FILE *outfile;
34
35extern int optind;
36extern char *optarg;
37
38_PROTOTYPE(int main, (int argc, char **argv));
39_PROTOTYPE(void descend, (char *dirname));
40_PROTOTYPE(void display_attrib, (char *name, struct stat *st));
41_PROTOTYPE(void usage, (char *binname));
42_PROTOTYPE(void open_outfile, (void));
43
44int main(argc, argv)
45int argc;
46char *argv[];
47{
48 char *dir;
49 struct stat st;
50 int op;
51
52 gid = DEF_GID;
53 uid = DEF_UID;
54 prot = DEF_PROT;
55 blocks = DEF_BLOCKS;
56 inodes = DEF_INODES;
57 indentstr = DEF_INDENTSTR;
58 inode_given = 0;
59 block_given = 0;
60 top = 0;
61 same_uid = 0;
62 same_gid = 0;
63 same_prot = 0;
64 while ((op = getopt(argc, argv, "b:g:i:p:t:u:d:s")) != EOF) {
65 switch (op) {
66 case 'b':
67 blocks = atoi(optarg);
68 block_given = 1;
69 break;
70 case 'g':
71 gid = atoi(optarg);
72 if (gid == 0) usage(argv[0]);
73 same_gid = 0;
74 break;
75 case 'i':
76 inodes = atoi(optarg);
77 inode_given = 1;
78 break;
79 case 'p':
80 sscanf(optarg, "%o", &prot);
81 if (prot == 0) usage(argv[0]);
82 same_prot = 0;
83 break;
84 case 's':
85 same_prot = 1;
86 same_uid = 1;
87 same_gid = 1;
88 break;
89 case 't': top = optarg; break;
90 case 'u':
91 uid = atoi(optarg);
92 if (uid == 0) usage(argv[0]);
93 same_uid = 0;
94 break;
95 case 'd': indentstr = optarg; break;
96 default: /* Illegal options */
97 usage(argv[0]);
98 }
99 }
100
101 if (optind >= argc) {
102 usage(argv[0]);
103 } else {
104 dir = argv[optind];
105 optind++;
106 proto_file = argv[optind];
107 }
108 if (!top) top = dir;
109 open_outfile();
110 if (block_given && !inode_given) inodes = (blocks / 3) + 8;
111 if (!block_given && inode_given) usage(argv[0]);
112 count = 1;
113 tabs = 0;
114 origlen = strlen(dir);
115
116 /* Check that it really is a directory */
117 stat(dir, &st);
118 if ((st.st_mode & S_IFMT) != S_IFDIR) {
119 fprintf(stderr, "mkproto: %s must be a directory\n", dir);
120 usage(argv[0]);
121 }
122 fprintf(outfile, "boot\n%d %d\n", blocks, inodes);
123 display_attrib("", &st);
124 fprintf(outfile, "\n");
125 descend(dir);
126 fprintf(outfile, "$\n");
127 return(0);
128}
129
130/* Output the prototype spec for this directory. */
131void descend(dirname)
132char *dirname;
133{
134 struct dirent *dp;
135 DIR *dirp;
136 char *name, *temp, *tempend;
137 int i;
138 struct stat st;
139 mode_t mode;
140
141 dirp = opendir(dirname);
142 if (dirp == NULL) {
143 fprintf(stderr, "unable to open directory %s\n", dirname);
144 return;
145 }
146 tabs++;
147 temp = (char *) malloc(sizeof(char) * strlen(dirname) +1 + PATH_MAX);
148 strcpy(temp, dirname);
149 strcat(temp, "/");
150 tempend = &temp[strlen(temp)];
151
152 for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
153 name = dp->d_name;
154
155 count++;
156 strcpy(tempend, name);
157
158 if (stat(temp, &st) == -1) {
159 fprintf(stderr, "cant get status of '%s' \n", temp);
160 continue;
161 }
162 if (name[0] == '.' && (name[1] == 0 ||
163 (name[1] == '.' && name[2] == 0)))
164 continue;
165
166 display_attrib(name, &st);
167
168 mode = st.st_mode & S_IFMT;
169 if (mode == S_IFDIR) {
170 fprintf(outfile, "\n");
171 descend(temp);
172 for (i = 0; i < tabs; i++) {
173 fprintf(outfile, indentstr);
174 }
175 fprintf(outfile, "$\n");
176 continue;
177 }
178 if (mode == S_IFBLK || mode == S_IFCHR) {
179 fprintf(outfile, " %d %d\n", major(st.st_rdev), minor(st.st_rdev));
180 continue;
181 }
182 if (mode == S_IFREG) {
183 i = origlen;
184 fprintf(outfile, "%s%s", indentstr, top);
185 while (temp[i] != '\0') {
186 fputc(temp[i], outfile);
187 i++;
188 }
189 fprintf(outfile, "\n");
190 continue;
191 }
192 fprintf(outfile, " /dev/null");
193 fprintf(stderr,"File\n\t%s\n has an invalid mode, made empty.\n",temp);
194 }
195 closedir(dirp);
196 free(temp);
197 tabs--;
198}
199
200
201void display_attrib(name, st)
202char *name;
203struct stat *st;
204{
205/* Output the specification for a single file */
206
207 int i;
208
209 if (same_uid) uid = st->st_uid;
210 if (same_gid) gid = st->st_gid;
211 if (same_prot)
212 prot = st->st_mode & 0777; /***** This one is a bit shady *****/
213 for (i = 0; i < tabs; i++) fprintf(outfile, indentstr);
214 fprintf(outfile, "%s%s%c%c%c%3o %d %d",
215 name,
216 *name == '\0' ? "" : indentstr, /* stop the tab for a null name */
217 (st->st_mode & S_IFMT) == S_IFDIR ? 'd' :
218 (st->st_mode & S_IFMT) == S_IFCHR ? 'c' :
219 (st->st_mode & S_IFMT) == S_IFBLK ? 'b' :
220 '-', /* file type */
221 (st->st_mode & S_ISUID) ? 'u' : '-', /* set uid */
222 (st->st_mode & S_ISGID) ? 'g' : '-', /* set gid */
223 prot,
224 uid,
225 gid);
226}
227
228void usage(binname)
229char *binname;
230{
231 fprintf(stderr, "Usage: %s [options] source_directory [prototype_file]\n", binname);
232 fprintf(stderr, "options:\n");
233 fprintf(stderr, " -b n\t\t file system size is n blocks (default %d)\n", DEF_BLOCKS);
234 fprintf(stderr, " -d STRING\t define the indentation characters (default %s)\n", "(none)");
235 fprintf(stderr, " -g n\t\t use n as the gid on all files (default %d)\n", DEF_GID);
236 fprintf(stderr, " -i n\t\t file system gets n i-nodes (default %d)\n", DEF_INODES);
237 fprintf(stderr, " -p nnn\t use nnn (octal) as mode on all files (default %o)\n", DEF_PROT);
238 fprintf(stderr, " -s \t\t use the same uid, gid and mode as originals have\n");
239 fprintf(stderr, " -t ROOT\t inital path prefix for each entry\n");
240 fprintf(stderr, " -u n\t\t use nnn as the uid on all files (default %d)\n", DEF_UID);
241 exit(1);
242}
243
244void open_outfile()
245{
246 if (proto_file == NULL)
247 outfile = stdout;
248 else if ((outfile = fopen(proto_file, "w")) == NULL)
249 fprintf(stderr, "Cannot create %s\n ", proto_file);
250}
Note: See TracBrowser for help on using the repository browser.