Beispiel #1
0
main(int argc, char** argv)
{
	Ardir_t*	dir;
	Ardirent_t*	ent;
	long		touch;
	char*		file;

	touch = 0;
	while (file = *++argv)
	{
		if (!strcmp(file, "-t") && *(argv + 1))
			touch = strtol(*++argv, NiL, 0);
		else if (dir = ardiropen(file, NiL, touch ? ARDIR_UPDATE : 0))
		{
			sfprintf(sfstdout, "%s: type=%s truncate=%d%s\n", file, dir->meth->name, dir->truncate, (dir->flags & ARDIR_RANLIB) ? " ranlib" : "");
			while (ent = ardirnext(dir))
			{
				if (touch)
				{
					ent->mtime = touch;
					ardirchange(dir, ent);
					sfprintf(sfstdout, "touch %s\n", ent->name);
				}
				else
					sfprintf(sfstdout, "%s %8u %8u %8llu %8llu %s %s\n", fmtmode(ent->mode, 1), ent->uid, ent->gid, ent->size, ent->offset, fmttime("%k", ent->mtime), ent->name);
			}
			if (ardirclose(dir))
				error(2, "%s: archive read error", file);
		}
		else
			error(ERROR_SYSTEM|2, "%s: not an archive", file);
	}
	return 0;
}
Beispiel #2
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;
}