xref: /csrg-svn/local/local.cmd/dl.c (revision 16067)
1*16067Sralph static char *sccsid = "@(#)dl.c	4.1\t02/17/84";
2*16067Sralph 
3*16067Sralph #include <stdio.h>
4*16067Sralph #include <sys/param.h>
5*16067Sralph #include <sys/stat.h>
6*16067Sralph #include <sys/dir.h>
7*16067Sralph #include <errno.h>
8*16067Sralph #include <signal.h>
9*16067Sralph 
10*16067Sralph #define	DELIM	'/'
11*16067Sralph #define MODEBITS 07777
12*16067Sralph #define	ISDIR(st)	(((st).st_mode&S_IFMT) == S_IFDIR)
13*16067Sralph #define	ISLNK(st)	(((st).st_mode&S_IFMT) == S_IFLNK)
14*16067Sralph #define	ISREG(st)	(((st).st_mode&S_IFMT) == S_IFREG)
15*16067Sralph #define	ISDEV(st) \
16*16067Sralph 	(((st).st_mode&S_IFMT) == S_IFCHR || ((st).st_mode&S_IFMT) == S_IFBLK)
17*16067Sralph 
18*16067Sralph struct	stat s1, s2, buf;
19*16067Sralph extern	unsigned errno;
20*16067Sralph int	errcode;
21*16067Sralph char	*sprintf();
22*16067Sralph char    *path;
23*16067Sralph char    *path2;
24*16067Sralph char    line[1024];
25*16067Sralph int     cflag = 0;   /* "copy" - same as cp  */
26*16067Sralph int     dflag = 0;   /* "debug" - enable trace printf statements */
27*16067Sralph int     fflag = 0;   /* "force" option: override protection, no messages */
28*16067Sralph int     mflag = 0;   /* "move" - same as mv  */
29*16067Sralph int     cs = 0;      /* flag used with cflag to prevent endless recursion */
30*16067Sralph int     ms = 0;      /* flag used with mflag to prevent endless recursion */
31*16067Sralph int     tflag = 0;   /* restore original time stamp */
32*16067Sralph 
33*16067Sralph main(argc, argv)     /* dl.c - delete, undelete, move, copy */
34*16067Sralph char *argv[];
35*16067Sralph {
36*16067Sralph 	register char *arg;
37*16067Sralph 	char *s;
38*16067Sralph 	int mode;
39*16067Sralph 	int aflg = 0;   /* "all" option: undelete all deleted files */
40*16067Sralph 	int iflg = 0;	/* "interactive" option: send messages to user */
41*16067Sralph 	int rflg = 0;   /* "recursive" opt., used only with n */
42*16067Sralph 	int sflg = 0;   /* do not delete previous dlsave file */
43*16067Sralph 	int uflg = 0;   /* undelete named files and/or directories */
44*16067Sralph 	int nflg = 0;   /* do not provide back-up files */
45*16067Sralph 
46*16067Sralph 	if (isatty(0) == 0)	/* if standard i/o is not a terminal, */
47*16067Sralph 		fflag++;		/*  turn on the f flag                */
48*16067Sralph 
49*16067Sralph 	if (strcmp(*argv,"ud") == 0)
50*16067Sralph 		uflg++;
51*16067Sralph 
52*16067Sralph 	if (strcmp(*argv,"copy") == 0)
53*16067Sralph 		cflag++;
54*16067Sralph 
55*16067Sralph 	if (strcmp(*argv,"move") == 0)
56*16067Sralph 		mflag++;
57*16067Sralph 
58*16067Sralph 	while(argc>1 && argv[1][0]=='-') {
59*16067Sralph 		arg = *++argv;
60*16067Sralph 		argc--;
61*16067Sralph 
62*16067Sralph 		/*
63*16067Sralph 		 *  all arguments following a null option (- ) are
64*16067Sralph 		 *   treated as file names, so that file names may
65*16067Sralph 		 *   begin with a minus sign (-).
66*16067Sralph 		 */
67*16067Sralph 		if (*(arg+1) == '\0') break;
68*16067Sralph 
69*16067Sralph 		while(*++arg != '\0')
70*16067Sralph 			switch(*arg) {
71*16067Sralph 			case 'a':	/* "all" */
72*16067Sralph 				aflg++;
73*16067Sralph 				break;
74*16067Sralph 			case 'c':	/* "copy" */
75*16067Sralph 				cflag++;
76*16067Sralph 				break;
77*16067Sralph 			case 'd':	/* "debug" */
78*16067Sralph 				dflag++;
79*16067Sralph 				break;
80*16067Sralph 			case 'f':	/* "force" */
81*16067Sralph 				fflag++;
82*16067Sralph 				break;
83*16067Sralph 			case 'i':	/* "interactive" */
84*16067Sralph 				iflg++;
85*16067Sralph 				break;
86*16067Sralph 			case 'r':	/* "recursive" */
87*16067Sralph 				rflg++;
88*16067Sralph 				break;
89*16067Sralph 			case 's':	/* "save" */
90*16067Sralph 				sflg++;
91*16067Sralph 				break;
92*16067Sralph 			case 't':	/* "time" stamp */
93*16067Sralph 				tflag++;
94*16067Sralph 				break;
95*16067Sralph 			case 'u':	/* "undelete" */
96*16067Sralph 				uflg++;
97*16067Sralph 				break;
98*16067Sralph 			case 'm':	/* "move" */
99*16067Sralph 				mflag++;
100*16067Sralph 				break;
101*16067Sralph 			case 'n':	/* "not save" */
102*16067Sralph 				nflg++;
103*16067Sralph 				break;
104*16067Sralph 			default:
105*16067Sralph 				printf("dl: unknown option %s\n", *argv);
106*16067Sralph 				exit(1);
107*16067Sralph 			}
108*16067Sralph 	}
109*16067Sralph 	if (cflag || mflag || nflg)  sflg++;
110*16067Sralph 	/*
111*16067Sralph 	 * set up home directory pathname
112*16067Sralph 	 */
113*16067Sralph 	setpath();
114*16067Sralph 	/*
115*16067Sralph 	 * process "undelete all" request
116*16067Sralph 	 */
117*16067Sralph 	if(aflg) {
118*16067Sralph 		undelete_all(iflg);
119*16067Sralph 		exit;
120*16067Sralph 	}
121*16067Sralph 	/*
122*16067Sralph 	 * remove previously saved files unless "save" option,
123*16067Sralph 	 *  or ud or rm mode
124*16067Sralph 	 */
125*16067Sralph 	if(!sflg && !uflg)
126*16067Sralph 		dldir(path,0);
127*16067Sralph 	if(!nflg && lstat(path,&buf) != 0) {
128*16067Sralph 		/*
129*16067Sralph 		 * set up .dlsave directory
130*16067Sralph 	 	 */
131*16067Sralph 		mode = 0777;
132*16067Sralph           	if (mkdir(path,mode) != 0) {
133*16067Sralph 		       	   fprintf(stderr,"dl: cannot mkdir ~/.dlsave\n");
134*16067Sralph 			   perror(s);
135*16067Sralph 			   exit(1);
136*16067Sralph 		}
137*16067Sralph 	}
138*16067Sralph      	while(--argc > 0) {
139*16067Sralph 		if(!strcmp(*++argv, "..")) {
140*16067Sralph 		    	if(!fflag)
141*16067Sralph 				fprintf(stderr, "dl: cannot remove `..'\n");
142*16067Sralph 			continue;
143*16067Sralph 		}
144*16067Sralph 	       /*
145*16067Sralph 	 	* process "undelete" request(s)
146*16067Sralph 	 	*/
147*16067Sralph 		if(uflg) {
148*16067Sralph 			undelete(*argv,iflg);
149*16067Sralph 			exit;
150*16067Sralph 		}
151*16067Sralph 		else {
152*16067Sralph 		/*
153*16067Sralph 		 * process delete request(s)
154*16067Sralph 		 */
155*16067Sralph 			if (cflag) {
156*16067Sralph 				copy(*argv,argv[argc-1],iflg,rflg);
157*16067Sralph 				exit(errcode);
158*16067Sralph 			}
159*16067Sralph 			if (mflag) {
160*16067Sralph 				move(*argv,argv[argc-1],iflg);
161*16067Sralph 				exit(errcode);
162*16067Sralph 			}
163*16067Sralph 			if (nflg)
164*16067Sralph 				rm(*argv, iflg, rflg);
165*16067Sralph 			else
166*16067Sralph 				dl(*argv, iflg);
167*16067Sralph 		}
168*16067Sralph 	}
169*16067Sralph 	exit(errcode);
170*16067Sralph }
171*16067Sralph 
172*16067Sralph setpath()
173*16067Sralph {
174*16067Sralph 	char *home;
175*16067Sralph 	char *suffix;
176*16067Sralph 	char *getenv();
177*16067Sralph 
178*16067Sralph 	home = "HOME";
179*16067Sralph 	if ((path=getenv(home)) == NULL) {
180*16067Sralph 		fprintf(stderr,"dl: getenv failed\n");
181*16067Sralph 		exit(1);
182*16067Sralph 	}
183*16067Sralph 	suffix = "/.dlsave";
184*16067Sralph 	strcat(path,suffix);
185*16067Sralph 	return;
186*16067Sralph }
187*16067Sralph 
188*16067Sralph package(argu)
189*16067Sralph char argu[];
190*16067Sralph {
191*16067Sralph 	register int i, j, k;
192*16067Sralph 	char  *slash, *slashdot;
193*16067Sralph 	char  *place;
194*16067Sralph 	char  line2[512];
195*16067Sralph 
196*16067Sralph 	place = line2;
197*16067Sralph 	strcpy(place,argu);
198*16067Sralph 	path2 = line;
199*16067Sralph 	strcpy(path2,path);
200*16067Sralph 	slashdot = "/.#";
201*16067Sralph 	strcat(path2,slashdot);
202*16067Sralph 	i = strlen(argu);
203*16067Sralph 	slash = "/";
204*16067Sralph 	k = 0;
205*16067Sralph 	for (j=0;j<i;j++) {
206*16067Sralph 		if (place[j] == *slash) {
207*16067Sralph 			k = j + 1;
208*16067Sralph 		}
209*16067Sralph 	}
210*16067Sralph 	strcat(path2,argu+k);
211*16067Sralph 	return;
212*16067Sralph }
213*16067Sralph 
214*16067Sralph undelete_all(iflg)
215*16067Sralph {
216*16067Sralph 	struct direct *dp;
217*16067Sralph 	DIR *dirp;
218*16067Sralph 	char *filename;
219*16067Sralph 	int x;
220*16067Sralph 
221*16067Sralph 	/*
222*16067Sralph 	 * undelete all saved files (a option)
223*16067Sralph 	 */
224*16067Sralph 	if((dirp = opendir(path)) == NULL) {
225*16067Sralph 		if(!fflag)
226*16067Sralph 			printf("uda: cannot read %s?\n", path);
227*16067Sralph 		exit(1);
228*16067Sralph 	}
229*16067Sralph 	while((dp = readdir(dirp)) != NULL) {
230*16067Sralph              	if(dp->d_ino != 0 && !dotname(dp->d_name)) {
231*16067Sralph 			filename = (dp->d_name)+2;
232*16067Sralph 			package(filename);
233*16067Sralph 			if(iflg) {
234*16067Sralph 				printf("uda: undelete %s?", filename);
235*16067Sralph 				if (!yes())
236*16067Sralph 					goto no;
237*16067Sralph 			}
238*16067Sralph 			if(lstat(filename, &buf) == 0) {
239*16067Sralph 				printf("uda: %s exists. Override?", filename);
240*16067Sralph 				if(!yes())
241*16067Sralph 					goto no;
242*16067Sralph 			}
243*16067Sralph 			x = move(path2,filename,0);
244*16067Sralph 			if(iflg) {
245*16067Sralph 			        if (x >= 0)
246*16067Sralph 				       printf("uda: %s undeleted.\n", filename);
247*16067Sralph 				else
248*16067Sralph 				       printf("uda: unable to undelete %s\n", filename);
249*16067Sralph 			}
250*16067Sralph no:		continue;
251*16067Sralph 	        }
252*16067Sralph 	}
253*16067Sralph 	closedir(dirp);
254*16067Sralph 	return;
255*16067Sralph }
256*16067Sralph 
257*16067Sralph undelete(arg,iflg)
258*16067Sralph char arg[];
259*16067Sralph {
260*16067Sralph 	struct stat buf1, buf2;
261*16067Sralph 	int x;
262*16067Sralph 
263*16067Sralph 	/*
264*16067Sralph 	 * undelete a saved file (u option)
265*16067Sralph 	 */
266*16067Sralph 	package(arg);
267*16067Sralph 	if(lstat(path2, &buf1)) {
268*16067Sralph 		if (!fflag)
269*16067Sralph 			printf("ud: %s nonexistent\n", path2);
270*16067Sralph 		++errcode;
271*16067Sralph 	    	return;
272*16067Sralph 	}
273*16067Sralph 	if(iflg) {
274*16067Sralph 		printf("ud: undelete %s?", arg);
275*16067Sralph 		if(!yes())
276*16067Sralph 			return;
277*16067Sralph 	}
278*16067Sralph 	if(lstat(arg, &buf2) == 0) {
279*16067Sralph 			printf("ud: %s exists: overwrite?", arg);
280*16067Sralph 			if(!yes())
281*16067Sralph 				return;
282*16067Sralph 	}
283*16067Sralph         x = move(path2,arg,0);
284*16067Sralph 	if(iflg) {
285*16067Sralph 		if (x >= 0)
286*16067Sralph       	      		printf("ud: %s undeleted.\n", arg);
287*16067Sralph         	else
288*16067Sralph        	      		printf("ud: unable to undelete %s\n", arg);
289*16067Sralph 	}
290*16067Sralph 	return;
291*16067Sralph }
292*16067Sralph 
293*16067Sralph rm(arg, iflg, rflg)
294*16067Sralph char arg[];
295*16067Sralph {
296*16067Sralph 	if (dflag) printf("rm entered: arg=%s fflag=%d iflg=%d rflg=%d\n",arg,fflag,iflg,rflg);
297*16067Sralph 	if(lstat(arg, &buf)) {
298*16067Sralph 		if (!fflag)
299*16067Sralph 			printf("rm: %s nonexistent\n", arg);
300*16067Sralph 		++errcode;
301*16067Sralph 	    	return;
302*16067Sralph 	}
303*16067Sralph 	/*
304*16067Sralph 	 * unlink file named by arg
305*16067Sralph 	 */
306*16067Sralph 	if ((buf.st_mode&S_IFMT) == S_IFDIR || rflg) {
307*16067Sralph 		if(iflg) {
308*16067Sralph 			printf("rm: remove directory %s?", arg);
309*16067Sralph 			if(!yes())
310*16067Sralph 				return;
311*16067Sralph 		}
312*16067Sralph 		dldir(arg, iflg);
313*16067Sralph 		return;
314*16067Sralph 	}
315*16067Sralph 	if (!fflag && iflg) {
316*16067Sralph 		printf("rm: remove %s?", arg);
317*16067Sralph 		if (!yes())
318*16067Sralph 			return;
319*16067Sralph 	}
320*16067Sralph 	else if (!fflag) {
321*16067Sralph 		if ((buf.st_mode&S_IFMT) != S_IFLNK && access(arg, 02) < 0) {
322*16067Sralph 			printf("rm: override protection %o for %s?\n",buf.st_mode&0777,arg);
323*16067Sralph 			if (!yes())
324*16067Sralph 				return;
325*16067Sralph 		}
326*16067Sralph 	}
327*16067Sralph 	if (unlink(arg) && !fflag) {
328*16067Sralph 		printf ("rm: %s not removed.\n",arg);
329*16067Sralph 		++errcode;
330*16067Sralph 	}
331*16067Sralph 	else {
332*16067Sralph 		if (!fflag && iflg)
333*16067Sralph 			printf ("rm: %s removed.\n",arg);
334*16067Sralph 	}
335*16067Sralph 	return;
336*16067Sralph }
337*16067Sralph 
338*16067Sralph dl(arg, iflg)
339*16067Sralph char arg[];
340*16067Sralph {
341*16067Sralph 	/*
342*16067Sralph 	 * move the argument (file or directory) to
343*16067Sralph 	 *  .dlsave directory in user's home directory
344*16067Sralph 	 */
345*16067Sralph 	if (dflag) printf("dl entered: arg=%s fflag=%d iflg=%d\n",arg,fflag,iflg);
346*16067Sralph 	package(arg);
347*16067Sralph 	move(arg,path2,iflg);
348*16067Sralph 	return;
349*16067Sralph }
350*16067Sralph 
351*16067Sralph dldir(arg, iflg)
352*16067Sralph char arg[];
353*16067Sralph {
354*16067Sralph 	struct  stat  buf1, buf2;
355*16067Sralph 	struct direct *dp;
356*16067Sralph 	DIR *dirp;
357*16067Sralph 	char name[BUFSIZ];
358*16067Sralph 
359*16067Sralph 	if (dflag) printf("dldir entered: arg=%s fflag=%d iflg=%d\n",arg,fflag,iflg);
360*16067Sralph 	if(lstat(arg, &buf1)) {
361*16067Sralph 		if (!fflag && iflg)
362*16067Sralph 			printf("dldir: %s nonexistent\n", arg);
363*16067Sralph 		++errcode;
364*16067Sralph 	    	return;
365*16067Sralph 	}
366*16067Sralph 	/*
367*16067Sralph 	 * if the argument is a directory,
368*16067Sralph 	 * recursively remove the directory's contents
369*16067Sralph 	 * and then the directory.
370*16067Sralph 	 */
371*16067Sralph 	if ((buf1.st_mode&S_IFMT) == S_IFDIR) {
372*16067Sralph 		if (access(arg, 02) < 0) {
373*16067Sralph 			if(!fflag) {
374*16067Sralph 			 	printf("dldir: %s not accessable\n",arg);
375*16067Sralph 			}
376*16067Sralph 			errcode++;
377*16067Sralph 			return;
378*16067Sralph 		}
379*16067Sralph 		if((dirp = opendir(arg)) == NULL)
380*16067Sralph 			exit(1);
381*16067Sralph 		while((dp = readdir(dirp)) != NULL) {
382*16067Sralph 			if(dp->d_ino != 0 && !dotname(dp->d_name)) {
383*16067Sralph 				sprintf(name, "%s/%s", arg, dp->d_name);
384*16067Sralph 				if (dflag) printf("dldir: name= %s\n",name);
385*16067Sralph 				if(lstat(name, &buf2)) {
386*16067Sralph 					if (!fflag)
387*16067Sralph 					   printf("dldir: %s nonexistent\n", name);
388*16067Sralph 					++errcode;
389*16067Sralph 	    				return;
390*16067Sralph 				}
391*16067Sralph 				if ((buf2.st_mode&S_IFMT) == S_IFDIR) {
392*16067Sralph     				if(!fflag && iflg) {
393*16067Sralph 					printf("dldir: delete directory %s?", name);
394*16067Sralph 					if(!yes())
395*16067Sralph 						return;
396*16067Sralph    				}
397*16067Sralph   				dldir(name, iflg);
398*16067Sralph 				}
399*16067Sralph 				else {
400*16067Sralph     					if(!fflag && iflg) {
401*16067Sralph 					   printf("dldir: delete file %s?", name);
402*16067Sralph 						if(!yes())
403*16067Sralph 							return;
404*16067Sralph    					}
405*16067Sralph 			       		/*
406*16067Sralph 	 				 * permanently remove the file
407*16067Sralph 	 				 */
408*16067Sralph 					if (unlink(name)) {
409*16067Sralph 					  if (!fflag)
410*16067Sralph 					   printf("dldir: %s not removed\n", name);
411*16067Sralph 					   ++errcode;
412*16067Sralph 					}
413*16067Sralph 					else {
414*16067Sralph 					   if (!fflag && iflg)
415*16067Sralph 					     printf("dldir: %s removed.\n", name);
416*16067Sralph 					}
417*16067Sralph 				}
418*16067Sralph 			}
419*16067Sralph 		}
420*16067Sralph 		closedir(dirp);
421*16067Sralph 		if (dotname(arg))
422*16067Sralph 			return;
423*16067Sralph 		if (rmdir(arg) < 0) {
424*16067Sralph 			if(!fflag && iflg) {
425*16067Sralph 				fprintf(stderr, "dldir: rmdir:");
426*16067Sralph 				perror(arg);
427*16067Sralph 			}
428*16067Sralph 			errcode++;
429*16067Sralph 		}
430*16067Sralph 		else {
431*16067Sralph 			if(!fflag && iflg)
432*16067Sralph 				printf("dldir: directory %s removed.\n",arg);
433*16067Sralph 		}
434*16067Sralph 	return;
435*16067Sralph 	}
436*16067Sralph }
437*16067Sralph 
438*16067Sralph dotname(s)
439*16067Sralph char *s;
440*16067Sralph {
441*16067Sralph 	if(s[0] == '.')
442*16067Sralph 		if(s[1] == '.')
443*16067Sralph 			if(s[2] == '\0')
444*16067Sralph 				return(1);
445*16067Sralph 			else
446*16067Sralph 				return(0);
447*16067Sralph 		else if(s[1] == '\0')
448*16067Sralph 			return(1);
449*16067Sralph 	return(0);
450*16067Sralph }
451*16067Sralph 
452*16067Sralph yes()
453*16067Sralph {
454*16067Sralph 	int i, b;
455*16067Sralph 
456*16067Sralph 	i = b = getchar();
457*16067Sralph 	while(b != '\n' && b != EOF)
458*16067Sralph 		b = getchar();
459*16067Sralph 	return(i == 'y');
460*16067Sralph }
461*16067Sralph 
462*16067Sralph move(source, target, iflag)
463*16067Sralph 	char *source, *target;
464*16067Sralph {
465*16067Sralph 	int targetexists;
466*16067Sralph 	int sw = 0;
467*16067Sralph 
468*16067Sralph 	if (dflag) printf("move entered: source=%s target=%s fflag=%d iflag=%d\n",source,target,fflag,iflag);
469*16067Sralph 	if (lstat(source, &s1) < 0) {
470*16067Sralph 		if (!fflag)
471*16067Sralph 			error("cannot access %s", source);
472*16067Sralph 		return (1);
473*16067Sralph 	}
474*16067Sralph 	if (dflag) printf("move: lstat(%s) successful\n",source);
475*16067Sralph 	/*
476*16067Sralph 	 * First, try to rename source to target.
477*16067Sralph 	 */
478*16067Sralph 	targetexists = lstat(target, &s2) >= 0;
479*16067Sralph 	if (targetexists) {
480*16067Sralph 		if (dflag) printf("move: lstat(%s) successful\n",target);
481*16067Sralph 		if (s1.st_dev == s2.st_dev && s1.st_ino == s2.st_ino) {
482*16067Sralph 			if (!fflag)
483*16067Sralph 			      error("%s and %s are identical", source, target);
484*16067Sralph 			return (1);
485*16067Sralph 		}
486*16067Sralph 		if (access(target, 2) < 0 && !fflag && isatty(fileno(stdin))) {
487*16067Sralph 			if (query("override protection %o for %s? ",
488*16067Sralph 			  s2.st_mode & MODEBITS, target) == 0)
489*16067Sralph 				return (1);
490*16067Sralph 			sw++;
491*16067Sralph 		}
492*16067Sralph 		if (mflag && ms == 0) {
493*16067Sralph 			if (ISREG(s2)) {
494*16067Sralph 				if (!fflag && sw == 0) {
495*16067Sralph 		   		printf("overwrite file %s?", target);
496*16067Sralph 				if(!yes())
497*16067Sralph 					return;
498*16067Sralph 				}
499*16067Sralph 			ms = 1;
500*16067Sralph 			dl (target, 0);
501*16067Sralph 			}
502*16067Sralph 			else
503*16067Sralph 			if (s1.st_dev != s2.st_dev && ISDIR(s2))
504*16067Sralph 				goto copyit;
505*16067Sralph 		}
506*16067Sralph 	}
507*16067Sralph 	if (!fflag && iflag && !mflag) {
508*16067Sralph 		if (ISDIR(s1))
509*16067Sralph 			printf("dl: delete directory %s?", source);
510*16067Sralph 		else
511*16067Sralph 			printf("dl: delete file %s?", source);
512*16067Sralph 		if(!yes())
513*16067Sralph 			return;
514*16067Sralph 	}
515*16067Sralph 	if(dflag) printf("move(1)rename: source=%s, target=%s\n",source, target);
516*16067Sralph 	if (rename(source, target) >= 0) {
517*16067Sralph 		if (!fflag && iflag && !mflag)
518*16067Sralph 			printf("dl: %s deleted. \n",source);
519*16067Sralph 		if (dflag) printf("move: %s renamed %s.\n",source,target);
520*16067Sralph 		return (0);
521*16067Sralph 	}
522*16067Sralph 	if (dflag) printf("move/rename: errno=%d\n",errno);
523*16067Sralph 	if (errno != EXDEV) {
524*16067Sralph 		if (!fflag && iflag) {
525*16067Sralph 			Perror2(source, "rename");
526*16067Sralph 		}
527*16067Sralph 		goto copyit;
528*16067Sralph 	}
529*16067Sralph 	if (targetexists && unlink(target) < 0) {
530*16067Sralph 		if(!fflag)
531*16067Sralph 			error("cannot unlink %s", target);
532*16067Sralph 		return (1);
533*16067Sralph 	}
534*16067Sralph 	if (dflag) printf("move: target unlinked\n");
535*16067Sralph 
536*16067Sralph 	/*
537*16067Sralph 	 * If file or directory cannot be renamed:
538*16067Sralph 	 *  If directory, copy it with r option
539*16067Sralph 	 *   and delete the source
540*16067Sralph 	 */
541*16067Sralph copyit:	if (ISDIR(s1)) {
542*16067Sralph 	     if (dflag) printf("move: directory copy %s to %s\n",source,target);
543*16067Sralph 		copy (source, target, iflag, 1);
544*16067Sralph 		dldir (source, iflag);
545*16067Sralph 		return(0);
546*16067Sralph 	}
547*16067Sralph 
548*16067Sralph 	/*
549*16067Sralph 	 *  If link, recreate symbolic link
550*16067Sralph 	 */
551*16067Sralph 	if (ISLNK(s1)) {
552*16067Sralph 		register m;
553*16067Sralph 		char symln[MAXPATHLEN];
554*16067Sralph 
555*16067Sralph 		if (readlink(source, symln, sizeof (symln)) < 0) {
556*16067Sralph 			if (!fflag)
557*16067Sralph 				Perror(source);
558*16067Sralph 				return (1);
559*16067Sralph 		}
560*16067Sralph 		m = umask(~(s1.st_mode & MODEBITS));
561*16067Sralph 		if (symlink(symln, target) < 0) {
562*16067Sralph 			if (!fflag)
563*16067Sralph 				Perror(target);
564*16067Sralph 				return (1);
565*16067Sralph 		}
566*16067Sralph 		if (dflag) printf("move: symlink to target successful\n");
567*16067Sralph 		(void) umask(m);
568*16067Sralph 		goto cleanup;
569*16067Sralph 	}
570*16067Sralph 
571*16067Sralph 	/*
572*16067Sralph 	 *  If device
573*16067Sralph 	 */
574*16067Sralph 	if (ISDEV(s1)) {
575*16067Sralph 		if (mknod(target, s1.st_mode, s1.st_rdev) < 0) {
576*16067Sralph 			if (!fflag)
577*16067Sralph 				Perror(target);
578*16067Sralph 			return (1);
579*16067Sralph 		}
580*16067Sralph 		if (dflag) printf("move: mknod for target successful\n");
581*16067Sralph 		goto cleanup;
582*16067Sralph 	}
583*16067Sralph 
584*16067Sralph 	/*
585*16067Sralph 	 *  If regular file, copy it
586*16067Sralph 	 */
587*16067Sralph 	if (ISREG(s1)) {
588*16067Sralph 	     	if(dflag) printf("move: file copy %s to %s\n",source,target);
589*16067Sralph 		copy(source, target, iflag, 0);
590*16067Sralph 		goto cleanup;
591*16067Sralph  	}
592*16067Sralph 
593*16067Sralph 	if (!fflag)
594*16067Sralph 		error("%s: unknown file type %o", source, s1.st_mode);
595*16067Sralph 	return (1);
596*16067Sralph 
597*16067Sralph 	/*
598*16067Sralph 	 *  If a move has been successful, erase the source
599*16067Sralph 	 */
600*16067Sralph cleanup:
601*16067Sralph 	if (dflag) printf("move: cleanup\n");
602*16067Sralph 	if (unlink(source) < 0) {
603*16067Sralph 		if (!fflag)
604*16067Sralph 			error("cannot unlink %s", source);
605*16067Sralph 		return (1);
606*16067Sralph 	}
607*16067Sralph 	if (dflag) printf("move: %s unlinked.\n",source);
608*16067Sralph 	if (!fflag && iflag && !mflag)
609*16067Sralph 		printf("dl: %s deleted.\n",source);
610*16067Sralph 	return (0);
611*16067Sralph }
612*16067Sralph 
613*16067Sralph /*VARARGS*/
614*16067Sralph query(prompt, a1, a2)
615*16067Sralph 	char *a1;
616*16067Sralph {
617*16067Sralph 	register char i, c;
618*16067Sralph 
619*16067Sralph 	fprintf(stderr, prompt, a1, a2);
620*16067Sralph 	i = c = getchar();
621*16067Sralph 	while (c != '\n' && c != EOF)
622*16067Sralph 		c = getchar();
623*16067Sralph 	return (i == 'y');
624*16067Sralph }
625*16067Sralph 
626*16067Sralph error(fmt, a1, a2)
627*16067Sralph 	char *fmt;
628*16067Sralph {
629*16067Sralph 	fprintf(stderr, "dl: ");
630*16067Sralph 	fprintf(stderr, fmt, a1, a2);
631*16067Sralph 	fprintf(stderr, "\n");
632*16067Sralph }
633*16067Sralph 
634*16067Sralph Perror(s)
635*16067Sralph 	char *s;
636*16067Sralph {
637*16067Sralph 	char buf[MAXPATHLEN + 10];
638*16067Sralph 
639*16067Sralph 	sprintf(buf, "move: %s", s);
640*16067Sralph 	perror(buf);
641*16067Sralph }
642*16067Sralph 
643*16067Sralph Perror2(s1, s2)
644*16067Sralph 	char *s1, *s2;
645*16067Sralph {
646*16067Sralph 	char buf[MAXPATHLEN + 20];
647*16067Sralph 
648*16067Sralph 	sprintf(buf, "dl: %s: %s", s1, s2);
649*16067Sralph 	perror(buf);
650*16067Sralph }
651*16067Sralph 
652*16067Sralph #define	BSIZE	8192
653*16067Sralph 
654*16067Sralph char	*rindex();
655*16067Sralph 
656*16067Sralph copy(from, to, iflag, rflag)
657*16067Sralph 	char *from, *to;
658*16067Sralph {
659*16067Sralph 	int fold, fnew, n;
660*16067Sralph 	char *last, destname[BSIZE], buf[BSIZE];
661*16067Sralph 	struct stat stfrom, stto;
662*16067Sralph 	time_t tv[2];
663*16067Sralph 
664*16067Sralph 	if (dflag) printf("copy entered: from=%s to=%s iflag=%d rflag=%d\n",from,to,iflag,rflag);
665*16067Sralph 	fold = open(from, 0);
666*16067Sralph 	if (fold < 0) {
667*16067Sralph 		Cerror(from,fflag);
668*16067Sralph 		return (1);
669*16067Sralph 	}
670*16067Sralph 	if (fstat(fold, &stfrom) < 0) {
671*16067Sralph 		Cerror(from,fflag);
672*16067Sralph 		(void) close(fold);
673*16067Sralph 		return (1);
674*16067Sralph 	}
675*16067Sralph 	if (dflag) printf("copy: fstat(%s) OK.\n",from);
676*16067Sralph 	if (stat(to, &stto) >= 0 &&
677*16067Sralph 	   (stto.st_mode&S_IFMT) == S_IFDIR) {
678*16067Sralph 		last = rindex(from, '/');
679*16067Sralph 		if (last) last++; else last = from;
680*16067Sralph 		if (strlen(to) + strlen(last) >= BSIZE - 1) {
681*16067Sralph 			fprintf(stderr, "cp: %s/%s: Name too long", to, last);
682*16067Sralph 			(void) close(fold);
683*16067Sralph 			return(1);
684*16067Sralph 		}
685*16067Sralph 		(void) sprintf(destname, "%s/%s", to, last);
686*16067Sralph 		if (dflag) printf("copy: stat %s & %s is dir., to=%s.\n",to,to,destname);
687*16067Sralph 		to = destname;
688*16067Sralph 	}
689*16067Sralph 	if (!rflag && (stfrom.st_mode&S_IFMT) == S_IFDIR) {
690*16067Sralph 		fprintf(stderr, "cp: %s is a directory, and option -r not chosen.  Job aborted.\n", from);
691*16067Sralph 		return(1);
692*16067Sralph 	}
693*16067Sralph 	if (rflag && (stfrom.st_mode&S_IFMT) == S_IFDIR) {
694*16067Sralph 		(void) close(fold);
695*16067Sralph 		if (dflag) printf("copy: rflag & from is dir., %s closed.\n",from);
696*16067Sralph 		if (stat(to, &stto) < 0) {
697*16067Sralph 			if (mkdir(to, (int)stfrom.st_mode) < 0) {
698*16067Sralph 				Cerror(to,fflag);
699*16067Sralph 				return (1);
700*16067Sralph 			}
701*16067Sralph 			if (dflag) printf("copy: stat(%s) failed & mkdir % successful.\n",to,to);
702*16067Sralph 		}
703*16067Sralph 		else {
704*16067Sralph 			if (!fflag) {
705*16067Sralph 				if ((stto.st_mode&S_IFMT) == S_IFDIR) {
706*16067Sralph 				dl(to, iflag);
707*16067Sralph 				}
708*16067Sralph 				else {
709*16067Sralph 			      		fprintf(stderr, "cp: %s: Not a directory.\n", to);
710*16067Sralph 			      		return (1);
711*16067Sralph 				}
712*16067Sralph 			}
713*16067Sralph 		}
714*16067Sralph 		if (dflag) printf("copy: return with rcopy(%s,%s,%d,%d)\n",from,to,iflag,rflag);
715*16067Sralph 		return (rcopy(from, to, iflag, rflag));
716*16067Sralph 	}
717*16067Sralph 	if (stat(to, &stto) >= 0) {
718*16067Sralph 		if (dflag) printf("cp:stat(%s) o.k.\n",to);
719*16067Sralph 		if (stfrom.st_dev == stto.st_dev &&
720*16067Sralph 		   stfrom.st_ino == stto.st_ino) {
721*16067Sralph 			fprintf(stderr, "cp: Cannot copy file to itself.\n");
722*16067Sralph 			(void) close(fold);
723*16067Sralph 			return (1);
724*16067Sralph 		}
725*16067Sralph 		if (cflag && cs == 0) {
726*16067Sralph 			if (!fflag)
727*16067Sralph 			     fprintf (stderr, "cp: %s exists: overwrite? ", to);
728*16067Sralph 			     if (!yes()) {
729*16067Sralph 			        	(void) close(fold);
730*16067Sralph 					return(1);
731*16067Sralph 			}
732*16067Sralph 			dl(to, 0);
733*16067Sralph 			cs = 1;
734*16067Sralph 		}
735*16067Sralph 	}
736*16067Sralph 	fnew = creat(to, (int)stfrom.st_mode);
737*16067Sralph 	if (fnew < 0) {
738*16067Sralph 		Cerror(to,fflag);
739*16067Sralph 		(void) close(fold); return(1);
740*16067Sralph 	}
741*16067Sralph 	if (dflag) printf("copy: creat(%s,%d) successful.\n",to,stfrom.st_mode);
742*16067Sralph 	for (;;) {
743*16067Sralph 		n = read(fold, buf, BSIZE);
744*16067Sralph 		if (n == 0)
745*16067Sralph 			break;
746*16067Sralph 		if (n < 0) {
747*16067Sralph 			Cerror(from,fflag);
748*16067Sralph 			(void) close(fold); (void) close(fnew); return (1);
749*16067Sralph 		}
750*16067Sralph 		if (write(fnew, buf, n) != n) {
751*16067Sralph 			Cerror(to,fflag);
752*16067Sralph 			(void) close(fold); (void) close(fnew); return (1);
753*16067Sralph 		}
754*16067Sralph 	}
755*16067Sralph 	if (dflag) printf("copy: %s copied to %s.\n",from,to);
756*16067Sralph 	if (!tflag) {
757*16067Sralph 		/* restore original time-stamp */
758*16067Sralph 		tv[0] = stfrom.st_atime;
759*16067Sralph 		tv[1] = stfrom.st_mtime;
760*16067Sralph 		(void) utime(to, tv);
761*16067Sralph 		if (dflag) printf("copy: tflag on, tv[0]=%d, tv[1]=%d.\n",tv[0], tv[1]);
762*16067Sralph 	}
763*16067Sralph 	if (dflag) printf("copy: returning from copy, from=%s, to=%s.\n",from,to);
764*16067Sralph 	(void) close(fold); (void) close(fnew); return (0);
765*16067Sralph }
766*16067Sralph 
767*16067Sralph rcopy(from, to, iflag, rflag)
768*16067Sralph 	char *from, *to;
769*16067Sralph {
770*16067Sralph 	DIR *fold = opendir(from);
771*16067Sralph 	struct direct *dp;
772*16067Sralph 	int errs = 0;
773*16067Sralph 	char fromname[BUFSIZ];
774*16067Sralph 
775*16067Sralph 	if (dflag) printf("rcopy: entered: from=%s, to=%s.\n",from,to);
776*16067Sralph 	if (fold == 0) {
777*16067Sralph 		Cerror(from,fflag);
778*16067Sralph 		return (1);
779*16067Sralph 	}
780*16067Sralph 	for (;;) {
781*16067Sralph 		dp = readdir(fold);
782*16067Sralph 		if (dp == 0) {
783*16067Sralph 			closedir(fold);
784*16067Sralph 			return (errs);
785*16067Sralph 		}
786*16067Sralph 		if (dp->d_ino == 0)
787*16067Sralph 			continue;
788*16067Sralph 		if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
789*16067Sralph 			continue;
790*16067Sralph 		if (strlen(from) + 1 + strlen(dp->d_name) >= BUFSIZ - 1) {
791*16067Sralph 			if (!fflag) {
792*16067Sralph 				fprintf(stderr, "cp: %s/%s: Name too long.\n",
793*16067Sralph 			    		from, dp->d_name);
794*16067Sralph 			}
795*16067Sralph 			errs++;
796*16067Sralph 			continue;
797*16067Sralph 		}
798*16067Sralph 		(void) sprintf(fromname, "%s/%s", from, dp->d_name);
799*16067Sralph 		if (dflag) printf("rcopy: copy(%s,%s,%d,%d)\n",fromname,to,iflag,rflag);
800*16067Sralph 		errs += copy(fromname, to, iflag, rflag);
801*16067Sralph 	}
802*16067Sralph }
803*16067Sralph 
804*16067Sralph Cerror(s)
805*16067Sralph 	char *s;
806*16067Sralph {
807*16067Sralph 	if (!fflag) {
808*16067Sralph 	 	fprintf(stderr, "cp: ");
809*16067Sralph 		perror(s);
810*16067Sralph 	}
811*16067Sralph }
812