예제 #1
0
파일: setfiles.c 프로젝트: mgrepl/selinux
int main(int argc, char **argv)
{
	struct stat sb;
	int opt, i = 0;
	const char *input_filename = NULL;
	int use_input_file = 0;
	char *buf = NULL;
	size_t buf_len;
	int recurse; /* Recursive descent. */
	const char *base;
	int mass_relabel = 0, errors = 0;
	const char *ropts = "e:f:hilno:pqrsvFRW0";
	const char *sopts = "c:de:f:hilno:pqr:svFR:W0";
	const char *opts;
	
	memset(&r_opts, 0, sizeof(r_opts));

	/* Initialize variables */
	r_opts.progress = 0;
	r_opts.count = 0;
	r_opts.nfile = 0;
	r_opts.debug = 0;
	r_opts.change = 1;
	r_opts.verbose = 0;
	r_opts.logging = 0;
	r_opts.rootpath = NULL;
	r_opts.rootpathlen = 0;
	r_opts.outfile = NULL;
	r_opts.force = 0;
	r_opts.hard_links = 1;

	altpath = NULL;

	r_opts.progname = strdup(argv[0]);
	if (!r_opts.progname) {
		fprintf(stderr, "%s:  Out of memory!\n", argv[0]);
		exit(-1);
	}
	base = basename(r_opts.progname);
	
	if (!strcmp(base, SETFILES)) {
		/* 
		 * setfiles:  
		 * Recursive descent,
		 * Does not expand paths via realpath, 
		 * Aborts on errors during the file tree walk, 
		 * Try to track inode associations for conflict detection,
		 * Does not follow mounts,
		 * Validates all file contexts at init time. 
		 */
		iamrestorecon = 0;
		recurse = 1;
		r_opts.expand_realpath = 0;
		r_opts.abort_on_error = 1;
		r_opts.add_assoc = 1;
		r_opts.fts_flags = FTS_PHYSICAL | FTS_XDEV;
		ctx_validate = 1;
		opts = sopts;
	} else {
		/*
		 * restorecon:  
		 * No recursive descent unless -r/-R,
		 * Expands paths via realpath, 
		 * Do not abort on errors during the file tree walk,
		 * Do not try to track inode associations for conflict detection,
		 * Follows mounts,
		 * Does lazy validation of contexts upon use. 
		 */
		if (strcmp(base, RESTORECON) && !r_opts.quiet) 
			printf("Executed with an unrecognized name (%s), defaulting to %s behavior.\n", base, RESTORECON);
		iamrestorecon = 1;
		recurse = 0;
		r_opts.expand_realpath = 1;
		r_opts.abort_on_error = 0;
		r_opts.add_assoc = 0;
		r_opts.fts_flags = FTS_PHYSICAL;
		ctx_validate = 0;
		opts = ropts;

		/* restorecon only:  silent exit if no SELinux.
		   Allows unconditional execution by scripts. */
		if (is_selinux_enabled() <= 0)
			exit(0);
	}

	/* This must happen before getopt. */
	r_opts.nfile = exclude_non_seclabel_mounts();

	if (iamrestorecon) 
		opts = ropts;
	else
		opts = sopts;
		
	/* Process any options. */
	while ((opt = getopt(argc, argv, opts)) > 0) {
		switch (opt) {
		case 'c':
			{
				FILE *policystream;

				if (iamrestorecon)
					usage(argv[0]);

				policyfile = optarg;

				policystream = fopen(policyfile, "r");
				if (!policystream) {
					fprintf(stderr,
						"Error opening %s: %s\n",
						policyfile, strerror(errno));
					exit(-1);
				}
				__fsetlocking(policystream,
					      FSETLOCKING_BYCALLER);

				if (sepol_set_policydb_from_file(policystream) <
				    0) {
					fprintf(stderr,
						"Error reading policy %s: %s\n",
						policyfile, strerror(errno));
					exit(-1);
				}
				fclose(policystream);

				ctx_validate = 1;

				break;
			}
		case 'e':
			remove_exclude(optarg);
			if (lstat(optarg, &sb) < 0 && errno != EACCES) {
				fprintf(stderr, "Can't stat exclude path \"%s\", %s - ignoring.\n",
					optarg, strerror(errno));
				break;
			}
			if (add_exclude(optarg))
				exit(-1);
			break;
		case 'f':
			use_input_file = 1;
			input_filename = optarg;
			break;			
		case 'd':
			if (iamrestorecon)
				usage(argv[0]);
			r_opts.debug = 1;
			break;
		case 'i':
			r_opts.ignore_enoent = 1;
			break;
		case 'l':
			r_opts.logging = 1;
			break;
		case 'F':
			r_opts.force = 1;
			break;
		case 'n':
			r_opts.change = 0;
			break;
		case 'o':
			if (strcmp(optarg, "-") == 0) {
				r_opts.outfile = stdout;
				break;
			}

			r_opts.outfile = fopen(optarg, "w");
			if (!r_opts.outfile) {
				fprintf(stderr, "Error opening %s: %s\n",
					optarg, strerror(errno));

				usage(argv[0]);
			}
			__fsetlocking(r_opts.outfile, FSETLOCKING_BYCALLER);
			break;
		case 'q':
			r_opts.quiet = 1;
			break;
		case 'R':
		case 'r':
			if (iamrestorecon) {
				recurse = 1;
				break;
			}
			if (NULL != r_opts.rootpath) {
				fprintf(stderr,
					"%s: only one -r can be specified\n",
					argv[0]);
				exit(-1);
			}
			set_rootpath(optarg);
			break;
		case 's':
			use_input_file = 1;
			input_filename = "-";
			r_opts.add_assoc = 0;
			break;
		case 'v':
			if (r_opts.progress) {
				fprintf(stderr,
					"Progress and Verbose mutually exclusive\n");
				usage(argv[0]);
			}
			r_opts.verbose++;
			break;
		case 'p':
			if (r_opts.verbose) {
				fprintf(stderr,
					"Progress and Verbose mutually exclusive\n");
				usage(argv[0]);
			}
			r_opts.progress++;
			break;
		case 'W':
			warn_no_match = 1;
			break;
		case '0':
			null_terminated = 1;
			break;
		case 'h':
		case '?':
			usage(argv[0]);
		}
	}

	for (i = optind; i < argc; i++) {
		if (!strcmp(argv[i], "/")) {
			mass_relabel = 1;
			if (r_opts.progress)
				r_opts.progress++;
		}
	}

	if (!iamrestorecon) {
		if (policyfile) {
			if (optind != (argc - 1))
				usage(argv[0]);
		} else if (use_input_file) {
			if (optind != (argc - 1)) {
				/* Cannot mix with pathname arguments. */
				usage(argv[0]);
			}
		} else {
			if (optind > (argc - 2))
				usage(argv[0]);
		}

		/* Use our own invalid context checking function so that
		   we can support either checking against the active policy or
		   checking against a binary policy file. */
		selinux_set_callback(SELINUX_CB_VALIDATE,
				     (union selinux_callback)&canoncon);

		if (stat(argv[optind], &sb) < 0) {
			perror(argv[optind]);
			exit(-1);
		}
		if (!S_ISREG(sb.st_mode)) {
			fprintf(stderr, "%s:  spec file %s is not a regular file.\n",
				argv[0], argv[optind]);
			exit(-1);
		}

		altpath = argv[optind];
		optind++;
	} else if (argc == 1)
		usage(argv[0]);

	/* Load the file contexts configuration and check it. */
	r_opts.selabel_opt_validate = (ctx_validate ? (char *)1 : NULL);
	r_opts.selabel_opt_path = altpath;

	if (nerr)
		exit(-1);

	restore_init(&r_opts);
	if (use_input_file) {
		FILE *f = stdin;
		ssize_t len;
		int delim;
		if (strcmp(input_filename, "-") != 0)
			f = fopen(input_filename, "r");
		if (f == NULL) {
			fprintf(stderr, "Unable to open %s: %s\n", input_filename,
				strerror(errno));
			usage(argv[0]);
		}
		__fsetlocking(f, FSETLOCKING_BYCALLER);

		delim = (null_terminated != 0) ? '\0' : '\n';
		while ((len = getdelim(&buf, &buf_len, delim, f)) > 0) {
			buf[len - 1] = 0;
			if (!strcmp(buf, "/"))
				mass_relabel = 1;
			errors |= process_glob(buf, recurse) < 0;
		}
		if (strcmp(input_filename, "-") != 0)
			fclose(f);
	} else {
		for (i = optind; i < argc; i++)
			errors |= process_glob(argv[i], recurse) < 0;
	}
	
	maybe_audit_mass_relabel(mass_relabel, errors);

	if (warn_no_match)
		selabel_stats(r_opts.hnd);

	selabel_close(r_opts.hnd);
	restore_finish();

	if (r_opts.outfile)
		fclose(r_opts.outfile);

	if (r_opts.progress && r_opts.count >= STAR_COUNT)
		printf("\n");
	exit(errors ? -1: 0);
}
예제 #2
0
파일: copy.c 프로젝트: marwatk/TivoTools
int
copy_main (int argc, char **argv)
{
	char source_a[PATH_MAX], source_b[PATH_MAX];
	char dest_a[PATH_MAX], dest_b[PATH_MAX];
	char *tmp;
	struct backup_info *info_b, *info_r;
	int opt, loop, thresh = 0, threshopt = 0;
	unsigned int varsize = 0, swapsize = 0;
	unsigned int bflags = BF_BACKUPVAR, rflags = 0;
	int quiet = 0;
	int bswap = 0;
	int expand = 0;
	int expandscale = 2;

	tivo_partition_direct ();

	while ((opt = getopt (argc, argv, "hqf:L:tTaspxr:v:S:lbBzE")) > 0)
	{
		switch (opt)
		{
		case 'q':
			quiet++;
			break;
		case 's':
			bflags |= BF_SHRINK;
			break;
		case 'E':
			bflags |= BF_TRUNCATED;
			break;
		case 'f':
			if (threshopt)
			{
				fprintf (stderr, "%s: -f and -%c cannot be used together\n", argv[0], threshopt);
				return 1;
			}
			threshopt = loop;
			thresh = strtoul (optarg, &tmp, 10);
			if (*tmp)
			{
				fprintf (stderr, "%s: Non integer argument to -f\n", argv[0]);
				return 1;
			}
			break;
		case 'L':
			if (threshopt)
			{
				fprintf (stderr, "%s: -l and -%c cannot be used together\n", argv[0], threshopt);
				return 1;
			}
			threshopt = loop;
			thresh = strtoul (optarg, &tmp, 10);
			thresh *= 1024 * 2;
			bflags |= BF_THRESHSIZE;
			if (*tmp)
			{
				fprintf (stderr, "%s: Non integer argument to -L\n", argv[0]);
				return 1;
			}
			break;
		case 't':
			bflags |= BF_THRESHTOT;
			break;
		case 'T':
			bflags |= BF_STREAMTOT;
			break;
		case 'a':
			if (threshopt)
			{
				fprintf (stderr, "%s: -a and -%c cannot be used together\n", argv[0], threshopt);
				return 1;
			}
			threshopt = loop;
			thresh = ~0;
			break;

		case 'v':
			bflags &= ~BF_BACKUPVAR;
			varsize = strtoul (optarg, &tmp, 10);
			varsize *= 1024 * 2;
			if (tmp && *tmp)
			{
				fprintf (stderr, "%s: Integer argument expected for -v.\n", argv[0]);
				return 1;
			}
			break;
		case 'S':
			swapsize = strtoul (optarg, &tmp, 10);
			swapsize *= 1024 * 2;
			if (tmp && *tmp)
			{
				fprintf (stderr, "%s: Integer argument expected for -s.\n", argv[0]);
				return 1;
			}
			break;
		case 'z':
			rflags |= RF_ZEROPART;
			break;
		case 'b':
			if (bswap != 0)
			{
				fprintf (stderr, "%s: Only one byte swapping option (-b/-B) allowed.\n", argv[0]);
				return 1;
			}
			bswap = -1;
			break;
		case 'B':
			if (bswap != 0)
			{
				fprintf (stderr, "%s: Only one byte swapping option (-b/-B) allowed.\n", argv[0]);
				return 1;
			}
			bswap = 1;
			break;
		case 'p':
			rflags |= RF_BALANCE;
			break;
		case 'l':
			rflags |= RF_NOFILL;
			break;
		case 'x':
			expand = 1;
			break;
		case 'r':
			expandscale = strtoul (optarg, &tmp, 10);
			if (tmp && *tmp)
			{
				fprintf (stderr, "%s: Integer argument expected for -r.\n", argv[0]);
				return 1;
			}
			if (expandscale < 0 || expandscale > 4)
			{
				fprintf (stderr, "%s: Scale value for -r must be in the range 0 to 4.\n", argv[0]);
				return 1;
			}
			break;
		default:
			copy_usage (argv[0]);
			return 1;
		}
	}

	// Split out the drive names
	source_a[0] = 0;
	source_b[0] = 0;
	dest_a[0] = 0;
	dest_b[0] = 0;

	if (argc - optind < 4)
	{
		if (optind < argc)
		{
			get_drives (argv[optind++], source_a, source_b);
		}
		if (optind < argc)
		{
			get_drives (argv[optind++], dest_a, dest_b);
		}
	}
	else
	{
// Special case for convenience - 2 source and 2 target named
		strcpy (source_a, argv[optind++]);
		strcpy (source_b, argv[optind++]);
		strcpy (dest_a, argv[optind++]);
		strcpy (dest_b, argv[optind++]);
	}

	if (optind < argc || !*source_a || !*dest_a)
	{
		copy_usage (argv[0]);
		return 1;
	}

	if (expand > 0)
		rflags |= RF_NOFILL;

	info_b = init_backup (source_a, source_b, bflags);

	// Try to continue anyway despite error.
	if (bflags & BF_TRUNCATED && backup_has_error (info_b))
	{
		backup_perror (info_b, "WARNING");
		fprintf (stderr, "Attempting copy anyway\n");
		backup_check_truncated_volume (info_b);
		if (info_b && backup_has_error (info_b))
		{
			backup_perror (info_b, "Copy source");
			return 1;
		}
	}

	if (info_b && backup_has_error (info_b))
	{
		backup_perror (info_b, "Copy source");

		fprintf (stderr, "To attempt copy anyway, try again with -E.  -s is implied by -E.\n");
		return 1;
	}

	info_r = init_restore (rflags);
	if (info_r && restore_has_error (info_r))
	{
		restore_perror (info_r, "Copy target");
		return 1;
	}

	if (!info_b || !info_r)
	{
		fprintf (stderr, "%s: Copy failed to start.  Make sure you specified the right\ndevices, and that the drives are not locked.\n", argv[0]);
		return 1;
	}
	else
	{
		unsigned starttime;
		char buf[BUFSIZE];
		unsigned int curcount = 0;
		int nread, nwrit;

		if (threshopt)
			backup_set_thresh (info_b, thresh);

		if (varsize)
			restore_set_varsize (info_r, varsize);
		if (swapsize)
			restore_set_swapsize (info_r, swapsize);
		if (bswap)
			restore_set_bswap (info_r, bswap);

		if (quiet < 2)
			fprintf (stderr, "Scanning source drive.  Please wait a moment.\n");

		if (backup_start (info_b) < 0)
		{
			if (backup_has_error (info_b))
				backup_perror (info_b, "Copy source");
			else
				fprintf (stderr, "Copy source failed.\n");
			return 1;
		}

// Fill the buffer up to start.  Restore needs some information to bootstrap
// the process.
		while (curcount < BUFSIZE && (nread = backup_read (info_b, buf, BUFSIZE - curcount)) > 0)
		{
			curcount += nread;
		}

		if (curcount < BUFSIZE)
		{
			if (backup_has_error (info_b))
				backup_perror (info_b, "Copy source");
			else
				fprintf (stderr, "Copy source failed.\n");
			return 1;
		}

		nread = curcount;

		nwrit = restore_write (info_r, buf, nread);
		if (nwrit < 0)
		{
			if (restore_has_error (info_r))
				restore_perror (info_r, "Copy target");
			else
				fprintf (stderr, "Copy target failed.\n");
			return 1;
		}

		if (restore_trydev (info_r, dest_a, dest_b) < 0)
		{
			if (restore_has_error (info_r))
				restore_perror (info_r, "Copy target");
			else
				fprintf (stderr, "Copy target failed.\n");
			return 1;
		}

		if (restore_start (info_r) < 0)
		{
			if (restore_has_error (info_r))
				restore_perror (info_r, "Copy target");
			else
				fprintf (stderr, "Copy target failed.\n");
			return 1;
		}

		if (restore_write (info_r, buf + nwrit, nread - nwrit) != nread - nwrit)
		{
			if (restore_has_error (info_r))
				restore_perror (info_r, "Copy target");
			else
				fprintf (stderr, "Copy target failed.\n");
			return 1;
		}

		starttime = time (NULL);

		fprintf (stderr, "Starting copy\nSize: %d megabytes\n", info_r->nsectors / 2048);
		while ((curcount = backup_read (info_b, buf, BUFSIZE)) > 0)
		{
			unsigned int prcnt, compr;
			if (restore_write (info_r, buf, curcount) != curcount)
			{
				if (quiet < 1)
					fprintf (stderr, "\n");
				if (restore_has_error (info_r))
					restore_perror (info_r, "Copy source");
				else
					fprintf (stderr, "Copy source failed.\n");
				return 1;
			}
			prcnt = get_percent (info_r->cursector, info_r->nsectors);
			if (quiet < 1)
			{
				unsigned timedelta = time(NULL) - starttime;

				fprintf (stderr, "\rCopying %d of %d mb (%d.%02d%%)", info_r->cursector / 2048, info_r->nsectors / 2048, prcnt / 100, prcnt % 100);

				if (prcnt > 100 && timedelta > 15)
				{
					unsigned ETA = timedelta * (10000 - prcnt) / prcnt;
					fprintf (stderr, " %d mb/sec (ETA %d:%02d:%02d)", info_r->cursector / timedelta / 2048, ETA / 3600, ETA / 60 % 60, ETA % 60);
				}
			}
		}

		if (quiet < 1)
			fprintf (stderr, "\n");

		if (backup_has_error (info_b))
		{
			backup_perror (info_b, "Copy source");
			return 1;
		}

		if (restore_has_error (info_r))
		{
			restore_perror (info_r, "Copy target");
			return 1;
		}
	}

	if (backup_finish (info_b) < 0)
	{
		if (backup_has_error (info_b))
			backup_perror (info_b, "Copy source");
		else
			fprintf (stderr, "Copy source failed.\n");
		return 1;
	}

	if (info_b->back_flags & BF_TRUNCATED)
	{
		fprintf (stderr, "***WARNING***\nCopy was made of an incomplete volume.  While the copy succeeded,\nit is possible there was some required data missing.  Verify your copy.\n");
	}

	if (quiet < 2)
		fprintf (stderr, "Cleaning up target.  Please wait a moment.\n");

	if (restore_finish (info_r) < 0)
	{
		if (restore_has_error (info_r))
			restore_perror (info_r, "Copy target");
		else
			fprintf (stderr, "Copy target failed.\n");
		return 1;
	}

	if (quiet < 2)
		fprintf (stderr, "Copy done!\n");

	if (expand > 0)
	{
		int blocksize = 0x800;
		struct mfs_handle *mfshnd;

		expand = 0;

		mfshnd = mfs_init (dest_a, dest_b, O_RDWR);
		if (!mfshnd)
		{
			fprintf (stderr, "Drive expansion failed.\n");
			return 1;
		}

		if (mfs_has_error (mfshnd))
		{
			mfs_perror (mfshnd, "Target expand");
			return 1;
		}

		while (expandscale-- > 0)
			blocksize *= 2;

		if (tivo_partition_largest_free (dest_a) > 1024 * 1024 * 2)
		{
			if (expand_drive (mfshnd, "/dev/hda", dest_a, blocksize) < 0)
			{
				if (mfs_has_error (mfshnd))
					mfs_perror (mfshnd, "Expand drive A");
				else
					fprintf (stderr, "Drive A expansion failed.\n");
				return 1;
			}
			expand++;
		}

		if (dest_b[0] && tivo_partition_largest_free (dest_b) > 1024 * 1024 * 2)
		{
			if (expand_drive (mfshnd, "/dev/hdb", dest_b, blocksize) < 0)
			{
				if (mfs_has_error (mfshnd))
					mfs_perror (mfshnd, "Expand drive B");
				else
					fprintf (stderr, "Drive B expansion failed.\n");
				return 1;
			}
			expand++;
		}

		if (!expand)
		{
			fprintf (stderr, "Not enough extra space to expand on A drive%s.\n", dest_b[0]? " or B drive": "");
		}
	}

	return 0;
}