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
/