static char *sccsid
= "@(#)dl.c 4.2\t%G%";
#define ISDIR(st) (((st).st_mode&S_IFMT) == S_IFDIR)
#define ISLNK(st) (((st).st_mode&S_IFMT) == S_IFLNK)
#define ISREG(st) (((st).st_mode&S_IFMT) == S_IFREG)
(((st).st_mode&S_IFMT) == S_IFCHR || ((st).st_mode&S_IFMT) == S_IFBLK)
int cflag
= 0; /* "copy" - same as cp */
int dflag
= 0; /* "debug" - enable trace printf statements */
int fflag
= 0; /* "force" option: override protection, no messages */
int mflag
= 0; /* "move" - same as mv */
int cs
= 0; /* flag used with cflag to prevent endless recursion */
int ms
= 0; /* flag used with mflag to prevent endless recursion */
int tflag
= 0; /* restore original time stamp */
main(argc
, argv
) /* dl.c - delete, undelete, move, copy */
int aflg
= 0; /* "all" option: undelete all deleted files */
int iflg
= 0; /* "interactive" option: send messages to user */
int rflg
= 0; /* "recursive" opt., used only with n */
int sflg
= 0; /* do not delete previous dlsave file */
int uflg
= 0; /* undelete named files and/or directories */
int nflg
= 0; /* do not provide back-up files */
if (isatty(0) == 0) /* if standard i/o is not a terminal, */
fflag
++; /* turn on the f flag */
if (strcmp(*argv
,"ud") == 0)
if (strcmp(*argv
,"copy") == 0)
if (strcmp(*argv
,"move") == 0)
while(argc
>1 && argv
[1][0]=='-') {
* all arguments following a null option (- ) are
* treated as file names, so that file names may
* begin with a minus sign (-).
if (*(arg
+1) == '\0') break;
case 'i': /* "interactive" */
case 'r': /* "recursive" */
case 't': /* "time" stamp */
case 'u': /* "undelete" */
case 'n': /* "not save" */
printf("dl: unknown option %s\n", *argv
);
if (cflag
|| mflag
|| nflg
) sflg
++;
* set up home directory pathname
* process "undelete all" request
* remove previously saved files unless "save" option,
if(!nflg
&& lstat(path
,&buf
) != 0) {
* set up .dlsave directory
if (mkdir(path
,mode
) != 0) {
fprintf(stderr
,"dl: cannot mkdir ~/.dlsave\n");
if(!strcmp(*++argv
, "..")) {
fprintf(stderr
, "dl: cannot remove `..'\n");
* process "undelete" request(s)
* process delete request(s)
copy(*argv
,argv
[argc
-1],iflg
,rflg
);
move(*argv
,argv
[argc
-1],iflg
);
if ((path
=getenv(home
)) == NULL
) {
fprintf(stderr
,"dl: getenv failed\n");
if (place
[j
] == *slash
) {
* undelete all saved files (a option)
if((dirp
= opendir(path
)) == NULL
) {
printf("uda: cannot read %s?\n", path
);
while((dp
= readdir(dirp
)) != NULL
) {
if(dp
->d_ino
!= 0 && !dotname(dp
->d_name
)) {
filename
= (dp
->d_name
)+2;
printf("uda: undelete %s?", filename
);
if(lstat(filename
, &buf
) == 0) {
printf("uda: %s exists. Override?", filename
);
x
= move(path2
,filename
,0);
printf("uda: %s undeleted.\n", filename
);
printf("uda: unable to undelete %s\n", filename
);
* undelete a saved file (u option)
if(lstat(path2
, &buf1
)) {
printf("ud: %s nonexistent\n", path2
);
printf("ud: undelete %s?", arg
);
if(lstat(arg
, &buf2
) == 0) {
printf("ud: %s exists: overwrite?", arg
);
printf("ud: %s undeleted.\n", arg
);
printf("ud: unable to undelete %s\n", arg
);
if (dflag
) printf("rm entered: arg=%s fflag=%d iflg=%d rflg=%d\n",arg
,fflag
,iflg
,rflg
);
printf("rm: %s nonexistent\n", arg
);
* unlink file named by arg
if ((buf
.st_mode
&S_IFMT
) == S_IFDIR
|| rflg
) {
printf("rm: remove directory %s?", arg
);
printf("rm: remove %s?", arg
);
if ((buf
.st_mode
&S_IFMT
) != S_IFLNK
&& access(arg
, 02) < 0) {
printf("rm: override protection %o for %s?\n",buf
.st_mode
&0777,arg
);
if (unlink(arg
) && !fflag
) {
printf ("rm: %s not removed.\n",arg
);
printf ("rm: %s removed.\n",arg
);
* move the argument (file or directory) to
* .dlsave directory in user's home directory
if (dflag
) printf("dl entered: arg=%s fflag=%d iflg=%d\n",arg
,fflag
,iflg
);
if (dflag
) printf("dldir entered: arg=%s fflag=%d iflg=%d\n",arg
,fflag
,iflg
);
printf("dldir: %s nonexistent\n", arg
);
* if the argument is a directory,
* recursively remove the directory's contents
* and then the directory.
if ((buf1
.st_mode
&S_IFMT
) == S_IFDIR
) {
if (access(arg
, 02) < 0) {
printf("dldir: %s not accessable\n",arg
);
if((dirp
= opendir(arg
)) == NULL
)
while((dp
= readdir(dirp
)) != NULL
) {
if(dp
->d_ino
!= 0 && !dotname(dp
->d_name
)) {
(void) sprintf(name
, "%s/%s", arg
, dp
->d_name
);
if (dflag
) printf("dldir: name= %s\n",name
);
printf("dldir: %s nonexistent\n", name
);
if ((buf2
.st_mode
&S_IFMT
) == S_IFDIR
) {
printf("dldir: delete directory %s?", name
);
printf("dldir: delete file %s?", name
);
* permanently remove the file
printf("dldir: %s not removed\n", name
);
printf("dldir: %s removed.\n", name
);
fprintf(stderr
, "dldir: rmdir:");
printf("dldir: directory %s removed.\n",arg
);
while(b
!= '\n' && b
!= EOF
)
move(source
, target
, iflag
)
if (dflag
) printf("move entered: source=%s target=%s fflag=%d iflag=%d\n",source
,target
,fflag
,iflag
);
if (lstat(source
, &s1
) < 0) {
error("cannot access %s", source
);
if (dflag
) printf("move: lstat(%s) successful\n",source
);
* First, try to rename source to target.
targetexists
= lstat(target
, &s2
) >= 0;
if (dflag
) printf("move: lstat(%s) successful\n",target
);
if (s1
.st_dev
== s2
.st_dev
&& s1
.st_ino
== s2
.st_ino
) {
error("%s and %s are identical", source
, target
);
if (access(target
, 2) < 0 && !fflag
&& isatty(fileno(stdin
))) {
if (query("override protection %o for %s? ",
s2
.st_mode
& MODEBITS
, target
) == 0)
printf("overwrite file %s?", target
);
if (s1
.st_dev
!= s2
.st_dev
&& ISDIR(s2
))
if (!fflag
&& iflag
&& !mflag
) {
printf("dl: delete directory %s?", source
);
printf("dl: delete file %s?", source
);
if(dflag
) printf("move(1)rename: source=%s, target=%s\n",source
, target
);
if (rename(source
, target
) >= 0) {
if (!fflag
&& iflag
&& !mflag
)
printf("dl: %s deleted. \n",source
);
if (dflag
) printf("move: %s renamed %s.\n",source
,target
);
if (dflag
) printf("move/rename: errno=%d\n",errno
);
Perror2(source
, "rename");
if (targetexists
&& unlink(target
) < 0) {
error("cannot unlink %s", target
);
if (dflag
) printf("move: target unlinked\n");
* If file or directory cannot be renamed:
* If directory, copy it with r option
if (dflag
) printf("move: directory copy %s to %s\n",source
,target
);
copy (source
, target
, iflag
, 1);
* If link, recreate symbolic link
if (readlink(source
, symln
, sizeof (symln
)) < 0) {
m
= umask(~(s1
.st_mode
& MODEBITS
));
if (symlink(symln
, target
) < 0) {
if (dflag
) printf("move: symlink to target successful\n");
if (mknod(target
, s1
.st_mode
, s1
.st_rdev
) < 0) {
if (dflag
) printf("move: mknod for target successful\n");
* If regular file, copy it
if(dflag
) printf("move: file copy %s to %s\n",source
,target
);
copy(source
, target
, iflag
, 0);
error("%s: unknown file type %o", source
, s1
.st_mode
);
* If a move has been successful, erase the source
if (dflag
) printf("move: cleanup\n");
if (unlink(source
) < 0) {
error("cannot unlink %s", source
);
if (dflag
) printf("move: %s unlinked.\n",source
);
if (!fflag
&& iflag
&& !mflag
)
printf("dl: %s deleted.\n",source
);
fprintf(stderr
, prompt
, a1
, a2
);
while (c
!= '\n' && c
!= EOF
)
fprintf(stderr
, fmt
, a1
, a2
);
char buf
[MAXPATHLEN
+ 10];
(void) sprintf(buf
, "move: %s", s
);
char buf
[MAXPATHLEN
+ 20];
(void) sprintf(buf
, "dl: %s: %s", s1
, s2
);
copy(from
, to
, iflag
, rflag
)
char *last
, destname
[BSIZE
], buf
[BSIZE
];
struct stat stfrom
, stto
;
if (dflag
) printf("copy entered: from=%s to=%s iflag=%d rflag=%d\n",from
,to
,iflag
,rflag
);
if (fstat(fold
, &stfrom
) < 0) {
if (dflag
) printf("copy: fstat(%s) OK.\n",from
);
if (stat(to
, &stto
) >= 0 &&
(stto
.st_mode
&S_IFMT
) == S_IFDIR
) {
last
= rindex(from
, '/');
if (last
) last
++; else last
= from
;
if (strlen(to
) + strlen(last
) >= BSIZE
- 1) {
fprintf(stderr
, "cp: %s/%s: Name too long", to
, last
);
(void) sprintf(destname
, "%s/%s", to
, last
);
if (dflag
) printf("copy: stat %s & %s is dir., to=%s.\n",to
,to
,destname
);
if (!rflag
&& (stfrom
.st_mode
&S_IFMT
) == S_IFDIR
) {
fprintf(stderr
, "cp: %s is a directory, and option -r not chosen. Job aborted.\n", from
);
if (rflag
&& (stfrom
.st_mode
&S_IFMT
) == S_IFDIR
) {
if (dflag
) printf("copy: rflag & from is dir., %s closed.\n",from
);
if (stat(to
, &stto
) < 0) {
if (mkdir(to
, (int)stfrom
.st_mode
) < 0) {
if (dflag
) printf("copy: stat(%s) failed & mkdir % successful.\n",to
,to
);
if ((stto
.st_mode
&S_IFMT
) == S_IFDIR
) {
fprintf(stderr
, "cp: %s: Not a directory.\n", to
);
if (dflag
) printf("copy: return with rcopy(%s,%s,%d,%d)\n",from
,to
,iflag
,rflag
);
return (rcopy(from
, to
, iflag
, rflag
));
if (stat(to
, &stto
) >= 0) {
if (dflag
) printf("cp:stat(%s) o.k.\n",to
);
if (stfrom
.st_dev
== stto
.st_dev
&&
stfrom
.st_ino
== stto
.st_ino
) {
fprintf(stderr
, "cp: Cannot copy file to itself.\n");
fprintf (stderr
, "cp: %s exists: overwrite? ", to
);
fnew
= creat(to
, (int)stfrom
.st_mode
);
(void) close(fold
); return(1);
if (dflag
) printf("copy: creat(%s,%d) successful.\n",to
,stfrom
.st_mode
);
n
= read(fold
, buf
, BSIZE
);
(void) close(fold
); (void) close(fnew
); return (1);
if (write(fnew
, buf
, n
) != n
) {
(void) close(fold
); (void) close(fnew
); return (1);
if (dflag
) printf("copy: %s copied to %s.\n",from
,to
);
/* restore original time-stamp */
if (dflag
) printf("copy: tflag on, tv[0]=%d, tv[1]=%d.\n",tv
[0], tv
[1]);
if (dflag
) printf("copy: returning from copy, from=%s, to=%s.\n",from
,to
);
(void) close(fold
); (void) close(fnew
); return (0);
rcopy(from
, to
, iflag
, rflag
)
DIR *fold
= opendir(from
);
if (dflag
) printf("rcopy: entered: from=%s, to=%s.\n",from
,to
);
if (!strcmp(dp
->d_name
, ".") || !strcmp(dp
->d_name
, ".."))
if (strlen(from
) + 1 + strlen(dp
->d_name
) >= BUFSIZ
- 1) {
fprintf(stderr
, "cp: %s/%s: Name too long.\n",
(void) sprintf(fromname
, "%s/%s", from
, dp
->d_name
);
if (dflag
) printf("rcopy: copy(%s,%s,%d,%d)\n",fromname
,to
,iflag
,rflag
);
errs
+= copy(fromname
, to
, iflag
, rflag
);