Example #1
0
static void
f_ibs(char *arg)
{

	if (!(ddflags & C_BS))
		in.dbsz = strsuftoll("input block size", arg, 1, UINT_MAX);
}
Example #2
0
static void
f_obs(char *arg)
{

	if (!(ddflags & C_BS))
		out.dbsz = strsuftoll("output block size", arg, 1, UINT_MAX);
}
Example #3
0
static void
f_files(char *arg)
{

	files_cnt = (u_int)strsuftoll("file count", arg, 0, UINT_MAX);
	if (!files_cnt)
		terminate(0);
}
Example #4
0
static void
f_count(char *arg)
{

	cpy_cnt = strsuftoll("block count", arg, 0, LLONG_MAX);
	if (!cpy_cnt)
		terminate(0);
}
Example #5
0
int
set_option(option_t *options, const char *var, const char *val)
{
	int	i;

	for (i = 0; options[i].name != NULL; i++) {
		if (strcmp(options[i].name, var) != 0)
			continue;
		*options[i].value = (int)strsuftoll(options[i].desc, val,
		    options[i].minimum, options[i].maximum);
		return (1);
	}
	warnx("Unknown option `%s'", var);
	return (0);
}
Example #6
0
static void
config(int argc, char **argv)
{
	int fd, isreg, istmp, ispersistent;
	char full[64], path[MAXPATHLEN];
	off_t bssize;
	dev_t mountdev;
	struct stat sbuf;
	struct statvfs fsbuf;
	struct fss_set fss;

	if (argc < 3)
		usage();

	istmp = ispersistent = 0;

	fss.fss_mount = argv[1];
	fss.fss_bstore = argv[2];

	if (prog_statvfs1(argv[1], &fsbuf, ST_WAIT) != 0 ||
	    prog_stat(argv[1], &sbuf) != 0)
		err(1, "stat %s", argv[1]);
	mountdev = sbuf.st_dev;
	if (stat(argv[2], &sbuf) == 0 &&
	    S_ISREG(sbuf.st_mode) &&
	    sbuf.st_dev == mountdev) {
		if ((sbuf.st_flags & SF_SNAPSHOT) == 0)
			errx(1, "%s: exists and is not a snapshot", argv[2]);
		if (argc != 3)
			usage();
		isreg = ispersistent = 1;

		goto configure;
	}

	if (argc > 5)
		usage();

	if (argc > 3)
		fss.fss_csize = strsuftoll("cluster size", argv[3], 0, INT_MAX);
	else
		fss.fss_csize = 0;
	if (argc > 4)
		bssize = strsuftoll("bs size", argv[4], 0, LLONG_MAX);
	else
		bssize = (off_t)fsbuf.f_blocks*fsbuf.f_frsize;

	/*
	 * Create the backing store. If it is a directory, create a temporary
	 * file and set the unlink flag.
	 */
	fd = prog_open(fss.fss_bstore, O_CREAT|O_TRUNC|O_WRONLY, 0600);
	if (fd < 0) {
		if (errno != EISDIR)
			err(1, "create: %s", fss.fss_bstore);
		snprintf(path, sizeof(path), "%s/XXXXXXXXXX", fss.fss_bstore);
		if ((fd = mkstemp(path)) < 0)
			err(1, "mkstemp: %s", path);
		fss.fss_bstore = path;
		istmp = 1;
	}
	if (prog_fstat(fd, &sbuf) < 0)
		err(1, "stat: %s", fss.fss_bstore);
	if (!ispersistent && sbuf.st_dev == mountdev)
		ispersistent = 1;
	isreg = S_ISREG(sbuf.st_mode);
	if (!ispersistent && isreg && ftruncate(fd, bssize) < 0)
		err(1, "truncate %s", fss.fss_bstore);
	prog_close(fd);

configure:
	fd = opendisk1(argv[0], O_RDWR, full, sizeof(full), 0, prog_open);
	if (fd < 0) {
		if (istmp)
			unlink(fss.fss_bstore);
		err(1, "open: %s", argv[0]);
	}

	fss.fss_flags = 0;
	if ((xflag || istmp) && isreg)
		fss.fss_flags |= FSS_UNLINK_ON_CREATE;

	if (prog_ioctl(fd, FSSIOCSET, &fss) < 0) {
		if (istmp)
			unlink(fss.fss_bstore);
		err(1, "%s: FSSIOCSET", full);
	}

	if (vflag)
		list(1, argv);
}
Example #7
0
static void
f_progress(char *arg)
{

	progress = strsuftoll("progress blocks", arg, 0, LLONG_MAX);
}
Example #8
0
static void
f_skip(char *arg)
{

	in.offset = strsuftoll("skip blocks", arg, 0, LLONG_MAX);
}
Example #9
0
static void
f_seek(char *arg)
{

	out.offset = strsuftoll("seek blocks", arg, 0, LLONG_MAX);
}
Example #10
0
static void
f_cbs(char *arg)
{

	cbsz = strsuftoll("conversion record size", arg, 1, UINT_MAX);
}
Example #11
0
static void
f_bs(char *arg)
{

	in.dbsz = out.dbsz = strsuftoll("block size", arg, 1, UINT_MAX);
}
Example #12
0
int
main(int argc, char *argv[])
{
	char *fb_buf;
	char *infile = NULL;
	pid_t pid = 0, gzippid = 0, deadpid;
	int ch, fd, outpipe[2];
	int ws, gzipstat, cmdstat;
	int eflag = 0, lflag = 0, zflag = 0;
	ssize_t nr, nw, off;
	size_t buffersize;
	struct stat statb;
	struct ttysize ts;

	setprogname(argv[0]);

	/* defaults: Read from stdin, 0 filesize (no completion estimate) */
	fd = STDIN_FILENO;
	filesize = 0;
	buffersize = 64 * 1024;
	prefix = NULL;

	while ((ch = getopt(argc, argv, "b:ef:l:p:z")) != -1)
		switch (ch) {
		case 'b':
			buffersize = (size_t) strsuftoll("buffer size", optarg,
			    0, SIZE_T_MAX);
			break;
		case 'e':
			eflag++;
			break;
		case 'f':
			infile = optarg;
			break;
		case 'l':
			lflag++;
			filesize = strsuftoll("input size", optarg, 0,
			    LLONG_MAX);
			break;
		case 'p':
			prefix = optarg;
			break;
		case 'z':
			zflag++;
			break;
		case '?':
		default:
			usage();
			/* NOTREACHED */
		}
	argc -= optind;
	argv += optind;

	if (argc < 1)
		usage();

	if (infile && (fd = open(infile, O_RDONLY, 0)) < 0)
		err(1, "%s", infile);

	/* stat() to get the filesize unless overridden, or -z */
	if (!zflag && !lflag && (fstat(fd, &statb) == 0)) {
		if (S_ISFIFO(statb.st_mode)) {
			/* stat(2) on pipe may return only the
			 * first few bytes with more coming.
			 * Don't trust!
			 */
		} else {
			filesize = statb.st_size;
		}
	}

	/* gzip -l the file if we have the name and -z is given */
	if (zflag && !lflag && infile != NULL) {
		FILE *gzipsizepipe;
		char buf[256], *cp, *cmd;

		/*
		 * Read second word of last line of gzip -l output. Looks like:
		 * % gzip -l ../etc.tgz 
		 *   compressed uncompressed  ratio uncompressed_name
		 * 	 119737       696320  82.8% ../etc.tar
		 */

		asprintf(&cmd, "gzip -l %s", infile);
		if ((gzipsizepipe = popen(cmd, "r")) == NULL)
			err(1, "reading compressed file length");
		for (; fgets(buf, 256, gzipsizepipe) != NULL;)
		    continue;
		strtoimax(buf, &cp, 10);
		filesize = strtoimax(cp, NULL, 10);
		if (pclose(gzipsizepipe) < 0)
			err(1, "closing compressed file length pipe");
		free(cmd);
	}
	/* Pipe input through gzip -dc if -z is given */
	if (zflag) {
		int gzippipe[2];

		if (pipe(gzippipe) < 0)
			err(1, "gzip pipe");
		gzippid = fork();
		if (gzippid < 0)
			err(1, "fork for gzip");

		if (gzippid) {
			/* parent */
			dup2(gzippipe[0], fd);
			close(gzippipe[0]);
			close(gzippipe[1]);
		} else {
			dup2(gzippipe[1], STDOUT_FILENO);
			dup2(fd, STDIN_FILENO);
			close(gzippipe[0]);
			close(gzippipe[1]);
			if (execlp("gzip", "gzip", "-dc", NULL))
				err(1, "exec()ing gzip");
		}
	}

	/* Initialize progressbar.c's global state */
	bytes = 0;
	progress = 1;
	ttyout = eflag ? stderr : stdout;

	if (ioctl(fileno(ttyout), TIOCGSIZE, &ts) == -1)
		ttywidth = 80;
	else
		ttywidth = ts.ts_cols;

	fb_buf = malloc(buffersize);
	if (fb_buf == NULL)
		err(1, "malloc for buffersize");

	if (pipe(outpipe) < 0)
		err(1, "output pipe");
	pid = fork();
	if (pid < 0)
		err(1, "fork for output pipe");

	if (pid == 0) {
		/* child */
		dup2(outpipe[0], STDIN_FILENO);
		close(outpipe[0]);
		close(outpipe[1]);
		execvp(argv[0], argv);
		err(1, "could not exec %s", argv[0]);
	}
	close(outpipe[0]);

	signal(SIGPIPE, broken_pipe);
	progressmeter(-1);

	while ((nr = read(fd, fb_buf, buffersize)) > 0)
		for (off = 0; nr; nr -= nw, off += nw, bytes += nw)
			if ((nw = write(outpipe[1], fb_buf + off,
			    (size_t) nr)) < 0) {
				progressmeter(1);
				err(1, "writing %u bytes to output pipe",
							(unsigned) nr);
			}
	close(outpipe[1]);

	gzipstat = 0;
	cmdstat = 0;
	while (pid || gzippid) {
		deadpid = wait(&ws);
		/*
		 * We need to exit with an error if the command (or gzip)
		 * exited abnormally.
		 * Unfortunately we can't generate a true 'exited by signal'
		 * error without sending the signal to ourselves :-(
		 */
		ws = WIFSIGNALED(ws) ? WTERMSIG(ws) : WEXITSTATUS(ws);

		if (deadpid != -1 && errno == EINTR)
			continue;
		if (deadpid == pid) {
			pid = 0;
			cmdstat = ws;
			continue;
		}
		if (deadpid == gzippid) {
			gzippid = 0;
			gzipstat = ws;
			continue;
		}
		break;
	}

	progressmeter(1);
	signal(SIGPIPE, SIG_DFL);

	free(fb_buf);

	exit(cmdstat ? cmdstat : gzipstat);
}
Example #13
0
int
main(int argc, char *argv[])
{
	struct stat	 sb;
	struct timeval	 start;
	fstype_t	*fstype;
	fsinfo_t	 fsoptions;
	fsnode		*root;
	int	 	 ch, i, len;
	char		*subtree;
	char		*specfile;

	setprogname(argv[0]);

	debug = 0;
	if ((fstype = get_fstype(DEFAULT_FSTYPE)) == NULL)
		errx(1, "Unknown default fs type `%s'.", DEFAULT_FSTYPE);

		/* set default fsoptions */
	(void)memset(&fsoptions, 0, sizeof(fsoptions));
	fsoptions.fd = -1;
	fsoptions.sectorsize = -1;

	if (fstype->prepare_options)
		fstype->prepare_options(&fsoptions);

	specfile = NULL;
	if (gettimeofday(&start, NULL) == -1)
		err(1, "Unable to get system time");

	start_time.tv_sec = start.tv_sec;
	start_time.tv_nsec = start.tv_usec * 1000;

	while ((ch = getopt(argc, argv, "B:b:Dd:f:F:M:m:N:o:pr:s:S:t:xZ")) != -1) {
		switch (ch) {

		case 'B':
			if (strcmp(optarg, "be") == 0 ||
			    strcmp(optarg, "4321") == 0 ||
			    strcmp(optarg, "big") == 0) {
#if BYTE_ORDER == LITTLE_ENDIAN
				fsoptions.needswap = 1;
#endif
			} else if (strcmp(optarg, "le") == 0 ||
			    strcmp(optarg, "1234") == 0 ||
			    strcmp(optarg, "little") == 0) {
#if BYTE_ORDER == BIG_ENDIAN
				fsoptions.needswap = 1;
#endif
			} else {
				warnx("Invalid endian `%s'.", optarg);
				usage();
			}
			break;

		case 'b':
			len = strlen(optarg) - 1;
			if (optarg[len] == '%') {
				optarg[len] = '\0';
				fsoptions.freeblockpc =
				    strsuftoll("free block percentage",
					optarg, 0, 99);
			} else {
				fsoptions.freeblocks =
				    strsuftoll("free blocks",
					optarg, 0, LLONG_MAX);
			}
			break;

		case 'D':
			dupsok = 1;
			break;

		case 'd':
			debug = strtoll(optarg, NULL, 0);
			break;

		case 'f':
			len = strlen(optarg) - 1;
			if (optarg[len] == '%') {
				optarg[len] = '\0';
				fsoptions.freefilepc =
				    strsuftoll("free file percentage",
					optarg, 0, 99);
			} else {
				fsoptions.freefiles =
				    strsuftoll("free files",
					optarg, 0, LLONG_MAX);
			}
			break;

		case 'F':
			specfile = optarg;
			break;

		case 'M':
			fsoptions.minsize =
			    strsuftoll("minimum size", optarg, 1LL, LLONG_MAX);
			break;

		case 'N':
			if (! setup_getid(optarg))
				errx(1,
			    "Unable to use user and group databases in `%s'",
				    optarg);
			break;

		case 'm':
			fsoptions.maxsize =
			    strsuftoll("maximum size", optarg, 1LL, LLONG_MAX);
			break;
			
		case 'o':
		{
			char *p;

			while ((p = strsep(&optarg, ",")) != NULL) {
				if (*p == '\0')
					errx(1, "Empty option");
				if (! fstype->parse_options(p, &fsoptions))
					usage();
			}
			break;
		}
		case 'p':
			/* Deprecated in favor of 'Z' */
			fsoptions.sparse = 1;
			break;

		case 'r':
			/* Round image size up to specified block size */
			fsoptions.roundup =
			    strsuftoll("roundup", optarg, 0, LLONG_MAX);
			break;

		case 's':
			fsoptions.minsize = fsoptions.maxsize =
			    strsuftoll("size", optarg, 1LL, LLONG_MAX);
			break;

		case 'S':
			fsoptions.sectorsize =
			    (int)strsuftoll("sector size", optarg,
				1LL, INT_MAX);
			break;

		case 't':
			/* Check current one and cleanup if necessary. */
			if (fstype->cleanup_options)
				fstype->cleanup_options(&fsoptions);
			fsoptions.fs_specific = NULL;
			if ((fstype = get_fstype(optarg)) == NULL)
				errx(1, "Unknown fs type `%s'.", optarg);
			fstype->prepare_options(&fsoptions);
			break;

		case 'x':
			fsoptions.onlyspec = 1;
			break;

		case 'Z':
			/* Superscedes 'p' for compatibility with NetBSD makefs(8) */
			fsoptions.sparse = 1;
			break;

		case '?':
		default:
			usage();
			/* NOTREACHED */

		}
	}
	if (debug) {
		printf("debug mask: 0x%08x\n", debug);
		printf("start time: %ld.%ld, %s",
		    (long)start_time.tv_sec, (long)start_time.tv_nsec,
		    ctime(&start_time.tv_sec));
	}
	argc -= optind;
	argv += optind;

	if (argc < 2)
		usage();

	/* -x must be accompanied by -F */
	if (fsoptions.onlyspec != 0 && specfile == NULL)
		errx(1, "-x requires -F mtree-specfile.");

	/* Accept '-' as meaning "read from standard input". */
	if (strcmp(argv[1], "-") == 0)
		sb.st_mode = S_IFREG;
	else {
		if (stat(argv[1], &sb) == -1)
			err(1, "Can't stat `%s'", argv[1]);
	}

	switch (sb.st_mode & S_IFMT) {
	case S_IFDIR:		/* walk the tree */
		subtree = argv[1];
		TIMER_START(start);
		root = walk_dir(subtree, ".", NULL, NULL);
		TIMER_RESULTS(start, "walk_dir");
		break;
	case S_IFREG:		/* read the manifest file */
		subtree = ".";
		TIMER_START(start);
		root = read_mtree(argv[1], NULL);
		TIMER_RESULTS(start, "manifest");
		break;
	default:
		errx(1, "%s: not a file or directory", argv[1]);
		/* NOTREACHED */
	}

	/* append extra directory */
	for (i = 2; i < argc; i++) {
		if (stat(argv[i], &sb) == -1)
			err(1, "Can't stat `%s'", argv[i]);
		if (!S_ISDIR(sb.st_mode))
			errx(1, "%s: not a directory", argv[i]);
		TIMER_START(start);
		root = walk_dir(argv[i], ".", NULL, root);
		TIMER_RESULTS(start, "walk_dir2");
	}

	if (specfile) {		/* apply a specfile */
		TIMER_START(start);
		apply_specfile(specfile, subtree, root, fsoptions.onlyspec);
		TIMER_RESULTS(start, "apply_specfile");
	}

	if (debug & DEBUG_DUMP_FSNODES) {
		printf("\nparent: %s\n", subtree);
		dump_fsnodes(root);
		putchar('\n');
	}

				/* build the file system */
	TIMER_START(start);
	fstype->make_fs(argv[0], subtree, root, &fsoptions);
	TIMER_RESULTS(start, "make_fs");

	free_fsnodes(root);

	exit(0);
	/* NOTREACHED */
}