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