da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* This software is part of the ast package *
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner* Copyright (c) 1992-2010 AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* and is licensed under the *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Common Public License, Version 1.0 *
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin* by AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* http://www.opensource.org/licenses/cpl1.0.txt *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Glenn Fowler <gsf@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* David Korn <dgk@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#pragma prototyped
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Glenn Fowler
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * AT&T Research
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * cp/ln/mv -- copy/link/move files
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic const char usage_head[] =
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner"[-?@(#)$Id: cp (AT&T Research) 2010-01-20 $\n]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinUSAGE_LICENSE
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic const char usage_cp[] =
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[+NAME?cp - copy files]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[+DESCRIPTION?If the last argument names an existing directory, \bcp\b"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" copies each \afile\a into a file with the same name in that"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" directory. Otherwise, if only two files are given, \bcp\b copies"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" the first onto the second. It is an error if the last argument is"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" not a directory and more than two files are given. By default"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" directories are not copied.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[a:archive?Preserve as much as possible of the structure and attributes of"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" the original files in the copy. Equivalent to \b--physical\b"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" \b--preserve\b \b--recursive\b.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[p:preserve?Preserve file owner, group, permissions and timestamps.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[h:hierarchy|parents?Form the name of each destination file by appending"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" to the target directory a slash and the specified source file name."
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" The last argument must be an existing directory. Missing destination"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" directories are created.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[H:metaphysical?Follow command argument symbolic links, otherwise don't"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" follow.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[l:link?Make hard links to destination files instead of copies.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[L:logical|dereference?Follow symbolic links and copy the files"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" they point to.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[P|d:physical|nodereference?Don't follow symbolic links; copy symbolic"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" rather than the files they point to.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic const char usage_ln[] =
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[+NAME?ln - link files]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[+DESCRIPTION?If the last argument names an existing directory, \bln\b"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" links each \afile\a into a file with the same name in that"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" directory. Otherwise, if only two files are given, \bln\b links"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" the first onto the second. It is an error if the last argument is"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" not a directory and more than two files are given. By default"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" directories are not linked.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic const char usage_mv[] =
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[+NAME?mv - rename files]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[+DESCRIPTION?If the last argument names an existing directory, \bmv\b"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" renames each \afile\a into a file with the same name in that"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" directory. Otherwise, if only two files are given, \bmv\b renames"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" the first onto the second. It is an error if the last argument is"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" not a directory and more than two files are given. If a source and"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" destination file reside on different filesystems then \bmv\b copies"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" the file contents to the destination and then deletes the source"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" file.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic const char usage_tail[] =
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[f:force?Replace existing destination files.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[i:interactive|prompt?Prompt whether to replace existing destination files."
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" An affirmative response (\by\b or \bY\b) replaces the file, a quit"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" response (\bq\b or \bQ\b) exits immediately, and all other"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" responses skip the file.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[r|R:recursive?Operate on the contents of directories recursively.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[s:symlink|symbolic-link?Make symbolic links to destination files.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[u:update?Replace a destination file only if its modification time is older"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" than the corresponding source file modification time.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[v:verbose?Print the name of each file before operating on it.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[b:backup?Make backups of files that are about to be replaced. See"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" \b--suffix\b and \b--version-control\b for more information.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[F:fsync|sync?\bfsync\b(2) each file after it is copied.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[S:backup-suffix|suffix?A backup file is made by renaming the file to the"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" same name with the backup suffix appended. The backup suffix is"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" determined in this order: this option, the \bSIMPLE_BACKUP_SUFFIX\b,"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" environment variable, or the default value \b~\b.]:[suffix]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[V:backup-type|version-control?The backup type is determined in this order:"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" this option, the \bVERSION_CONTROL\b environment variable, or the"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" default value \bexisting\b. \atype\a may be one of:]:[type]{"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" [+numbered|t?Always make numbered backups. The numbered backup"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" suffix is \b.\aSNS\a, where \aS\a is the"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" \bbackup-suffix\b and \aN\a is the version number,"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" starting at 1, incremented with each version.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" [+existing|nil?Make numbered backups of files that already"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" have them, otherwise simple backups.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" [+simple|never?Always make simple backups.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"}"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[x|X|l:xdev|local|mount|one-file-system?Do not descend into directories in"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" different filesystems than their parents.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"\n"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"\nsource destination\n"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"file ... directory\n"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"\n"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[+SEE ALSO?\bpax\b(1), \bfsync\b(2), \brename\b(2), \bunlink\b(2),"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" \bremove\b(3)]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <cmd.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <ls.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <times.h>
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#include <fts_fix.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <fs3d.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <hashkey.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <stk.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <tmx.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define PATH_CHUNK 256
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define CP 1
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define LN 2
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define MV 3
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define BAK_replace 0 /* no backup -- just replace */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define BAK_existing 1 /* number if already else simple*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define BAK_number 2 /* append .suffix number suffix */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define BAK_simple 3 /* append suffix */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chintypedef struct State_s /* program state */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz void* context; /* builtin context */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int backup; /* BAK_* type */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int directory; /* destination is directory */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int flags; /* FTS_* flags */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int force; /* force approval */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int fs3d; /* 3d fs enabled */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int hierarchy; /* preserve hierarchy */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int interactive; /* prompt for approval */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int missmode; /* default missing dir mode */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int official; /* move to next view */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int op; /* {CP,LN,MV} */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int perm; /* permissions to preserve */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int postsiz; /* state.path post index */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int presiz; /* state.path pre index */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int preserve; /* preserve { id mode time } */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int recursive; /* subtrees too */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int suflen; /* strlen(state.suffix) */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int sync; /* fsync() each file after copy */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int uid; /* caller uid */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int update; /* replace only if newer */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int verbose; /* list each file before op */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin int wflags; /* open() for write flags */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int (*link)(const char*, const char*); /* link */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int (*stat)(const char*, struct stat*); /* stat */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#define INITSTATE pathsiz /* (re)init state before this */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin int pathsiz; /* state.path buffer size */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char* path; /* to pathname buffer */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char* opname; /* state.op message string */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char* suffix; /* backup suffix */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Sfio_t* tmp; /* tmp string stream */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char text[PATH_MAX]; /* link text buffer */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin} State_t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic const char dot[2] = { '.' };
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * preserve support
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinpreserve(State_t* state, const char* path, struct stat* ns, struct stat* os)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (tmxtouch(path, tmxgetatime(os), tmxgetmtime(os), TMX_NOTIME, 0))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|2, "%s: cannot reset access and modify times", path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = ((ns->st_uid != os->st_uid) << 1) | (ns->st_gid != os->st_gid);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (n && chown(state->path, os->st_uid, os->st_gid))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (n)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 01:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|2, "%s: cannot reset group to %s", path, fmtgid(os->st_gid));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 02:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|2, "%s: cannot reset owner to %s", path, fmtuid(os->st_uid));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 03:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|2, "%s: cannot reset owner to %s and group to %s", path, fmtuid(os->st_uid), fmtgid(os->st_gid));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * visit a single file and state.op to the destination
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinvisit(State_t* state, register FTSENT* ent)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char* base;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int len;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int rm;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int rfd;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int wfd;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int m;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int v;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char* s;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char* e;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char* protection;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Sfio_t* ip;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Sfio_t* op;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin FTS* fts;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin FTSENT* sub;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct stat st;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (ent->fts_info == FTS_DC)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "%s: directory causes cycle", ent->fts_path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fts_set(NiL, ent, FTS_SKIP);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (ent->fts_level == 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin base = ent->fts_name;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin len = ent->fts_namelen;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (state->hierarchy)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state->presiz = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state->presiz = ent->fts_pathlen;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (*base == '.' && *(base + 1) == '/')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (base += 2; *base == '/'; base++);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*base == '.' && !*(base + 1))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state->presiz--;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (*base)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state->presiz -= base - ent->fts_name;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin base = ent->fts_name + len;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (base > ent->fts_name && *(base - 1) == '/')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin base--;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (base > ent->fts_name && *(base - 1) != '/')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin base--;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin len -= base - ent->fts_name;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (state->directory)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state->presiz -= len + 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin base = ent->fts_path + state->presiz + 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin len = ent->fts_pathlen - state->presiz - 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin len++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (state->directory)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((state->postsiz + len) > state->pathsiz && !(state->path = newof(state->path, char, state->pathsiz = roundof(state->postsiz + len, PATH_CHUNK), 0)))
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner error(ERROR_SYSTEM|3, "out of space");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (state->hierarchy && ent->fts_level == 0 && strchr(base, '/'))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin s = state->path + state->postsiz;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin memcpy(s, base, len);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (e = strchr(s, '/'))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *e = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (access(state->path, F_OK))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin st.st_mode = state->missmode;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (s = strrchr(s, '/'))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *s = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stat(state->path, &st);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *s = '/';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (mkdir(state->path, st.st_mode & S_IPERM))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|2, "%s: cannot create directory -- %s ignored", state->path, ent->fts_path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fts_set(NiL, ent, FTS_SKIP);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *e++ = '/';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin s = e;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (ent->fts_info)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case FTS_DP:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (state->preserve && state->op != LN || ent->fts_level > 0 && (ent->fts_statp->st_mode & S_IRWXU) != S_IRWXU)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (len && ent->fts_level > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin memcpy(state->path + state->postsiz, base, len);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state->path[state->postsiz] = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (stat(state->path, &st))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|2, "%s: cannot stat", state->path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((ent->fts_statp->st_mode & S_IPERM) != (st.st_mode & S_IPERM) && chmod(state->path, ent->fts_statp->st_mode & S_IPERM))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|2, "%s: cannot reset directory mode to %s", state->path, fmtmode(st.st_mode & S_IPERM, 0) + 1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (state->preserve)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin preserve(state, state->path, &st, ent->fts_statp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case FTS_DNR:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case FTS_DNX:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case FTS_D:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!state->recursive)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fts_set(NiL, ent, FTS_SKIP);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (state->op == CP)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(1, "%s: directory -- copying as plain file", ent->fts_path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (state->link == link && !state->force)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "%s: cannot link directory", ent->fts_path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else switch (ent->fts_info)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case FTS_DNR:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "%s: cannot read directory", ent->fts_path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case FTS_DNX:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "%s: cannot search directory", ent->fts_path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fts_set(NiL, ent, FTS_SKIP);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*FALLTHROUGH*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case FTS_D:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (state->directory)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin memcpy(state->path + state->postsiz, base, len);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(*state->stat)(state->path, &st))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!S_ISDIR(st.st_mode))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "%s: not a directory -- %s ignored", state->path, ent->fts_path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (mkdir(state->path, (ent->fts_statp->st_mode & S_IPERM)|(ent->fts_info == FTS_D ? S_IRWXU : 0)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|2, "%s: cannot create directory -- %s ignored", state->path, ent->fts_path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fts_set(NiL, ent, FTS_SKIP);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!state->directory)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state->directory = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state->path[state->postsiz++] = '/';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state->presiz--;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case FTS_ERR:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case FTS_NS:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case FTS_SLNONE:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (state->link != pathsetlink)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "%s: not found", ent->fts_path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if 0
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case FTS_SL:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (state->op == CP)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "%s: cannot copy non-terminal symbolic link", ent->fts_path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (state->directory)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin memcpy(state->path + state->postsiz, base, len);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((*state->stat)(state->path, &st))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin st.st_mode = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (state->update && !S_ISDIR(st.st_mode) && (unsigned long)ent->fts_statp->st_mtime < (unsigned long)st.st_mtime)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fts_set(NiL, ent, FTS_SKIP);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (!state->fs3d || !iview(&st))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * target is in top 3d view
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (st.st_dev == ent->fts_statp->st_dev && st.st_ino == ent->fts_statp->st_ino)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (state->op == MV)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * let rename() handle it
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (state->verbose)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfputr(sfstdout, state->path, '\n');
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto operate;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!state->official)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "%s: identical to %s", state->path, ent->fts_path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (S_ISDIR(st.st_mode))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "%s: cannot %s existing directory", state->path, state->opname);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (state->verbose)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfputr(sfstdout, state->path, '\n');
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rm = state->op == LN || ent->fts_info == FTS_SL;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!rm || !state->force)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((n = open(state->path, O_RDWR|O_BINARY)) >= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin close(n);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (state->force)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* ok */;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (state->interactive)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if (astquery(-1, "%s %s? ", state->opname, state->path) < 0 || sh_checksig(state->context))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (state->op == LN)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "%s: cannot %s existing file", state->path, state->opname);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (state->force)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rm = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin protection =
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef ETXTBSY
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errno == ETXTBSY ? "``running program''" :
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin st.st_uid != state->uid ? "``not owner''" :
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fmtmode(st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO), 0) + 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (state->interactive)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if (astquery(-1, "override protection %s for %s? ", protection, state->path) < 0 || sh_checksig(state->context))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rm = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (!rm)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "%s: cannot %s %s protection", state->path, state->opname, protection);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (state->backup)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case BAK_existing:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case BAK_number:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin v = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (s = strrchr(state->path, '/'))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin e = state->path;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *s++ = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin e = (char*)dot;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin s = state->path;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = strlen(s);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (fts = fts_open((char**)e, FTS_NOCHDIR|FTS_ONEPATH|FTS_PHYSICAL|FTS_NOPOSTORDER|FTS_NOSTAT|FTS_NOSEEDOTDIR, NiL))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (sub = fts_read(fts))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (strneq(s, sub->fts_name, n) && sub->fts_name[n] == '.' && strneq(sub->fts_name + n + 1, state->suffix, state->suflen) && (m = strtol(sub->fts_name + n + state->suflen + 1, &e, 10)) && streq(e, state->suffix) && m > v)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin v = m;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (sub->fts_level)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fts_set(NiL, sub, FTS_SKIP);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fts_close(fts);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (s != state->path)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *--s = '/';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (v || state->backup == BAK_number)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(state->tmp, "%s.%s%d%s", state->path, state->suffix, v + 1, state->suffix);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto backup;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*FALLTHROUGH*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case BAK_simple:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(state->tmp, "%s%s", state->path, state->suffix);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin backup:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(s = sfstruse(state->tmp)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|3, "%s: out of space", state->path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (rename(state->path, s))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|2, "%s: cannot backup to %s", state->path, s);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin default:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (rm && remove(state->path))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|2, "%s: cannot remove", state->path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin operate:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (state->op)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case MV:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (;;)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!rename(ent->fts_path, state->path))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (errno == ENOENT)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rm = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (!rm && st.st_mode && !remove(state->path))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rm = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (errno != EXDEV && (rm || S_ISDIR(ent->fts_statp->st_mode)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|2, "%s: cannot rename to %s", ent->fts_path, state->path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*FALLTHROUGH*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case CP:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (S_ISLNK(ent->fts_statp->st_mode))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((n = pathgetlink(ent->fts_path, state->text, sizeof(state->text) - 1)) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|2, "%s: cannot read symbolic link text", ent->fts_path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state->text[n] = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (pathsetlink(state->text, state->path))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|2, "%s: cannot copy symbolic link to %s", ent->fts_path, state->path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (state->op == CP || S_ISREG(ent->fts_statp->st_mode) || S_ISDIR(ent->fts_statp->st_mode))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (ent->fts_statp->st_size > 0 && (rfd = open(ent->fts_path, O_RDONLY|O_BINARY)) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|2, "%s: cannot read", ent->fts_path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin else if ((wfd = open(state->path, st.st_mode ? (state->wflags & ~O_EXCL) : state->wflags, ent->fts_statp->st_mode & state->perm)) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|2, "%s: cannot write", state->path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (ent->fts_statp->st_size > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin close(rfd);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (ent->fts_statp->st_size > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(ip = sfnew(NiL, NiL, SF_UNBOUND, rfd, SF_READ)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|2, "%s: %s read stream error", ent->fts_path, state->path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin close(rfd);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin close(wfd);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(op = sfnew(NiL, NiL, SF_UNBOUND, wfd, SF_WRITE)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|2, "%s: %s write stream error", ent->fts_path, state->path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin close(wfd);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfclose(ip);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (sfmove(ip, op, (Sfoff_t)SF_UNBOUND, -1) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n |= 3;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!sfeof(ip))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n |= 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (sfsync(op) || state->sync && fsync(wfd) || sfclose(op))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n |= 2;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (sfclose(ip))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n |= 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (n)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|2, "%s: %s %s error", ent->fts_path, state->path, n == 1 ? ERROR_translate(0, 0, 0, "read") : n == 2 ? ERROR_translate(0, 0, 0, "write") : ERROR_translate(0, 0, 0, "io"));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin close(wfd);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (S_ISBLK(ent->fts_statp->st_mode) || S_ISCHR(ent->fts_statp->st_mode) || S_ISFIFO(ent->fts_statp->st_mode))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (mknod(state->path, ent->fts_statp->st_mode, idevice(ent->fts_statp)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|2, "%s: cannot copy special file to %s", ent->fts_path, state->path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "%s: cannot copy -- unknown file type 0%o", ent->fts_path, S_ITYPE(ent->fts_statp->st_mode));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (state->preserve)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (ent->fts_info != FTS_SL)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (stat(state->path, &st))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|2, "%s: cannot stat", state->path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((ent->fts_statp->st_mode & state->perm) != (st.st_mode & state->perm) && chmod(state->path, ent->fts_statp->st_mode & state->perm))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|2, "%s: cannot reset mode to %s", state->path, fmtmode(st.st_mode & state->perm, 0) + 1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin preserve(state, state->path, &st, ent->fts_statp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (state->op == MV && remove(ent->fts_path))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|1, "%s: cannot remove", ent->fts_path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case LN:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((*state->link)(ent->fts_path, state->path))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|2, "%s: cannot link to %s", ent->fts_path, state->path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinb_cp(int argc, register char** argv, void* context)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char* file;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char* s;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char** v;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char* backup_type;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin FTS* fts;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz FTSENT* ent;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin const char* usage;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int path_resolve;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int standard;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct stat st;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin State_t* state;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin Shbltin_t* sh;
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner void* cleanup = context;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_NOTIFY);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (!(sh = CMD_CONTEXT(context)) || !(state = (State_t*)sh->ptr))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (!(state = newof(0, State_t, 1, 0)))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin error(ERROR_SYSTEM|3, "out of space");
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (sh)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sh->ptr = state;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin else
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin memset(state, 0, offsetof(State_t, INITSTATE));
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz state->context = context;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->presiz = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin backup_type = 0;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->flags = FTS_NOCHDIR|FTS_NOSEEDOTDIR;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->uid = geteuid();
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->wflags = O_WRONLY|O_CREAT|O_TRUNC|O_BINARY;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (!state->tmp && !(state->tmp = sfstropen()))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|3, "out of space [tmp string]");
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sfputr(state->tmp, usage_head, -1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin standard = !strcmp(astconf("CONFORMANCE", NiL, NiL), "standard");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (error_info.id[0])
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'c':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'C':
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sfputr(state->tmp, usage_cp, -1);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->op = CP;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->stat = stat;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin path_resolve = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'l':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'L':
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sfputr(state->tmp, usage_ln, -1);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->op = LN;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->flags |= FTS_PHYSICAL;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->link = link;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->stat = lstat;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin path_resolve = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'm':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'M':
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sfputr(state->tmp, usage_mv, -1);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->op = MV;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->flags |= FTS_PHYSICAL;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->preserve = 1;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->stat = lstat;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin path_resolve = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin default:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(3, "not implemented");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sfputr(state->tmp, usage_tail, -1);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (!(usage = sfstruse(state->tmp)))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin error(ERROR_SYSTEM|3, "%s: out of space", state->path);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->opname = state->op == CP ? ERROR_translate(0, 0, 0, "overwrite") : ERROR_translate(0, 0, 0, "replace");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (;;)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (optget(argv, usage))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'a':
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->flags |= FTS_PHYSICAL;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->preserve = 1;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->recursive = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin path_resolve = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'b':
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->backup = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'f':
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->force = 1;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (state->op != CP || !standard)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->interactive = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'h':
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->hierarchy = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'i':
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->interactive = 1;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (state->op != CP || !standard)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->force = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'l':
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->op = LN;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->link = link;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->stat = lstat;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'p':
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->preserve = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'r':
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->recursive = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (path_resolve < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin path_resolve = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 's':
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->op = LN;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->link = pathsetlink;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->stat = lstat;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'u':
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->update = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'v':
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->verbose = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'x':
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->flags |= FTS_XDEV;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'F':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _lib_fsync
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->sync = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(1, "%s not implemented on this system", opt_info.name);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'H':
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->flags |= FTS_META|FTS_PHYSICAL;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin path_resolve = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'L':
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->flags &= ~FTS_PHYSICAL;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin path_resolve = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'P':
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->flags &= ~FTS_META;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->flags |= FTS_PHYSICAL;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin path_resolve = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'R':
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->recursive = 1;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->flags &= ~FTS_META;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->flags |= FTS_PHYSICAL;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin path_resolve = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'S':
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->suffix = opt_info.arg;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'V':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin backup_type = opt_info.arg;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '?':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_USAGE|4, "%s", opt_info.arg);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case ':':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "%s", opt_info.arg);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin argc -= opt_info.index + 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin argv += opt_info.index;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*argv && streq(*argv, "-") && !streq(*(argv - 1), "--"))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin argc--;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin argv++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(v = (char**)stkalloc(stkstd, (argc + 2) * sizeof(char*))))
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner error(ERROR_SYSTEM|3, "out of space");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin memcpy(v, argv, (argc + 1) * sizeof(char*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin argv = v;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (!standard)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->wflags |= O_EXCL;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (!argc)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin argc++;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin argv[1] = (char*)dot;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (state->backup)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(file = backup_type) && !(backup_type = getenv("VERSION_CONTROL")))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->backup = BAK_existing;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (strkey(backup_type))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case HASHKEY6('e','x','i','s','t','i'):
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case HASHKEY5('e','x','i','s','t'):
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case HASHKEY4('e','x','i','s'):
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case HASHKEY3('e','x','i'):
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case HASHKEY2('e','x'):
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case HASHKEY1('e'):
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case HASHKEY3('n','i','l'):
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case HASHKEY2('n','i'):
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->backup = BAK_existing;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case HASHKEY5('n','e','v','e','r'):
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case HASHKEY4('n','e','v','e'):
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case HASHKEY3('n','e','v'):
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case HASHKEY2('n','e'):
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case HASHKEY6('s','i','m','p','l','e'):
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case HASHKEY5('s','i','m','p','l'):
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case HASHKEY4('s','i','m','p'):
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case HASHKEY3('s','i','m'):
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case HASHKEY2('s','i'):
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case HASHKEY1('s'):
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->backup = BAK_simple;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case HASHKEY6('n','u','m','b','e','r'):
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case HASHKEY5('n','u','m','b','e'):
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case HASHKEY4('n','u','m','b'):
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case HASHKEY3('n','u','m'):
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case HASHKEY2('n','u'):
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case HASHKEY1('t'):
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->backup = BAK_number;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin default:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (file)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "%s: unknown backup type", backup_type);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (!state->suffix && !(state->suffix = getenv("SIMPLE_BACKUP_SUFFIX")))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->suffix = "~";
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->suflen = strlen(state->suffix);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (argc <= 0 || error_info.errors)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_USAGE|4, "%s", optusage(NiL));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!path_resolve)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->flags |= fts_flags();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin file = argv[argc];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin argv[argc] = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (s = strrchr(file, '/'))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (*s == '/')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin s++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(!*s || *s == '.' && (!*++s || *s == '.' && !*++s)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin s = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (file != (char*)dot)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pathcanon(file, 0);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (!(state->directory = !stat(file, &st) && S_ISDIR(st.st_mode)) && argc > 1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_USAGE|4, "%s", optusage(NiL));
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (s && !state->directory)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(3, "%s: not a directory", file);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if ((state->fs3d = fs3d(FS3D_TEST)) && strmatch(file, "...|*/...|.../*"))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->official = 1;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->postsiz = strlen(file);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (state->pathsiz < roundof(state->postsiz + 2, PATH_CHUNK) && !(state->path = newof(state->path, char, state->pathsiz = roundof(state->postsiz + 2, PATH_CHUNK), 0)))
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner error(ERROR_SYSTEM|3, "out of space");
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin memcpy(state->path, file, state->postsiz + 1);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (state->directory && state->path[state->postsiz - 1] != '/')
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->path[state->postsiz++] = '/';
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (state->hierarchy)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (!state->directory)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(3, "%s: last argument must be a directory", file);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->missmode = st.st_mode;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->perm = state->uid ? S_IPERM : (S_IPERM & ~S_ISVTX);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (!state->recursive)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin state->flags |= FTS_TOP;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (fts = fts_open(argv, state->flags, NiL))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin while (!sh_checksig(context) && (ent = fts_read(fts)) && !visit(state, ent));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fts_close(fts);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin else if (state->link != pathsetlink)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin switch (state->op)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case CP:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|2, "%s: cannot copy", argv[0]);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case LN:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|2, "%s: cannot link", argv[0]);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case MV:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|2, "%s: cannot move", argv[0]);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin else if ((*state->link)(*argv, state->path))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin error(ERROR_SYSTEM|2, "%s: cannot link to %s", *argv, state->path);
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner if (cleanup && !sh)
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner {
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner if (state->path)
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner free(state->path);
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner free(state);
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return error_info.errors != 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}