1*33063Sbostic static char *sccsid = "@(#)dl.c 4.2\t12/20/87";
216067Sralph
316067Sralph #include <stdio.h>
416067Sralph #include <sys/param.h>
516067Sralph #include <sys/stat.h>
616067Sralph #include <sys/dir.h>
716067Sralph #include <errno.h>
816067Sralph #include <signal.h>
916067Sralph
1016067Sralph #define DELIM '/'
1116067Sralph #define MODEBITS 07777
1216067Sralph #define ISDIR(st) (((st).st_mode&S_IFMT) == S_IFDIR)
1316067Sralph #define ISLNK(st) (((st).st_mode&S_IFMT) == S_IFLNK)
1416067Sralph #define ISREG(st) (((st).st_mode&S_IFMT) == S_IFREG)
1516067Sralph #define ISDEV(st) \
1616067Sralph (((st).st_mode&S_IFMT) == S_IFCHR || ((st).st_mode&S_IFMT) == S_IFBLK)
1716067Sralph
1816067Sralph struct stat s1, s2, buf;
1916067Sralph extern unsigned errno;
2016067Sralph int errcode;
2116067Sralph char *path;
2216067Sralph char *path2;
2316067Sralph char line[1024];
2416067Sralph int cflag = 0; /* "copy" - same as cp */
2516067Sralph int dflag = 0; /* "debug" - enable trace printf statements */
2616067Sralph int fflag = 0; /* "force" option: override protection, no messages */
2716067Sralph int mflag = 0; /* "move" - same as mv */
2816067Sralph int cs = 0; /* flag used with cflag to prevent endless recursion */
2916067Sralph int ms = 0; /* flag used with mflag to prevent endless recursion */
3016067Sralph int tflag = 0; /* restore original time stamp */
3116067Sralph
main(argc,argv)3216067Sralph main(argc, argv) /* dl.c - delete, undelete, move, copy */
3316067Sralph char *argv[];
3416067Sralph {
3516067Sralph register char *arg;
3616067Sralph char *s;
3716067Sralph int mode;
3816067Sralph int aflg = 0; /* "all" option: undelete all deleted files */
3916067Sralph int iflg = 0; /* "interactive" option: send messages to user */
4016067Sralph int rflg = 0; /* "recursive" opt., used only with n */
4116067Sralph int sflg = 0; /* do not delete previous dlsave file */
4216067Sralph int uflg = 0; /* undelete named files and/or directories */
4316067Sralph int nflg = 0; /* do not provide back-up files */
4416067Sralph
4516067Sralph if (isatty(0) == 0) /* if standard i/o is not a terminal, */
4616067Sralph fflag++; /* turn on the f flag */
4716067Sralph
4816067Sralph if (strcmp(*argv,"ud") == 0)
4916067Sralph uflg++;
5016067Sralph
5116067Sralph if (strcmp(*argv,"copy") == 0)
5216067Sralph cflag++;
5316067Sralph
5416067Sralph if (strcmp(*argv,"move") == 0)
5516067Sralph mflag++;
5616067Sralph
5716067Sralph while(argc>1 && argv[1][0]=='-') {
5816067Sralph arg = *++argv;
5916067Sralph argc--;
6016067Sralph
6116067Sralph /*
6216067Sralph * all arguments following a null option (- ) are
6316067Sralph * treated as file names, so that file names may
6416067Sralph * begin with a minus sign (-).
6516067Sralph */
6616067Sralph if (*(arg+1) == '\0') break;
6716067Sralph
6816067Sralph while(*++arg != '\0')
6916067Sralph switch(*arg) {
7016067Sralph case 'a': /* "all" */
7116067Sralph aflg++;
7216067Sralph break;
7316067Sralph case 'c': /* "copy" */
7416067Sralph cflag++;
7516067Sralph break;
7616067Sralph case 'd': /* "debug" */
7716067Sralph dflag++;
7816067Sralph break;
7916067Sralph case 'f': /* "force" */
8016067Sralph fflag++;
8116067Sralph break;
8216067Sralph case 'i': /* "interactive" */
8316067Sralph iflg++;
8416067Sralph break;
8516067Sralph case 'r': /* "recursive" */
8616067Sralph rflg++;
8716067Sralph break;
8816067Sralph case 's': /* "save" */
8916067Sralph sflg++;
9016067Sralph break;
9116067Sralph case 't': /* "time" stamp */
9216067Sralph tflag++;
9316067Sralph break;
9416067Sralph case 'u': /* "undelete" */
9516067Sralph uflg++;
9616067Sralph break;
9716067Sralph case 'm': /* "move" */
9816067Sralph mflag++;
9916067Sralph break;
10016067Sralph case 'n': /* "not save" */
10116067Sralph nflg++;
10216067Sralph break;
10316067Sralph default:
10416067Sralph printf("dl: unknown option %s\n", *argv);
10516067Sralph exit(1);
10616067Sralph }
10716067Sralph }
10816067Sralph if (cflag || mflag || nflg) sflg++;
10916067Sralph /*
11016067Sralph * set up home directory pathname
11116067Sralph */
11216067Sralph setpath();
11316067Sralph /*
11416067Sralph * process "undelete all" request
11516067Sralph */
11616067Sralph if(aflg) {
11716067Sralph undelete_all(iflg);
11816067Sralph exit;
11916067Sralph }
12016067Sralph /*
12116067Sralph * remove previously saved files unless "save" option,
12216067Sralph * or ud or rm mode
12316067Sralph */
12416067Sralph if(!sflg && !uflg)
12516067Sralph dldir(path,0);
12616067Sralph if(!nflg && lstat(path,&buf) != 0) {
12716067Sralph /*
12816067Sralph * set up .dlsave directory
12916067Sralph */
13016067Sralph mode = 0777;
13116067Sralph if (mkdir(path,mode) != 0) {
13216067Sralph fprintf(stderr,"dl: cannot mkdir ~/.dlsave\n");
13316067Sralph perror(s);
13416067Sralph exit(1);
13516067Sralph }
13616067Sralph }
13716067Sralph while(--argc > 0) {
13816067Sralph if(!strcmp(*++argv, "..")) {
13916067Sralph if(!fflag)
14016067Sralph fprintf(stderr, "dl: cannot remove `..'\n");
14116067Sralph continue;
14216067Sralph }
14316067Sralph /*
14416067Sralph * process "undelete" request(s)
14516067Sralph */
14616067Sralph if(uflg) {
14716067Sralph undelete(*argv,iflg);
14816067Sralph exit;
14916067Sralph }
15016067Sralph else {
15116067Sralph /*
15216067Sralph * process delete request(s)
15316067Sralph */
15416067Sralph if (cflag) {
15516067Sralph copy(*argv,argv[argc-1],iflg,rflg);
15616067Sralph exit(errcode);
15716067Sralph }
15816067Sralph if (mflag) {
15916067Sralph move(*argv,argv[argc-1],iflg);
16016067Sralph exit(errcode);
16116067Sralph }
16216067Sralph if (nflg)
16316067Sralph rm(*argv, iflg, rflg);
16416067Sralph else
16516067Sralph dl(*argv, iflg);
16616067Sralph }
16716067Sralph }
16816067Sralph exit(errcode);
16916067Sralph }
17016067Sralph
setpath()17116067Sralph setpath()
17216067Sralph {
17316067Sralph char *home;
17416067Sralph char *suffix;
17516067Sralph char *getenv();
17616067Sralph
17716067Sralph home = "HOME";
17816067Sralph if ((path=getenv(home)) == NULL) {
17916067Sralph fprintf(stderr,"dl: getenv failed\n");
18016067Sralph exit(1);
18116067Sralph }
18216067Sralph suffix = "/.dlsave";
18316067Sralph strcat(path,suffix);
18416067Sralph return;
18516067Sralph }
18616067Sralph
package(argu)18716067Sralph package(argu)
18816067Sralph char argu[];
18916067Sralph {
19016067Sralph register int i, j, k;
19116067Sralph char *slash, *slashdot;
19216067Sralph char *place;
19316067Sralph char line2[512];
19416067Sralph
19516067Sralph place = line2;
19616067Sralph strcpy(place,argu);
19716067Sralph path2 = line;
19816067Sralph strcpy(path2,path);
19916067Sralph slashdot = "/.#";
20016067Sralph strcat(path2,slashdot);
20116067Sralph i = strlen(argu);
20216067Sralph slash = "/";
20316067Sralph k = 0;
20416067Sralph for (j=0;j<i;j++) {
20516067Sralph if (place[j] == *slash) {
20616067Sralph k = j + 1;
20716067Sralph }
20816067Sralph }
20916067Sralph strcat(path2,argu+k);
21016067Sralph return;
21116067Sralph }
21216067Sralph
undelete_all(iflg)21316067Sralph undelete_all(iflg)
21416067Sralph {
21516067Sralph struct direct *dp;
21616067Sralph DIR *dirp;
21716067Sralph char *filename;
21816067Sralph int x;
21916067Sralph
22016067Sralph /*
22116067Sralph * undelete all saved files (a option)
22216067Sralph */
22316067Sralph if((dirp = opendir(path)) == NULL) {
22416067Sralph if(!fflag)
22516067Sralph printf("uda: cannot read %s?\n", path);
22616067Sralph exit(1);
22716067Sralph }
22816067Sralph while((dp = readdir(dirp)) != NULL) {
22916067Sralph if(dp->d_ino != 0 && !dotname(dp->d_name)) {
23016067Sralph filename = (dp->d_name)+2;
23116067Sralph package(filename);
23216067Sralph if(iflg) {
23316067Sralph printf("uda: undelete %s?", filename);
23416067Sralph if (!yes())
23516067Sralph goto no;
23616067Sralph }
23716067Sralph if(lstat(filename, &buf) == 0) {
23816067Sralph printf("uda: %s exists. Override?", filename);
23916067Sralph if(!yes())
24016067Sralph goto no;
24116067Sralph }
24216067Sralph x = move(path2,filename,0);
24316067Sralph if(iflg) {
24416067Sralph if (x >= 0)
24516067Sralph printf("uda: %s undeleted.\n", filename);
24616067Sralph else
24716067Sralph printf("uda: unable to undelete %s\n", filename);
24816067Sralph }
24916067Sralph no: continue;
25016067Sralph }
25116067Sralph }
25216067Sralph closedir(dirp);
25316067Sralph return;
25416067Sralph }
25516067Sralph
undelete(arg,iflg)25616067Sralph undelete(arg,iflg)
25716067Sralph char arg[];
25816067Sralph {
25916067Sralph struct stat buf1, buf2;
26016067Sralph int x;
26116067Sralph
26216067Sralph /*
26316067Sralph * undelete a saved file (u option)
26416067Sralph */
26516067Sralph package(arg);
26616067Sralph if(lstat(path2, &buf1)) {
26716067Sralph if (!fflag)
26816067Sralph printf("ud: %s nonexistent\n", path2);
26916067Sralph ++errcode;
27016067Sralph return;
27116067Sralph }
27216067Sralph if(iflg) {
27316067Sralph printf("ud: undelete %s?", arg);
27416067Sralph if(!yes())
27516067Sralph return;
27616067Sralph }
27716067Sralph if(lstat(arg, &buf2) == 0) {
27816067Sralph printf("ud: %s exists: overwrite?", arg);
27916067Sralph if(!yes())
28016067Sralph return;
28116067Sralph }
28216067Sralph x = move(path2,arg,0);
28316067Sralph if(iflg) {
28416067Sralph if (x >= 0)
28516067Sralph printf("ud: %s undeleted.\n", arg);
28616067Sralph else
28716067Sralph printf("ud: unable to undelete %s\n", arg);
28816067Sralph }
28916067Sralph return;
29016067Sralph }
29116067Sralph
rm(arg,iflg,rflg)29216067Sralph rm(arg, iflg, rflg)
29316067Sralph char arg[];
29416067Sralph {
29516067Sralph if (dflag) printf("rm entered: arg=%s fflag=%d iflg=%d rflg=%d\n",arg,fflag,iflg,rflg);
29616067Sralph if(lstat(arg, &buf)) {
29716067Sralph if (!fflag)
29816067Sralph printf("rm: %s nonexistent\n", arg);
29916067Sralph ++errcode;
30016067Sralph return;
30116067Sralph }
30216067Sralph /*
30316067Sralph * unlink file named by arg
30416067Sralph */
30516067Sralph if ((buf.st_mode&S_IFMT) == S_IFDIR || rflg) {
30616067Sralph if(iflg) {
30716067Sralph printf("rm: remove directory %s?", arg);
30816067Sralph if(!yes())
30916067Sralph return;
31016067Sralph }
31116067Sralph dldir(arg, iflg);
31216067Sralph return;
31316067Sralph }
31416067Sralph if (!fflag && iflg) {
31516067Sralph printf("rm: remove %s?", arg);
31616067Sralph if (!yes())
31716067Sralph return;
31816067Sralph }
31916067Sralph else if (!fflag) {
32016067Sralph if ((buf.st_mode&S_IFMT) != S_IFLNK && access(arg, 02) < 0) {
32116067Sralph printf("rm: override protection %o for %s?\n",buf.st_mode&0777,arg);
32216067Sralph if (!yes())
32316067Sralph return;
32416067Sralph }
32516067Sralph }
32616067Sralph if (unlink(arg) && !fflag) {
32716067Sralph printf ("rm: %s not removed.\n",arg);
32816067Sralph ++errcode;
32916067Sralph }
33016067Sralph else {
33116067Sralph if (!fflag && iflg)
33216067Sralph printf ("rm: %s removed.\n",arg);
33316067Sralph }
33416067Sralph return;
33516067Sralph }
33616067Sralph
dl(arg,iflg)33716067Sralph dl(arg, iflg)
33816067Sralph char arg[];
33916067Sralph {
34016067Sralph /*
34116067Sralph * move the argument (file or directory) to
34216067Sralph * .dlsave directory in user's home directory
34316067Sralph */
34416067Sralph if (dflag) printf("dl entered: arg=%s fflag=%d iflg=%d\n",arg,fflag,iflg);
34516067Sralph package(arg);
34616067Sralph move(arg,path2,iflg);
34716067Sralph return;
34816067Sralph }
34916067Sralph
dldir(arg,iflg)35016067Sralph dldir(arg, iflg)
35116067Sralph char arg[];
35216067Sralph {
35316067Sralph struct stat buf1, buf2;
35416067Sralph struct direct *dp;
35516067Sralph DIR *dirp;
35616067Sralph char name[BUFSIZ];
35716067Sralph
35816067Sralph if (dflag) printf("dldir entered: arg=%s fflag=%d iflg=%d\n",arg,fflag,iflg);
35916067Sralph if(lstat(arg, &buf1)) {
36016067Sralph if (!fflag && iflg)
36116067Sralph printf("dldir: %s nonexistent\n", arg);
36216067Sralph ++errcode;
36316067Sralph return;
36416067Sralph }
36516067Sralph /*
36616067Sralph * if the argument is a directory,
36716067Sralph * recursively remove the directory's contents
36816067Sralph * and then the directory.
36916067Sralph */
37016067Sralph if ((buf1.st_mode&S_IFMT) == S_IFDIR) {
37116067Sralph if (access(arg, 02) < 0) {
37216067Sralph if(!fflag) {
37316067Sralph printf("dldir: %s not accessable\n",arg);
37416067Sralph }
37516067Sralph errcode++;
37616067Sralph return;
37716067Sralph }
37816067Sralph if((dirp = opendir(arg)) == NULL)
37916067Sralph exit(1);
38016067Sralph while((dp = readdir(dirp)) != NULL) {
38116067Sralph if(dp->d_ino != 0 && !dotname(dp->d_name)) {
382*33063Sbostic (void) sprintf(name, "%s/%s", arg, dp->d_name);
38316067Sralph if (dflag) printf("dldir: name= %s\n",name);
38416067Sralph if(lstat(name, &buf2)) {
38516067Sralph if (!fflag)
38616067Sralph printf("dldir: %s nonexistent\n", name);
38716067Sralph ++errcode;
38816067Sralph return;
38916067Sralph }
39016067Sralph if ((buf2.st_mode&S_IFMT) == S_IFDIR) {
39116067Sralph if(!fflag && iflg) {
39216067Sralph printf("dldir: delete directory %s?", name);
39316067Sralph if(!yes())
39416067Sralph return;
39516067Sralph }
39616067Sralph dldir(name, iflg);
39716067Sralph }
39816067Sralph else {
39916067Sralph if(!fflag && iflg) {
40016067Sralph printf("dldir: delete file %s?", name);
40116067Sralph if(!yes())
40216067Sralph return;
40316067Sralph }
40416067Sralph /*
40516067Sralph * permanently remove the file
40616067Sralph */
40716067Sralph if (unlink(name)) {
40816067Sralph if (!fflag)
40916067Sralph printf("dldir: %s not removed\n", name);
41016067Sralph ++errcode;
41116067Sralph }
41216067Sralph else {
41316067Sralph if (!fflag && iflg)
41416067Sralph printf("dldir: %s removed.\n", name);
41516067Sralph }
41616067Sralph }
41716067Sralph }
41816067Sralph }
41916067Sralph closedir(dirp);
42016067Sralph if (dotname(arg))
42116067Sralph return;
42216067Sralph if (rmdir(arg) < 0) {
42316067Sralph if(!fflag && iflg) {
42416067Sralph fprintf(stderr, "dldir: rmdir:");
42516067Sralph perror(arg);
42616067Sralph }
42716067Sralph errcode++;
42816067Sralph }
42916067Sralph else {
43016067Sralph if(!fflag && iflg)
43116067Sralph printf("dldir: directory %s removed.\n",arg);
43216067Sralph }
43316067Sralph return;
43416067Sralph }
43516067Sralph }
43616067Sralph
dotname(s)43716067Sralph dotname(s)
43816067Sralph char *s;
43916067Sralph {
44016067Sralph if(s[0] == '.')
44116067Sralph if(s[1] == '.')
44216067Sralph if(s[2] == '\0')
44316067Sralph return(1);
44416067Sralph else
44516067Sralph return(0);
44616067Sralph else if(s[1] == '\0')
44716067Sralph return(1);
44816067Sralph return(0);
44916067Sralph }
45016067Sralph
yes()45116067Sralph yes()
45216067Sralph {
45316067Sralph int i, b;
45416067Sralph
45516067Sralph i = b = getchar();
45616067Sralph while(b != '\n' && b != EOF)
45716067Sralph b = getchar();
45816067Sralph return(i == 'y');
45916067Sralph }
46016067Sralph
move(source,target,iflag)46116067Sralph move(source, target, iflag)
46216067Sralph char *source, *target;
46316067Sralph {
46416067Sralph int targetexists;
46516067Sralph int sw = 0;
46616067Sralph
46716067Sralph if (dflag) printf("move entered: source=%s target=%s fflag=%d iflag=%d\n",source,target,fflag,iflag);
46816067Sralph if (lstat(source, &s1) < 0) {
46916067Sralph if (!fflag)
47016067Sralph error("cannot access %s", source);
47116067Sralph return (1);
47216067Sralph }
47316067Sralph if (dflag) printf("move: lstat(%s) successful\n",source);
47416067Sralph /*
47516067Sralph * First, try to rename source to target.
47616067Sralph */
47716067Sralph targetexists = lstat(target, &s2) >= 0;
47816067Sralph if (targetexists) {
47916067Sralph if (dflag) printf("move: lstat(%s) successful\n",target);
48016067Sralph if (s1.st_dev == s2.st_dev && s1.st_ino == s2.st_ino) {
48116067Sralph if (!fflag)
48216067Sralph error("%s and %s are identical", source, target);
48316067Sralph return (1);
48416067Sralph }
48516067Sralph if (access(target, 2) < 0 && !fflag && isatty(fileno(stdin))) {
48616067Sralph if (query("override protection %o for %s? ",
48716067Sralph s2.st_mode & MODEBITS, target) == 0)
48816067Sralph return (1);
48916067Sralph sw++;
49016067Sralph }
49116067Sralph if (mflag && ms == 0) {
49216067Sralph if (ISREG(s2)) {
49316067Sralph if (!fflag && sw == 0) {
49416067Sralph printf("overwrite file %s?", target);
49516067Sralph if(!yes())
49616067Sralph return;
49716067Sralph }
49816067Sralph ms = 1;
49916067Sralph dl (target, 0);
50016067Sralph }
50116067Sralph else
50216067Sralph if (s1.st_dev != s2.st_dev && ISDIR(s2))
50316067Sralph goto copyit;
50416067Sralph }
50516067Sralph }
50616067Sralph if (!fflag && iflag && !mflag) {
50716067Sralph if (ISDIR(s1))
50816067Sralph printf("dl: delete directory %s?", source);
50916067Sralph else
51016067Sralph printf("dl: delete file %s?", source);
51116067Sralph if(!yes())
51216067Sralph return;
51316067Sralph }
51416067Sralph if(dflag) printf("move(1)rename: source=%s, target=%s\n",source, target);
51516067Sralph if (rename(source, target) >= 0) {
51616067Sralph if (!fflag && iflag && !mflag)
51716067Sralph printf("dl: %s deleted. \n",source);
51816067Sralph if (dflag) printf("move: %s renamed %s.\n",source,target);
51916067Sralph return (0);
52016067Sralph }
52116067Sralph if (dflag) printf("move/rename: errno=%d\n",errno);
52216067Sralph if (errno != EXDEV) {
52316067Sralph if (!fflag && iflag) {
52416067Sralph Perror2(source, "rename");
52516067Sralph }
52616067Sralph goto copyit;
52716067Sralph }
52816067Sralph if (targetexists && unlink(target) < 0) {
52916067Sralph if(!fflag)
53016067Sralph error("cannot unlink %s", target);
53116067Sralph return (1);
53216067Sralph }
53316067Sralph if (dflag) printf("move: target unlinked\n");
53416067Sralph
53516067Sralph /*
53616067Sralph * If file or directory cannot be renamed:
53716067Sralph * If directory, copy it with r option
53816067Sralph * and delete the source
53916067Sralph */
54016067Sralph copyit: if (ISDIR(s1)) {
54116067Sralph if (dflag) printf("move: directory copy %s to %s\n",source,target);
54216067Sralph copy (source, target, iflag, 1);
54316067Sralph dldir (source, iflag);
54416067Sralph return(0);
54516067Sralph }
54616067Sralph
54716067Sralph /*
54816067Sralph * If link, recreate symbolic link
54916067Sralph */
55016067Sralph if (ISLNK(s1)) {
55116067Sralph register m;
55216067Sralph char symln[MAXPATHLEN];
55316067Sralph
55416067Sralph if (readlink(source, symln, sizeof (symln)) < 0) {
55516067Sralph if (!fflag)
55616067Sralph Perror(source);
55716067Sralph return (1);
55816067Sralph }
55916067Sralph m = umask(~(s1.st_mode & MODEBITS));
56016067Sralph if (symlink(symln, target) < 0) {
56116067Sralph if (!fflag)
56216067Sralph Perror(target);
56316067Sralph return (1);
56416067Sralph }
56516067Sralph if (dflag) printf("move: symlink to target successful\n");
56616067Sralph (void) umask(m);
56716067Sralph goto cleanup;
56816067Sralph }
56916067Sralph
57016067Sralph /*
57116067Sralph * If device
57216067Sralph */
57316067Sralph if (ISDEV(s1)) {
57416067Sralph if (mknod(target, s1.st_mode, s1.st_rdev) < 0) {
57516067Sralph if (!fflag)
57616067Sralph Perror(target);
57716067Sralph return (1);
57816067Sralph }
57916067Sralph if (dflag) printf("move: mknod for target successful\n");
58016067Sralph goto cleanup;
58116067Sralph }
58216067Sralph
58316067Sralph /*
58416067Sralph * If regular file, copy it
58516067Sralph */
58616067Sralph if (ISREG(s1)) {
58716067Sralph if(dflag) printf("move: file copy %s to %s\n",source,target);
58816067Sralph copy(source, target, iflag, 0);
58916067Sralph goto cleanup;
59016067Sralph }
59116067Sralph
59216067Sralph if (!fflag)
59316067Sralph error("%s: unknown file type %o", source, s1.st_mode);
59416067Sralph return (1);
59516067Sralph
59616067Sralph /*
59716067Sralph * If a move has been successful, erase the source
59816067Sralph */
59916067Sralph cleanup:
60016067Sralph if (dflag) printf("move: cleanup\n");
60116067Sralph if (unlink(source) < 0) {
60216067Sralph if (!fflag)
60316067Sralph error("cannot unlink %s", source);
60416067Sralph return (1);
60516067Sralph }
60616067Sralph if (dflag) printf("move: %s unlinked.\n",source);
60716067Sralph if (!fflag && iflag && !mflag)
60816067Sralph printf("dl: %s deleted.\n",source);
60916067Sralph return (0);
61016067Sralph }
61116067Sralph
61216067Sralph /*VARARGS*/
query(prompt,a1,a2)61316067Sralph query(prompt, a1, a2)
61416067Sralph char *a1;
61516067Sralph {
61616067Sralph register char i, c;
61716067Sralph
61816067Sralph fprintf(stderr, prompt, a1, a2);
61916067Sralph i = c = getchar();
62016067Sralph while (c != '\n' && c != EOF)
62116067Sralph c = getchar();
62216067Sralph return (i == 'y');
62316067Sralph }
62416067Sralph
error(fmt,a1,a2)62516067Sralph error(fmt, a1, a2)
62616067Sralph char *fmt;
62716067Sralph {
62816067Sralph fprintf(stderr, "dl: ");
62916067Sralph fprintf(stderr, fmt, a1, a2);
63016067Sralph fprintf(stderr, "\n");
63116067Sralph }
63216067Sralph
Perror(s)63316067Sralph Perror(s)
63416067Sralph char *s;
63516067Sralph {
63616067Sralph char buf[MAXPATHLEN + 10];
637*33063Sbostic
638*33063Sbostic (void) sprintf(buf, "move: %s", s);
63916067Sralph perror(buf);
64016067Sralph }
64116067Sralph
Perror2(s1,s2)64216067Sralph Perror2(s1, s2)
64316067Sralph char *s1, *s2;
64416067Sralph {
64516067Sralph char buf[MAXPATHLEN + 20];
64616067Sralph
647*33063Sbostic (void) sprintf(buf, "dl: %s: %s", s1, s2);
64816067Sralph perror(buf);
64916067Sralph }
65016067Sralph
65116067Sralph #define BSIZE 8192
65216067Sralph
65316067Sralph char *rindex();
65416067Sralph
copy(from,to,iflag,rflag)65516067Sralph copy(from, to, iflag, rflag)
65616067Sralph char *from, *to;
65716067Sralph {
65816067Sralph int fold, fnew, n;
65916067Sralph char *last, destname[BSIZE], buf[BSIZE];
66016067Sralph struct stat stfrom, stto;
66116067Sralph time_t tv[2];
66216067Sralph
66316067Sralph if (dflag) printf("copy entered: from=%s to=%s iflag=%d rflag=%d\n",from,to,iflag,rflag);
66416067Sralph fold = open(from, 0);
66516067Sralph if (fold < 0) {
66616067Sralph Cerror(from,fflag);
66716067Sralph return (1);
66816067Sralph }
66916067Sralph if (fstat(fold, &stfrom) < 0) {
67016067Sralph Cerror(from,fflag);
67116067Sralph (void) close(fold);
67216067Sralph return (1);
67316067Sralph }
67416067Sralph if (dflag) printf("copy: fstat(%s) OK.\n",from);
67516067Sralph if (stat(to, &stto) >= 0 &&
67616067Sralph (stto.st_mode&S_IFMT) == S_IFDIR) {
67716067Sralph last = rindex(from, '/');
67816067Sralph if (last) last++; else last = from;
67916067Sralph if (strlen(to) + strlen(last) >= BSIZE - 1) {
68016067Sralph fprintf(stderr, "cp: %s/%s: Name too long", to, last);
68116067Sralph (void) close(fold);
68216067Sralph return(1);
68316067Sralph }
68416067Sralph (void) sprintf(destname, "%s/%s", to, last);
68516067Sralph if (dflag) printf("copy: stat %s & %s is dir., to=%s.\n",to,to,destname);
68616067Sralph to = destname;
68716067Sralph }
68816067Sralph if (!rflag && (stfrom.st_mode&S_IFMT) == S_IFDIR) {
68916067Sralph fprintf(stderr, "cp: %s is a directory, and option -r not chosen. Job aborted.\n", from);
69016067Sralph return(1);
69116067Sralph }
69216067Sralph if (rflag && (stfrom.st_mode&S_IFMT) == S_IFDIR) {
69316067Sralph (void) close(fold);
69416067Sralph if (dflag) printf("copy: rflag & from is dir., %s closed.\n",from);
69516067Sralph if (stat(to, &stto) < 0) {
69616067Sralph if (mkdir(to, (int)stfrom.st_mode) < 0) {
69716067Sralph Cerror(to,fflag);
69816067Sralph return (1);
69916067Sralph }
70016067Sralph if (dflag) printf("copy: stat(%s) failed & mkdir % successful.\n",to,to);
70116067Sralph }
70216067Sralph else {
70316067Sralph if (!fflag) {
70416067Sralph if ((stto.st_mode&S_IFMT) == S_IFDIR) {
70516067Sralph dl(to, iflag);
70616067Sralph }
70716067Sralph else {
70816067Sralph fprintf(stderr, "cp: %s: Not a directory.\n", to);
70916067Sralph return (1);
71016067Sralph }
71116067Sralph }
71216067Sralph }
71316067Sralph if (dflag) printf("copy: return with rcopy(%s,%s,%d,%d)\n",from,to,iflag,rflag);
71416067Sralph return (rcopy(from, to, iflag, rflag));
71516067Sralph }
71616067Sralph if (stat(to, &stto) >= 0) {
71716067Sralph if (dflag) printf("cp:stat(%s) o.k.\n",to);
71816067Sralph if (stfrom.st_dev == stto.st_dev &&
71916067Sralph stfrom.st_ino == stto.st_ino) {
72016067Sralph fprintf(stderr, "cp: Cannot copy file to itself.\n");
72116067Sralph (void) close(fold);
72216067Sralph return (1);
72316067Sralph }
72416067Sralph if (cflag && cs == 0) {
72516067Sralph if (!fflag)
72616067Sralph fprintf (stderr, "cp: %s exists: overwrite? ", to);
72716067Sralph if (!yes()) {
72816067Sralph (void) close(fold);
72916067Sralph return(1);
73016067Sralph }
73116067Sralph dl(to, 0);
73216067Sralph cs = 1;
73316067Sralph }
73416067Sralph }
73516067Sralph fnew = creat(to, (int)stfrom.st_mode);
73616067Sralph if (fnew < 0) {
73716067Sralph Cerror(to,fflag);
73816067Sralph (void) close(fold); return(1);
73916067Sralph }
74016067Sralph if (dflag) printf("copy: creat(%s,%d) successful.\n",to,stfrom.st_mode);
74116067Sralph for (;;) {
74216067Sralph n = read(fold, buf, BSIZE);
74316067Sralph if (n == 0)
74416067Sralph break;
74516067Sralph if (n < 0) {
74616067Sralph Cerror(from,fflag);
74716067Sralph (void) close(fold); (void) close(fnew); return (1);
74816067Sralph }
74916067Sralph if (write(fnew, buf, n) != n) {
75016067Sralph Cerror(to,fflag);
75116067Sralph (void) close(fold); (void) close(fnew); return (1);
75216067Sralph }
75316067Sralph }
75416067Sralph if (dflag) printf("copy: %s copied to %s.\n",from,to);
75516067Sralph if (!tflag) {
75616067Sralph /* restore original time-stamp */
75716067Sralph tv[0] = stfrom.st_atime;
75816067Sralph tv[1] = stfrom.st_mtime;
75916067Sralph (void) utime(to, tv);
76016067Sralph if (dflag) printf("copy: tflag on, tv[0]=%d, tv[1]=%d.\n",tv[0], tv[1]);
76116067Sralph }
76216067Sralph if (dflag) printf("copy: returning from copy, from=%s, to=%s.\n",from,to);
76316067Sralph (void) close(fold); (void) close(fnew); return (0);
76416067Sralph }
76516067Sralph
rcopy(from,to,iflag,rflag)76616067Sralph rcopy(from, to, iflag, rflag)
76716067Sralph char *from, *to;
76816067Sralph {
76916067Sralph DIR *fold = opendir(from);
77016067Sralph struct direct *dp;
77116067Sralph int errs = 0;
77216067Sralph char fromname[BUFSIZ];
77316067Sralph
77416067Sralph if (dflag) printf("rcopy: entered: from=%s, to=%s.\n",from,to);
77516067Sralph if (fold == 0) {
77616067Sralph Cerror(from,fflag);
77716067Sralph return (1);
77816067Sralph }
77916067Sralph for (;;) {
78016067Sralph dp = readdir(fold);
78116067Sralph if (dp == 0) {
78216067Sralph closedir(fold);
78316067Sralph return (errs);
78416067Sralph }
78516067Sralph if (dp->d_ino == 0)
78616067Sralph continue;
78716067Sralph if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
78816067Sralph continue;
78916067Sralph if (strlen(from) + 1 + strlen(dp->d_name) >= BUFSIZ - 1) {
79016067Sralph if (!fflag) {
79116067Sralph fprintf(stderr, "cp: %s/%s: Name too long.\n",
79216067Sralph from, dp->d_name);
79316067Sralph }
79416067Sralph errs++;
79516067Sralph continue;
79616067Sralph }
79716067Sralph (void) sprintf(fromname, "%s/%s", from, dp->d_name);
79816067Sralph if (dflag) printf("rcopy: copy(%s,%s,%d,%d)\n",fromname,to,iflag,rflag);
79916067Sralph errs += copy(fromname, to, iflag, rflag);
80016067Sralph }
80116067Sralph }
80216067Sralph
Cerror(s)80316067Sralph Cerror(s)
80416067Sralph char *s;
80516067Sralph {
80616067Sralph if (!fflag) {
80716067Sralph fprintf(stderr, "cp: ");
80816067Sralph perror(s);
80916067Sralph }
81016067Sralph }
811