forget difference between big and small commands - obsolete with vm.
[minix.git] / commands / simple / mkproto.c
blobb40d26ba99c811160ac796110f6291036b7c034e
1 /* mkproto - make an mkfs prototype Author: Andrew Cagney */
3 /* Submitted by: cagney@chook.ua.oz (Andrew Cagney - aka Noid) */
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>
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"
22 #ifndef major
23 #define major(x) ( (x>>8) & 0377)
24 #define minor(x) (x & 0377)
25 #endif
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;
35 extern int optind;
36 extern char *optarg;
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));
44 int main(argc, argv)
45 int argc;
46 char *argv[];
48 char *dir;
49 struct stat st;
50 int op;
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]);
101 if (optind >= argc) {
102 usage(argv[0]);
103 } else {
104 dir = argv[optind];
105 optind++;
106 proto_file = argv[optind];
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);
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]);
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);
130 /* Output the prototype spec for this directory. */
131 void descend(dirname)
132 char *dirname;
134 struct dirent *dp;
135 DIR *dirp;
136 char *name, *temp, *tempend;
137 int i;
138 struct stat st;
139 mode_t mode;
141 dirp = opendir(dirname);
142 if (dirp == NULL) {
143 fprintf(stderr, "unable to open directory %s\n", dirname);
144 return;
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)];
152 for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
153 name = dp->d_name;
155 count++;
156 strcpy(tempend, name);
158 if (stat(temp, &st) == -1) {
159 fprintf(stderr, "cant get status of '%s' \n", temp);
160 continue;
162 if (name[0] == '.' && (name[1] == 0 ||
163 (name[1] == '.' && name[2] == 0)))
164 continue;
166 display_attrib(name, &st);
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);
175 fprintf(outfile, "$\n");
176 continue;
178 if (mode == S_IFBLK || mode == S_IFCHR) {
179 fprintf(outfile, " %d %d\n", major(st.st_rdev), minor(st.st_rdev));
180 continue;
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++;
189 fprintf(outfile, "\n");
190 continue;
192 fprintf(outfile, " /dev/null");
193 fprintf(stderr,"File\n\t%s\n has an invalid mode, made empty.\n",temp);
195 closedir(dirp);
196 free(temp);
197 tabs--;
201 void display_attrib(name, st)
202 char *name;
203 struct stat *st;
205 /* Output the specification for a single file */
207 int i;
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);
228 void usage(binname)
229 char *binname;
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);
244 void open_outfile()
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);