cagney@chook.ua.oz (Andrew Cagney - aka Noid) (11/11/89)
Below is a version of mkproto (make prototype file) written earlier this year. It works on both unix (SUNOS, UMAX) and MINIX. (For minix modify the Makefile to not define -DUNIX). This tool avoids the hassles of creating prototype files by hand. BTW Is any one interrested in modifying mkfs so that the line below works? mkproto -b20000 -s /user | mkfs /dev/hd1 - :-) Andrew Cagney ------------------------------------------------------------- Chomp echo x - Makefile sed '/^X/s///' > Makefile << '/' X XBIN= /usr/etc XO=s X X Xmkproto : mkproto.c X cc -DUNIX mkproto.c -o mkproto X Xall : mkproto mkproto.doc X Xinstall : mkproto X rm -rf $(BIN)/mkproto X cp mkproto $(BIN) X Xmkproto.doc : mkproto.man X nroff -man mkproto.man | col -b > mkproto.doc X Xclean : X rm -rf mkproto mkproto.$(O) X / echo x - mkproto.c sed '/^X/s///' > mkproto.c << '/' X/* X * Mkproto: create a prototype file X * X */ X X#ifdef __STDC__ X#define _PROTO(p) p X#else X#define _PROTO(p) () X#endif X X#include <stdio.h> X#include <sys/types.h> X#include <sys/stat.h> X#ifdef UNIX X#include <sys/dir.h> X#else X#include <dirent.h> X#endif X X/* for getopt */ Xextern int getopt _PROTO((int argc, char **argv, char *opts)); Xextern int optind; Xextern char *optarg; X X#define PLEN 256 /* maximum path length; overflows are not detected */ X X/* the default values for the prototype file */ X X#define DEF_UID 2 /*bin*/ X#define DEF_GID 1 /*daemon group*/ X#define DEF_PROT 0555 /*a=re*/ X#define DEF_BLOCKS 360 X#define DEF_INODES 63 X#define DEF_INDENTSTR "\t" X Xint count, origlen, tabs; Xint gid, uid, prot, same_uid, same_gid, same_prot, blocks, inodes; Xint block_given, inode_given, dprot; Xchar *indentstr; Xchar *proto_file, *top; XFILE *outfile; X Xmain(argc, argv) X int argc; X char *argv[]; X{ X int i; X register char *ptr; /* Ptr to *argv in use */ X char *dir; X struct stat st; X char op; X X gid = DEF_GID; X uid = DEF_UID; X prot = DEF_PROT; X blocks = DEF_BLOCKS; X inodes = DEF_INODES; X indentstr = DEF_INDENTSTR; X inode_given = 0; X block_given = 0; X top = 0; X same_uid = 0; X same_gid = 0; X same_prot = 0; X while ((op = getopt(argc, argv, "b:g:i:p:t:u:d:s")) != EOF) { X switch (op) { X case 'b' : X blocks = atoi(optarg); X block_given = 1; X break; X case 'g' : X gid = atoi(optarg); X if (gid == 0) usage(argv[0]); X same_gid = 0; X break; X case 'i' : X inodes = atoi(optarg); X inode_given = 1; X break; X case 'p' : X sscanf(optarg, "%o" , &prot); X if (prot == 0) usage(argv[0]); X same_prot = 0; X break; X case 's' : X same_prot = 1; X same_uid = 1; X same_gid = 1; X break; X case 't' : X top = optarg; X break; X case 'u' : X uid = atoi(optarg); X if (uid == 0) usage(argv[0]); X same_uid = 0; X break; X case 'd' : X indentstr = optarg; X break; X default : /* Illegal options */ X usage(argv[0]); X } X } X X if (optind >= argc) { X usage(argv[0]); X } X else { X dir = argv[optind]; X optind++; X proto_file = argv[optind]; X } X if (!top) top = dir; X open_outfile(); X if (block_given && !inode_given) inodes = (blocks/3) + 8; X if (!block_given && inode_given) usage(argv[0]); X count=1; X tabs = 0; X origlen = strlen(dir); X X /* check that it really is a directory */ X stat(dir, &st); X if ((st.st_mode&S_IFMT) != S_IFDIR) { X fprintf(stderr,"mkproto: %s must be a directory\n", dir); X usage(argv[0]); X } X fprintf(outfile,"boot\n%d %d\n",blocks,inodes); X display_attrib("", &st); X fprintf(outfile,"\n"); X descend(dir); X fprintf(outfile,"$\n"); X} X X X/* X * Output the prototype spec for this directory. X */ X Xdescend(dirname) X char *dirname; X{ X#ifdef UNIX X struct direct *dp; X#else X struct dirent *dp; X#endif X DIR *dirp; X char *bs, *name, *newdir, *temp, *tempend; X int i; X struct stat st; X unsigned short mode; X X dirp = opendir(dirname); X if (dirp == NULL) { X fprintf(stderr, "unable to open directory %s\n",dirname); X return; X } X X tabs++; X temp = (char *)malloc(sizeof(char)*strlen(dirname)+1 + PLEN ); X strcpy(temp,dirname); X strcat(temp,"/"); X tempend = &temp[strlen(temp)]; X X for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { X name = dp->d_name; X X count++; X strcpy(tempend,name); X X if (stat(temp, &st) == -1) { X fprintf(stderr,"cant get status of '%s' \n",temp); X continue; X } X X if (name[0] == '.' && (name[1] == 0 || name[1] == '.' && name[2] == 0)) { X continue; X } X X display_attrib (name, &st); X X mode = st.st_mode&S_IFMT; X if (mode == S_IFDIR) { X fprintf(outfile,"\n"); X descend(temp); X for (i=0; i<tabs;i++) { X fprintf(outfile,indentstr); X } X fprintf(outfile,"$\n"); X continue; X } X if (mode == S_IFBLK || mode == S_IFCHR) { X fprintf(outfile," %d %d\n",major(st.st_rdev),minor(st.st_rdev)); X continue; X } X#ifdef S_IFLNK X if (mode == S_IFLNK) { X fprintf(outfile, "The file that is linked to goes here.\n"); X continue; X } X#endif X#ifdef S_IFSOCK X if (mode == S_IFSOCK) { X fprintf(outfile," This is ment to be a socket.\n"); X continue; X } X#endif X if (mode == S_IFREG) { X i = origlen; X fprintf(outfile,"%s%s",indentstr,top); X while( temp[i] != '\0') { X fputc(temp[i],outfile); X i++; X } X fprintf(outfile,"\n"); X continue; X } X fprintf(outfile, " /dev/null"); X fprintf(stderr, "File\n\t%s\n is of an invalid mode, made empty.\n", temp); X } X closedir(dirp); X free(temp); X tabs--; X} X X X/* X * Output the specification for a single file X */ X Xdisplay_attrib (name,st) X char *name; X struct stat *st; X{ X int i; X X if (same_uid) X uid = st->st_uid; X if (same_gid) X gid = st->st_gid; X if (same_prot) X prot = st->st_mode&0777; /***** This one is a bit shady *****/ X for (i=0; i<tabs; i++) X fprintf(outfile,indentstr); X fprintf(outfile,"%s%s%c%c%c%3o %d %d", X name, X *name == '\0' ? "" : indentstr, /* stop the tab for a null name */ X (st->st_mode&S_IFMT) == S_IFDIR ? 'd' : X (st->st_mode&S_IFMT) == S_IFCHR ? 'c' : X (st->st_mode&S_IFMT) == S_IFBLK ? 'b' : X#ifdef LINKS X (st->st_mode&S_IFMT) == S_IFLNK ? 'l' : X#endif X#ifdef SOCKETS X (st->st_mode&S_IFMT) == S_IFSOCK ? 's' : X#endif X '-', /*file type*/ X (st->st_mode&S_ISUID) ? 'u' : '-', /*set uid*/ X (st->st_mode&S_ISGID) ? 'g' : '-', /*set gid*/ X prot, X uid, X gid); X} X Xusage(binname) X char *binname; X{ X fprintf(stderr,"usage : %s [options] directory [prot file]\n",binname); X fprintf(stderr,"options:\n"); X fprintf(stderr,"\t-s\t\tuse the same uid, gid and prot as directory\n"); X fprintf(stderr,"\t-u nnn\t\tuse nnn as the uid on all files (default %d)\n",DEF_UID); X fprintf(stderr,"\t-g nnn\t\tuse nnn as the gid on all files (default %d)\n",DEF_GID); X fprintf(stderr,"\t-p nnn\t\tuse nnn as the protection on all file (default %o)\n",DEF_PROT); X fprintf(stderr,"\t-t ROOT\t\tsupply the path for each entry\n"); X fprintf(stderr,"\t-b nnn\t\tset the number of blocks to nnn for file system\n\t\t\t(default %d)\n",DEF_BLOCKS); X fprintf(stderr,"\t-i nnn\t\tset the number of inodes to nnn for file system\n\t\t\t(default %d)\n",DEF_INODES); X fprintf(stderr,"\t-d STRING\tdefine the indentation characters (default %s)\n", DEF_INDENTSTR); X exit(1); X} X Xopen_outfile() X{ X if (proto_file == NULL) X outfile = stdout; X else if ((outfile = fopen(proto_file, "w")) == NULL) X fprintf(stderr, "Cannot create %s\n ", proto_file); X} / echo x - mkproto.doc sed '/^X/s///' > mkproto.doc << '/' X X X Xmkproto(1) USER COMMANDS mkproto(1) X X X XNAME X Mkproto - create a minix prototype file X XSYNOPSIS X mkproto [options] source-directory [proto-file] X XDESCRIPTION X Mkproto creates a mkfs(1) prototype file for the specified X source-directory. The prototype file is either written to X standard output or, if specified, the proto-file. X XOPTIONS X -s Use the same uid, gid and protection as the files X in the source directory. X X -uN Use N as the uid on all files and directories. X X -gN Use N as the gid for all files and directories. X X -pOOO Use OOO (octal) as the protection for all files X and directories. X X -tROOT use the string ROOT as the start to every file X name. Normally the names of the files is based on X the CWD. X X -bN Use N as the number of blocks for the prototype X file. The number of i-nodes will be calculated X using this block value. This is passed to mkfs. X X -iN Use N as the number of i-nodes in the file system. X This is passed to mkfs. X X -dSTR Indent the prototype file using STR instead of a X tab character. X XSEE ALSO X mkfs(1) X XAUTHORS X John Warburton & Andrew Cagney X XBUGS X X X X X X X X X XSun Release 4.0 Last change: 1 X X X X X X / echo x - mkproto.man sed '/^X/s///' > mkproto.man << '/' X.TH mkproto 1 X.SH NAME XMkproto \- create a minix prototype file X.SH SYNOPSIS X.B mkproto X.I [options] source-directory [proto-file] X.SH DESCRIPTION X.B Mkproto Xcreates a mkfs(1) prototype file for the specified X.I source-directory. XThe prototype file is either written to standard output or, if specified, Xthe X.I proto-file. X.SH OPTIONS X.TP 10 X.BI -s XUse the same uid, gid and protection as the files in the source directory. X.TP 10 X.BI -u N XUse X.I N Xas the uid on all files and directories. X.TP 10 X.BI -g N XUse X.I N Xas the gid for all files and directories. X.TP 10 X.BI -p OOO XUse X.I OOO X(octal) as the protection for all files and directories. X.TP 10 X.BI -t ROOT Xuse the string X.I ROOT Xas the start to every file name. Normally the names of the files is based Xon the CWD. X.TP 10 X.BI -b N XUse X.I N Xas the number of blocks for the prototype file. The number of i-nodes will be Xcalculated using this block value. This is passed to mkfs. X.TP 10 X.BI -i N XUse X.I N Xas the number of i-nodes in the file system. This is passed to mkfs. X.TP 10 X.BI -d STR XIndent the prototype file using X.I STR Xinstead of a tab character. X.SH "SEE ALSO" Xmkfs(1) X.SH AUTHORS XJohn Warburton & Andrew Cagney X.SH "BUGS" X /