Exemple #1
0
static int
rm(State_t* state, register FTSENT* ent)
{
	register char*	path;
	register int	n;
	int		v;
	struct stat	st;

	if (ent->fts_info == FTS_NS || ent->fts_info == FTS_ERR || ent->fts_info == FTS_SLNONE)
	{
		if (!state->force)
			error(2, "%s: not found", ent->fts_path);
	}
	else if (state->fs3d && iview(ent->fts_statp))
		fts_set(NiL, ent, FTS_SKIP);
	else switch (ent->fts_info)
	{
	case FTS_DNR:
	case FTS_DNX:
		if (state->unconditional)
		{
			if (!beenhere(ent))
				break;
			if (!chmod(ent->fts_name, (ent->fts_statp->st_mode & S_IPERM)|S_IRWXU))
			{
				fts_set(NiL, ent, FTS_AGAIN);
				break;
			}
			error_info.errors++;
		}
		else if (!state->force)
			error(2, "%s: cannot %s directory", ent->fts_path, (ent->fts_info & FTS_NR) ? "read" : "search");
		else
			error_info.errors++;
		fts_set(NiL, ent, FTS_SKIP);
		nonempty(ent);
		break;
	case FTS_D:
	case FTS_DC:
		path = ent->fts_name;
		if (path[0] == '.' && (!path[1] || path[1] == '.' && !path[2]) && (ent->fts_level > 0 || path[1]))
		{
			fts_set(NiL, ent, FTS_SKIP);
			if (!state->force)
				error(2, "%s: cannot remove", ent->fts_path);
			else
				error_info.errors++;
			break;
		}
		if (!state->recursive)
		{
			fts_set(NiL, ent, FTS_SKIP);
			error(2, "%s: directory", ent->fts_path);
			break;
		}
		if (!beenhere(ent))
		{
			if (state->unconditional && (ent->fts_statp->st_mode & S_IRWXU) != S_IRWXU)
				chmod(path, (ent->fts_statp->st_mode & S_IPERM)|S_IRWXU);
			if (ent->fts_level > 0)
			{
				char*	s;

				if (ent->fts_accpath == ent->fts_name || !(s = strrchr(ent->fts_accpath, '/')))
					v = !stat(".", &st);
				else
				{
					path = ent->fts_accpath;
					*s = 0;
					v = !stat(path, &st);
					*s = '/';
				}
				if (v)
					v = st.st_nlink <= 2 || st.st_ino == ent->fts_parent->fts_statp->st_ino && st.st_dev == ent->fts_parent->fts_statp->st_dev || strchr(astconf("PATH_ATTRIBUTES", path, NiL), 'l');
			}
			else
				v = 1;
			if (v)
			{
				if (state->interactive)
				{
					if ((v = astquery(-1, "remove directory %s? ", ent->fts_path)) < 0 || sh_checksig(state->context))
						return -1;
					if (v > 0)
					{
						fts_set(NiL, ent, FTS_SKIP);
						nonempty(ent);
					}
				}
				if (ent->fts_info == FTS_D)
					break;
			}
			else
			{
				ent->fts_info = FTS_DC;
				error(1, "%s: hard link to directory", ent->fts_path);
			}
		}
		else if (ent->fts_info == FTS_D)
			break;
		/*FALLTHROUGH*/
	case FTS_DP:
		if (isempty(ent) || state->directory)
		{
			path = ent->fts_name;
			if (path[0] != '.' || path[1])
			{
				path = ent->fts_accpath;
				if (state->verbose)
					sfputr(sfstdout, ent->fts_path, '\n');
				if ((ent->fts_info == FTS_DC || state->directory) ? remove(path) : rmdir(path))
					switch (errno)
					{
					case ENOENT:
						break;
					case EEXIST:
#if defined(ENOTEMPTY) && (ENOTEMPTY) != (EEXIST)
					case ENOTEMPTY:
#endif
						if (ent->fts_info == FTS_DP && !beenhere(ent))
						{
							retry(ent);
							fts_set(NiL, ent, FTS_AGAIN);
							break;
						}
						/*FALLTHROUGH*/
					default:
						nonempty(ent);
						if (!state->force)
							error(ERROR_SYSTEM|2, "%s: directory not removed", ent->fts_path);
						else
							error_info.errors++;
						break;
					}
			}
			else if (!state->force)
				error(2, "%s: cannot remove", ent->fts_path);
			else
				error_info.errors++;
		}
		else
		{
			nonempty(ent);
			if (!state->force)
				error(2, "%s: directory not removed", ent->fts_path);
			else
				error_info.errors++;
		}
		break;
	default:
		path = ent->fts_accpath;
		if (state->verbose)
			sfputr(sfstdout, ent->fts_path, '\n');
		if (state->interactive)
		{
			if ((v = astquery(-1, "remove %s? ", ent->fts_path)) < 0 || sh_checksig(state->context))
				return -1;
			if (v > 0)
			{
				nonempty(ent);
				break;
			}
		}
		else if (!state->force && state->terminal && eaccess(path, W_OK))
		{
			if ((v = astquery(-1, "override protection %s for %s? ",
#ifdef ETXTBSY
				errno == ETXTBSY ? "``running program''" : 
#endif
				ent->fts_statp->st_uid != state->uid ? "``not owner''" :
				fmtmode(ent->fts_statp->st_mode & S_IPERM, 0) + 1, ent->fts_path)) < 0 ||
			    sh_checksig(state->context))
				return -1;
			if (v > 0)
			{
				nonempty(ent);
				break;
			}
		}
#if _lib_fsync
		if (state->clobber && S_ISREG(ent->fts_statp->st_mode) && ent->fts_statp->st_size > 0)
		{
			if ((n = open(path, O_WRONLY)) < 0)
				error(ERROR_SYSTEM|2, "%s: cannot clear data", ent->fts_path);
			else
			{
				off_t		c = ent->fts_statp->st_size;

				for (;;)
				{
					if (write(n, state->buf, sizeof(state->buf)) != sizeof(state->buf))
					{
						error(ERROR_SYSTEM|2, "%s: data clear error", ent->fts_path);
						break;
					}
					if (c <= sizeof(state->buf))
						break;
					c -= sizeof(state->buf);
				}
				fsync(n);
				close(n);
			}
		}
#endif
		if (remove(path))
		{
			nonempty(ent);
			switch (errno)
			{
			case ENOENT:
				break;
			default:
				if (!state->force || state->interactive)
					error(ERROR_SYSTEM|2, "%s: not removed", ent->fts_path);
				else
					error_info.errors++;
				break;
			}
		}
		break;
	}
	return 0;
}
Exemple #2
0
int
b_rm(int argc, register char** argv, void* context)
{
	State_t		state;
	FTS*		fts;
	FTSENT*		ent;
	int		set3d;

	cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_NOTIFY);
	memset(&state, 0, sizeof(state));
	state.context = context;
	state.fs3d = fs3d(FS3D_TEST);
	state.terminal = isatty(0);
	for (;;)
	{
		switch (optget(argv, usage))
		{
		case 'd':
			state.directory = 1;
			continue;
		case 'f':
			state.force = 1;
			state.interactive = 0;
			continue;
		case 'i':
			state.interactive = 1;
			state.force = 0;
			continue;
		case 'r':
		case 'R':
			state.recursive = 1;
			continue;
		case 'F':
#if _lib_fsync
			state.clobber = 1;
#else
			error(1, "%s not implemented on this system", opt_info.name);
#endif
			continue;
		case 'u':
			state.unconditional = 1;
			continue;
		case 'v':
			state.verbose = 1;
			continue;
		case '?':
			error(ERROR_USAGE|4, "%s", opt_info.arg);
			break;
		case ':':
			error(2, "%s", opt_info.arg);
			break;
		}
		break;
	}
	argv += opt_info.index;
	if (*argv && streq(*argv, "-") && !streq(*(argv - 1), "--"))
		argv++;
	if (error_info.errors || !*argv)
		error(ERROR_USAGE|4, "%s", optusage(NiL));

	/*
	 * do it
	 */

	if (state.interactive)
		state.verbose = 0;
	state.uid = geteuid();
	state.unconditional = state.unconditional && state.recursive && state.force;
	if (state.recursive && state.fs3d)
	{
		set3d = state.fs3d;
		state.fs3d = 0;
		fs3d(0);
	}
	else
		set3d = 0;
	if (fts = fts_open(argv, FTS_PHYSICAL, NiL))
	{
		while (!sh_checksig(context) && (ent = fts_read(fts)) && !rm(&state, ent));
		fts_close(fts);
	}
	else if (!state.force)
		error(ERROR_SYSTEM|2, "%s: cannot remove", argv[0]);
	if (set3d)
		fs3d(set3d);
	return error_info.errors != 0;
}
Exemple #3
0
int
b_mktemp(int argc, char** argv, Shbltin_t* context)
{
	mode_t		mode = 0;
	mode_t		mask;
	int		fd;
	int		i;
	int		quiet = 0;
	int		unsafe = 0;
	int*		fdp = &fd;
	char*		dir = "";
	char*		pfx;
	char*		t;
	char		path[PATH_MAX];

	cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_NOTIFY);
	for (;;)
	{
		switch (optget(argv, usage))
		{
		case 'd':
			fdp = 0;
			continue;
		case 'm':
			mode = strperm(pfx = opt_info.arg, &opt_info.arg, S_IRWXU);
			if (*opt_info.arg)
				error(ERROR_exit(0), "%s: invalid mode", pfx);
			continue;
		case 'p':
			if ((t = getenv("TMPDIR")) && *t)
				dir = 0;
			else
				dir = opt_info.arg;
			continue;
		case 'q':
			quiet = 1;
			continue;
		case 't':
			dir = 0;
			continue;
		case 'u':
			unsafe = 1;
			fdp = 0;
			continue;
		case 'R':
			if (!pathtemp(NiL, 0, opt_info.arg, "/seed", NiL))
				error(2, "%s: regression test initializtion failed", opt_info.arg);
			continue;
		case ':':
			error(2, "%s", opt_info.arg);
			break;
		case '?':
			error(ERROR_usage(2), "%s", opt_info.arg);
			break;
		}
		break;
	}
	argv += opt_info.index;
	if (error_info.errors || (pfx = *argv++) && *argv)
		error(ERROR_usage(2), "%s", optusage(NiL));
	mask = umask(0);
	if (!mode)
		mode = (fdp ? (S_IRUSR|S_IWUSR) : S_IRWXU) & ~mask;
	umask(~mode & (S_IRWXU|S_IRWXG|S_IRWXO));
	if (!pfx)
	{
		pfx = "tmp_";
		if (dir && !*dir)
			dir = 0;
	}
	if (t = strrchr(pfx, '/'))
	{
		i = ++t - pfx;
		dir = fmtbuf(i);
		memcpy(dir, pfx, i);
		dir[i] = 0;
		pfx = t;
	}
	for (;;)
	{
		if (!pathtemp(path, sizeof(path), dir, pfx, fdp))
		{
			if (quiet)
				error_info.errors++;
			else
				error(ERROR_SYSTEM|2, "cannot create temporary path");
			break;
		}
		if (fdp || unsafe || !mkdir(path, mode))
		{
			if (fdp)
				close(*fdp);
			sfputr(sfstdout, path, '\n');
			break;
		}
		if (sh_checksig(context))
		{
			error_info.errors++;
			break;
		}
	}
	umask(mask);
	return error_info.errors != 0;
}