249 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			249 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/* mkproto - make an mkfs prototype	Author: Andrew Cagney */
 | 
						|
 | 
						|
/* Submitted by: cagney@chook.ua.oz (Andrew Cagney - aka Noid) */
 | 
						|
 | 
						|
#include <sys/types.h>
 | 
						|
#include <sys/stat.h>
 | 
						|
#include <limits.h>
 | 
						|
#include <dirent.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <string.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include <unistd.h>
 | 
						|
 | 
						|
/* The default values for the prototype file */
 | 
						|
#define DEF_UID		2	/* bin */
 | 
						|
#define DEF_GID		1	/* daemon group */
 | 
						|
#define DEF_PROT	0555	/* a=re */
 | 
						|
#define DEF_BLOCKS	360
 | 
						|
#define DEF_INODES	63
 | 
						|
#define DEF_INDENTSTR	"\t"
 | 
						|
 | 
						|
#define major(x) ( (x>>8) & 0377)
 | 
						|
#define minor(x) (x & 0377)
 | 
						|
 | 
						|
/* Globals. */
 | 
						|
int count, origlen, tabs;
 | 
						|
int gid, uid, prot, same_uid, same_gid, same_prot, blocks, inodes;
 | 
						|
int block_given, inode_given, dprot;
 | 
						|
char *indentstr;
 | 
						|
char *proto_file, *top;
 | 
						|
FILE *outfile;
 | 
						|
 | 
						|
extern int optind;
 | 
						|
extern char *optarg;
 | 
						|
 | 
						|
_PROTOTYPE(int main, (int argc, char **argv));
 | 
						|
_PROTOTYPE(void descend, (char *dirname));
 | 
						|
_PROTOTYPE(void display_attrib, (char *name, struct stat *st));
 | 
						|
_PROTOTYPE(void usage, (char *binname));
 | 
						|
_PROTOTYPE(void open_outfile, (void));
 | 
						|
 | 
						|
int main(argc, argv)
 | 
						|
int argc;
 | 
						|
char *argv[];
 | 
						|
{
 | 
						|
  char *dir;
 | 
						|
  struct stat st;
 | 
						|
  int op;
 | 
						|
 | 
						|
  gid = DEF_GID;
 | 
						|
  uid = DEF_UID;
 | 
						|
  prot = DEF_PROT;
 | 
						|
  blocks = DEF_BLOCKS;
 | 
						|
  inodes = DEF_INODES;
 | 
						|
  indentstr = DEF_INDENTSTR;
 | 
						|
  inode_given = 0;
 | 
						|
  block_given = 0;
 | 
						|
  top = 0;
 | 
						|
  same_uid = 0;
 | 
						|
  same_gid = 0;
 | 
						|
  same_prot = 0;
 | 
						|
  while ((op = getopt(argc, argv, "b:g:i:p:t:u:d:s")) != EOF) {
 | 
						|
	switch (op) {
 | 
						|
	    case 'b':
 | 
						|
		blocks = atoi(optarg);
 | 
						|
		block_given = 1;
 | 
						|
		break;
 | 
						|
	    case 'g':
 | 
						|
		gid = atoi(optarg);
 | 
						|
		if (gid == 0) usage(argv[0]);
 | 
						|
		same_gid = 0;
 | 
						|
		break;
 | 
						|
	    case 'i':
 | 
						|
		inodes = atoi(optarg);
 | 
						|
		inode_given = 1;
 | 
						|
		break;
 | 
						|
	    case 'p':
 | 
						|
		sscanf(optarg, "%o", &prot);
 | 
						|
		if (prot == 0) usage(argv[0]);
 | 
						|
		same_prot = 0;
 | 
						|
		break;
 | 
						|
	    case 's':
 | 
						|
		same_prot = 1;
 | 
						|
		same_uid = 1;
 | 
						|
		same_gid = 1;
 | 
						|
		break;
 | 
						|
	    case 't':	top = optarg;	break;
 | 
						|
	    case 'u':
 | 
						|
		uid = atoi(optarg);
 | 
						|
		if (uid == 0) usage(argv[0]);
 | 
						|
		same_uid = 0;
 | 
						|
		break;
 | 
						|
	    case 'd':	indentstr = optarg;	break;
 | 
						|
	    default:		/* Illegal options */
 | 
						|
		usage(argv[0]);
 | 
						|
	}
 | 
						|
  }
 | 
						|
 | 
						|
  if (optind >= argc) {
 | 
						|
	usage(argv[0]);
 | 
						|
  } else {
 | 
						|
	dir = argv[optind];
 | 
						|
	optind++;
 | 
						|
	proto_file = argv[optind];
 | 
						|
  }
 | 
						|
  if (!top) top = dir;
 | 
						|
  open_outfile();
 | 
						|
  if (block_given && !inode_given) inodes = (blocks / 3) + 8;
 | 
						|
  if (!block_given && inode_given) usage(argv[0]);
 | 
						|
  count = 1;
 | 
						|
  tabs = 0;
 | 
						|
  origlen = strlen(dir);
 | 
						|
 | 
						|
  /* Check that it really is a directory */
 | 
						|
  stat(dir, &st);
 | 
						|
  if ((st.st_mode & S_IFMT) != S_IFDIR) {
 | 
						|
	fprintf(stderr, "mkproto: %s must be a directory\n", dir);
 | 
						|
	usage(argv[0]);
 | 
						|
  }
 | 
						|
  fprintf(outfile, "boot\n%d %d\n", blocks, inodes);
 | 
						|
  display_attrib("", &st);
 | 
						|
  fprintf(outfile, "\n");
 | 
						|
  descend(dir);
 | 
						|
  fprintf(outfile, "$\n");
 | 
						|
  return(0);
 | 
						|
}
 | 
						|
 | 
						|
/* Output the prototype spec for this directory. */
 | 
						|
void descend(dirname)
 | 
						|
char *dirname;
 | 
						|
{
 | 
						|
  struct dirent *dp;
 | 
						|
  DIR *dirp;
 | 
						|
  char *name, *temp, *tempend;
 | 
						|
  int i;
 | 
						|
  struct stat st;
 | 
						|
  mode_t mode;
 | 
						|
 | 
						|
  dirp = opendir(dirname);
 | 
						|
  if (dirp == NULL) {
 | 
						|
	fprintf(stderr, "unable to open directory %s\n", dirname);
 | 
						|
	return;
 | 
						|
  }
 | 
						|
  tabs++;
 | 
						|
  temp = (char *) malloc(sizeof(char) * strlen(dirname) +1 + PATH_MAX);
 | 
						|
  strcpy(temp, dirname);
 | 
						|
  strcat(temp, "/");
 | 
						|
  tempend = &temp[strlen(temp)];
 | 
						|
 | 
						|
  for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
 | 
						|
	name = dp->d_name;
 | 
						|
 | 
						|
	count++;
 | 
						|
	strcpy(tempend, name);
 | 
						|
 | 
						|
	if (stat(temp, &st) == -1) {
 | 
						|
		fprintf(stderr, "cant get status of '%s' \n", temp);
 | 
						|
		continue;
 | 
						|
	}
 | 
						|
	if (name[0] == '.' && (name[1] == 0 ||
 | 
						|
	    (name[1] == '.' && name[2] == 0)))
 | 
						|
		continue;
 | 
						|
 | 
						|
	display_attrib(name, &st);
 | 
						|
 | 
						|
	mode = st.st_mode & S_IFMT;
 | 
						|
	if (mode == S_IFDIR) {
 | 
						|
		fprintf(outfile, "\n");
 | 
						|
		descend(temp);
 | 
						|
		for (i = 0; i < tabs; i++) {
 | 
						|
			fprintf(outfile, indentstr);
 | 
						|
		}
 | 
						|
		fprintf(outfile, "$\n");
 | 
						|
		continue;
 | 
						|
	}
 | 
						|
	if (mode == S_IFBLK || mode == S_IFCHR) {
 | 
						|
		fprintf(outfile, " %d %d\n", major(st.st_rdev), minor(st.st_rdev));
 | 
						|
		continue;
 | 
						|
	}
 | 
						|
	if (mode == S_IFREG) {
 | 
						|
		i = origlen;
 | 
						|
		fprintf(outfile, "%s%s", indentstr, top);
 | 
						|
		while (temp[i] != '\0') {
 | 
						|
			fputc(temp[i], outfile);
 | 
						|
			i++;
 | 
						|
		}
 | 
						|
		fprintf(outfile, "\n");
 | 
						|
		continue;
 | 
						|
	}
 | 
						|
	fprintf(outfile, " /dev/null");
 | 
						|
	fprintf(stderr,"File\n\t%s\n has an invalid mode, made empty.\n",temp);
 | 
						|
  }
 | 
						|
  closedir(dirp);
 | 
						|
  free(temp);
 | 
						|
  tabs--;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void display_attrib(name, st)
 | 
						|
char *name;
 | 
						|
struct stat *st;
 | 
						|
{
 | 
						|
/* Output the specification for a single file */
 | 
						|
 | 
						|
  int i;
 | 
						|
 | 
						|
  if (same_uid) uid = st->st_uid;
 | 
						|
  if (same_gid) gid = st->st_gid;
 | 
						|
  if (same_prot)
 | 
						|
	prot = st->st_mode & 0777;	/***** This one is a bit shady *****/
 | 
						|
  for (i = 0; i < tabs; i++) fprintf(outfile, indentstr);
 | 
						|
  fprintf(outfile, "%s%s%c%c%c%3o %d %d",
 | 
						|
	name,
 | 
						|
	*name == '\0' ? "" : indentstr,	/* stop the tab for a null name */
 | 
						|
	(st->st_mode & S_IFMT) == S_IFDIR ? 'd' :
 | 
						|
	(st->st_mode & S_IFMT) == S_IFCHR ? 'c' :
 | 
						|
	(st->st_mode & S_IFMT) == S_IFBLK ? 'b' :
 | 
						|
	'-',			/* file type */
 | 
						|
	(st->st_mode & S_ISUID) ? 'u' : '-',	/* set uid */
 | 
						|
	(st->st_mode & S_ISGID) ? 'g' : '-',	/* set gid */
 | 
						|
	prot,
 | 
						|
	uid,
 | 
						|
	gid);
 | 
						|
}
 | 
						|
 | 
						|
void usage(binname)
 | 
						|
char *binname;
 | 
						|
{
 | 
						|
  fprintf(stderr, "Usage: %s [options] source_directory [prototype_file]\n", binname);
 | 
						|
  fprintf(stderr, "options:\n");
 | 
						|
  fprintf(stderr, "   -b n\t\t file system size is n blocks (default %d)\n", DEF_BLOCKS);
 | 
						|
  fprintf(stderr, "   -d STRING\t define the indentation characters (default %s)\n", "(none)");
 | 
						|
  fprintf(stderr, "   -g n\t\t use n as the gid on all files (default %d)\n", DEF_GID);
 | 
						|
  fprintf(stderr, "   -i n\t\t file system gets n i-nodes (default %d)\n", DEF_INODES);
 | 
						|
  fprintf(stderr, "   -p nnn\t use nnn (octal) as mode on all files (default %o)\n", DEF_PROT);
 | 
						|
  fprintf(stderr, "   -s  \t\t use the same uid, gid and mode as originals have\n");
 | 
						|
  fprintf(stderr, "   -t ROOT\t inital path prefix for each entry\n");
 | 
						|
  fprintf(stderr, "   -u n\t\t use nnn as the uid on all files (default %d)\n", DEF_UID);
 | 
						|
  exit(1);
 | 
						|
}
 | 
						|
 | 
						|
void open_outfile()
 | 
						|
{
 | 
						|
  if (proto_file == NULL)
 | 
						|
	outfile = stdout;
 | 
						|
  else if ((outfile = fopen(proto_file, "w")) == NULL)
 | 
						|
	fprintf(stderr, "Cannot create %s\n ", proto_file);
 | 
						|
}
 |