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. */
|
---|
28 | int count, origlen, tabs;
|
---|
29 | int gid, uid, prot, same_uid, same_gid, same_prot, blocks, inodes;
|
---|
30 | int block_given, inode_given, dprot;
|
---|
31 | char *indentstr;
|
---|
32 | char *proto_file, *top;
|
---|
33 | FILE *outfile;
|
---|
34 |
|
---|
35 | extern int optind;
|
---|
36 | extern 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 |
|
---|
44 | int main(argc, argv)
|
---|
45 | int argc;
|
---|
46 | char *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. */
|
---|
131 | void descend(dirname)
|
---|
132 | char *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 |
|
---|
201 | void display_attrib(name, st)
|
---|
202 | char *name;
|
---|
203 | struct 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 |
|
---|
228 | void usage(binname)
|
---|
229 | char *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 |
|
---|
244 | void 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 | }
|
---|