1 /* mkproto - make an mkfs prototype Author: Andrew Cagney */
3 /* Submitted by: cagney@chook.ua.oz (Andrew Cagney - aka Noid) */
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
20 #define DEF_INDENTSTR "\t"
23 #define major(x) ( (x>>8) & 0377)
24 #define minor(x) (x & 0377)
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
;
32 char *proto_file
, *top
;
38 int main(int argc
, char **argv
);
39 void descend(char *dirname
);
40 void display_attrib(const char *name
, struct stat
*st
);
41 void usage(char *binname
);
42 void open_outfile(void);
48 char *dir
= __UNCONST("");
57 indentstr
= __UNCONST(DEF_INDENTSTR
);
64 while ((op
= getopt(argc
, argv
, "b:g:i:p:t:u:d:s")) != EOF
) {
67 blocks
= atoi(optarg
);
72 if (gid
== 0) usage(argv
[0]);
76 inodes
= atoi(optarg
);
80 sscanf(optarg
, "%o", &prot
);
81 if (prot
== 0) usage(argv
[0]);
89 case 't': top
= optarg
; break;
92 if (uid
== 0) usage(argv
[0]);
95 case 'd': indentstr
= optarg
; break;
96 default: /* Illegal options */
101 if (optind
>= argc
) {
106 proto_file
= argv
[optind
];
110 if (block_given
&& !inode_given
) inodes
= (blocks
/ 3) + 8;
111 if (!block_given
&& inode_given
) usage(argv
[0]);
114 origlen
= strlen(dir
);
116 /* Check that it really is a directory */
118 if ((st
.st_mode
& S_IFMT
) != S_IFDIR
) {
119 fprintf(stderr
, "mkproto: %s must be a directory\n", dir
);
122 fprintf(outfile
, "boot\n%d %d\n", blocks
, inodes
);
123 display_attrib("", &st
);
124 fprintf(outfile
, "\n");
126 fprintf(outfile
, "$\n");
130 /* Output the prototype spec for this directory. */
131 void descend(dirname
)
136 char *name
, *temp
, *tempend
;
141 dirp
= opendir(dirname
);
143 fprintf(stderr
, "unable to open directory %s\n", dirname
);
147 temp
= (char *) malloc(sizeof(char) * strlen(dirname
) +1 + PATH_MAX
);
148 strcpy(temp
, dirname
);
150 tempend
= &temp
[strlen(temp
)];
152 for (dp
= readdir(dirp
); dp
!= NULL
; dp
= readdir(dirp
)) {
156 strcpy(tempend
, name
);
158 if (lstat(temp
, &st
) == -1) {
159 fprintf(stderr
, "cant get status of '%s' \n", temp
);
162 if (name
[0] == '.' && (name
[1] == 0 ||
163 (name
[1] == '.' && name
[2] == 0)))
166 display_attrib(name
, &st
);
168 mode
= st
.st_mode
& S_IFMT
;
169 if (mode
== S_IFDIR
) {
170 fprintf(outfile
, "\n");
172 for (i
= 0; i
< tabs
; i
++) {
173 fprintf(outfile
, "%s", indentstr
);
175 fprintf(outfile
, "$\n");
178 if (mode
== S_IFBLK
|| mode
== S_IFCHR
) {
179 fprintf(outfile
, " %d %d\n", major(st
.st_rdev
), minor(st
.st_rdev
));
182 if (mode
== S_IFREG
) {
184 fprintf(outfile
, "%s%s", indentstr
, top
);
185 while (temp
[i
] != '\0') {
186 fputc(temp
[i
], outfile
);
189 fprintf(outfile
, "\n");
192 if (mode
== S_IFLNK
) {
193 char linkcontent
[PATH_MAX
];
194 memset(linkcontent
, 0, sizeof(linkcontent
));
195 if(readlink(temp
, linkcontent
, sizeof(linkcontent
)) < 0) {
199 fprintf(outfile
, "%s%s\n", indentstr
, linkcontent
);
202 fprintf(outfile
, " /dev/null");
203 fprintf(stderr
,"File\n\t%s\n has an invalid mode, made empty.\n",temp
);
211 void display_attrib(name
, st
)
215 /* Output the specification for a single file */
219 if (same_uid
) uid
= st
->st_uid
;
220 if (same_gid
) gid
= st
->st_gid
;
222 prot
= st
->st_mode
& 0777; /***** This one is a bit shady *****/
223 for (i
= 0; i
< tabs
; i
++) fprintf(outfile
, "%s", indentstr
);
224 fprintf(outfile
, "%s%s%c%c%c%3o %d %d",
226 *name
== '\0' ? "" : indentstr
, /* stop the tab for a null name */
227 (st
->st_mode
& S_IFMT
) == S_IFDIR
? 'd' :
228 (st
->st_mode
& S_IFMT
) == S_IFCHR
? 'c' :
229 (st
->st_mode
& S_IFMT
) == S_IFBLK
? 'b' :
230 (st
->st_mode
& S_IFMT
) == S_IFLNK
? 's' :
232 (st
->st_mode
& S_ISUID
) ? 'u' : '-', /* set uid */
233 (st
->st_mode
& S_ISGID
) ? 'g' : '-', /* set gid */
242 fprintf(stderr
, "Usage: %s [options] source_directory [prototype_file]\n", binname
);
243 fprintf(stderr
, "options:\n");
244 fprintf(stderr
, " -b n\t\t file system size is n blocks (default %d)\n", DEF_BLOCKS
);
245 fprintf(stderr
, " -d STRING\t define the indentation characters (default %s)\n", "(none)");
246 fprintf(stderr
, " -g n\t\t use n as the gid on all files (default %d)\n", DEF_GID
);
247 fprintf(stderr
, " -i n\t\t file system gets n i-nodes (default %d)\n", DEF_INODES
);
248 fprintf(stderr
, " -p nnn\t use nnn (octal) as mode on all files (default %o)\n", DEF_PROT
);
249 fprintf(stderr
, " -s \t\t use the same uid, gid and mode as originals have\n");
250 fprintf(stderr
, " -t ROOT\t inital path prefix for each entry\n");
251 fprintf(stderr
, " -u n\t\t use nnn as the uid on all files (default %d)\n", DEF_UID
);
257 if (proto_file
== NULL
)
259 else if ((outfile
= fopen(proto_file
, "w")) == NULL
)
260 fprintf(stderr
, "Cannot create %s\n ", proto_file
);