forsyth@minster.UUCP (forsyth) (07/30/86)
Here are some changes from diffc to rmdir.c (7th edition) that use the catpath function just posted to net.sources (862@minster.UUCP) to correct the recently observed bug in rmdir. (I also changed the Usage message, and stopped the code from using "" as a file name.) Similar changes should apply to system V, but beware of the code in that version, in rmdir(), near the call to `strrchr'. It was changed from if((np = rindex(name, '/')) == NULL) np = name; else np++; to if((np = strrchr(name, '/')) == NULL) np = name; but unfortunately this breaks the protection (weak as it was) against doing (mkdir b; rmdir b/.) It might be best to put the np++ back in. In any case, there is still a problem that `rmdir /' results in `/ unreadable' on systems that refuse access to "" as a file name. Given the proposed target and the nature of the request, perhaps this is just as well. *** o_rmdir.c Wed Jul 23 13:49:31 1986 --- rmdir.c Wed Jul 23 14:04:32 1986 *************** *** 11,16 char *rindex(); char *strcat(); char *strcpy(); main(argc,argv) int argc; --- 11,17 ----- char *rindex(); char *strcat(); char *strcpy(); + char *catpath(); main(argc,argv) int argc; *************** *** 18,24 { if(argc < 2) { ! fprintf(stderr, "rmdir: arg count\n"); exit(1); } while(--argc) --- 19,25 ----- { if(argc < 2) { ! fprintf(stderr, "Usage: rmdir dirname ...\n"); exit(1); } while(--argc) *************** *** 30,36 char *d; { int fd; ! char *np, name[500]; struct stat st, cst; struct direct dir; --- 31,37 ----- char *d; { int fd; ! char *np, name[500], *comp[2]; struct stat st, cst; struct direct dir; *************** *** 34,40 struct stat st, cst; struct direct dir; ! strcpy(name, d); for (np = name+strlen(name); np != name && *--np == '/';) *np = 0; if((np = rindex(name, '/')) == NULL) --- 35,52 ----- struct stat st, cst; struct direct dir; ! if(stat(d,&st) < 0) { ! fprintf(stderr, "rmdir: %s non-existent\n", d); ! ++Errors; ! return; ! } ! comp[0] = d; ! comp[1] = NULL; ! if (catpath(name, sizeof name, comp) == NULL) { ! fprintf(stderr, "rmdir: the name %s is too long\n", d); ! ++Errors; ! return; ! } for (np = name+strlen(name); np != name && *--np == '/';) *np = 0; if((np = rindex(name, '/')) == NULL) *************** *** 41,48 np = name; else np++; ! if(stat(name,&st) < 0) { ! fprintf(stderr, "rmdir: %s non-existent\n", name); ++Errors; return; } --- 53,60 ----- np = name; else np++; ! if (stat(".", &cst) < 0) { ! fprintf(stderr, "rmdir: cannot stat \".\""); ++Errors; return; } *************** *** 46,56 ++Errors; return; } - if (stat("", &cst) < 0) { - fprintf(stderr, "rmdir: cannot stat \"\""); - ++Errors; - exit(1); - } if((st.st_mode & S_IFMT) != S_IFDIR) { fprintf(stderr, "rmdir: %s not a directory\n", name); ++Errors; --- 58,63 ----- ++Errors; return; } if((st.st_mode & S_IFMT) != S_IFDIR) { fprintf(stderr, "rmdir: %s not a directory\n", name); return(1); *************** *** 53,60 } if((st.st_mode & S_IFMT) != S_IFDIR) { fprintf(stderr, "rmdir: %s not a directory\n", name); ! ++Errors; ! return; } if(st.st_ino==cst.st_ino &&st.st_dev==cst.st_dev) { fprintf(stderr, "rmdir: cannot remove current directory\n"); --- 60,66 ----- } if((st.st_mode & S_IFMT) != S_IFDIR) { fprintf(stderr, "rmdir: %s not a directory\n", name); ! return(1); } if(st.st_ino==cst.st_ino &&st.st_dev==cst.st_dev) { fprintf(stderr, "rmdir: cannot remove current directory\n"); *************** *** 58,63 } if(st.st_ino==cst.st_ino &&st.st_dev==cst.st_dev) { fprintf(stderr, "rmdir: cannot remove current directory\n"); ++Errors; return; } --- 64,73 ----- } if(st.st_ino==cst.st_ino &&st.st_dev==cst.st_dev) { fprintf(stderr, "rmdir: cannot remove current directory\n"); + return(1); + } + if(!strcmp(np, ".") || !strcmp(np, "..")) { + fprintf(stderr, "rmdir: cannot remove . or ..\n"); ++Errors; return; } *************** *** 62,68 return; } if((fd = open(name,0)) < 0) { ! fprintf(stderr, "rmdir: %s unreadable\n", name); ++Errors; return; } --- 72,78 ----- return; } if((fd = open(name,0)) < 0) { ! fprintf(stderr, "rmdir: %s unreadable\n", d); ++Errors; return; } *************** *** 66,80 ++Errors; return; } ! while(read(fd, (char *)&dir, sizeof dir) == sizeof dir) { ! if(dir.d_ino == 0) continue; ! if(!strcmp(dir.d_name, ".") || !strcmp(dir.d_name, "..")) ! continue; ! fprintf(stderr, "rmdir: %s not empty\n", name); ! ++Errors; ! close(fd); ! return; ! } close(fd); if(!strcmp(np, ".") || !strcmp(np, "..")) { fprintf(stderr, "rmdir: cannot remove . or ..\n"); --- 76,90 ----- ++Errors; return; } ! while(read(fd, (char *)&dir, sizeof dir) == sizeof dir) ! if (dir.d_ino != 0 && ! strcmp(dir.d_name, ".") != 0 && ! strcmp(dir.d_name, "..") != 0) { ! fprintf(stderr, "rmdir: %s not empty\n", d); ! ++Errors; ! close(fd); ! return; ! } close(fd); strcat(name, "/."); if(access(name, 0) < 0) { /* name/. non-existent */ *************** *** 76,86 return; } close(fd); - if(!strcmp(np, ".") || !strcmp(np, "..")) { - fprintf(stderr, "rmdir: cannot remove . or ..\n"); - ++Errors; - return; - } strcat(name, "/."); if((access(name, 0)) < 0) { /* name/. non-existent */ strcat(name, "."); --- 86,91 ----- return; } close(fd); strcat(name, "/."); if(access(name, 0) < 0) { /* name/. non-existent */ strcat(name, "."); *************** *** 82,88 return; } strcat(name, "/."); ! if((access(name, 0)) < 0) { /* name/. non-existent */ strcat(name, "."); goto unl; } --- 87,93 ----- } close(fd); strcat(name, "/."); ! if(access(name, 0) < 0) { /* name/. non-existent */ strcat(name, "."); goto unl; } *************** *** 87,93 goto unl; } strcat(name, "."); ! if((access(name, 0)) < 0) /* name/.. non-existent */ goto unl2; if(access(name, 02)) { name[strlen(name)-3] = '\0'; --- 92,98 ----- goto unl; } strcat(name, "."); ! if(access(name, 0) < 0) /* name/.. non-existent */ goto unl2; if(access(name, 02)) { fprintf(stderr, "rmdir: %s: no permission\n", d); *************** *** 90,97 if((access(name, 0)) < 0) /* name/.. non-existent */ goto unl2; if(access(name, 02)) { ! name[strlen(name)-3] = '\0'; ! fprintf(stderr, "rmdir: %s: no permission\n", name); ++Errors; return; } --- 95,101 ----- if(access(name, 0) < 0) /* name/.. non-existent */ goto unl2; if(access(name, 02)) { ! fprintf(stderr, "rmdir: %s: no permission\n", d); ++Errors; return; } *************** *** 102,108 unlink(name); /* unlink name/. */ name[strlen(name)-2] = '\0'; if (unlink(name) < 0) { ! fprintf(stderr, "rmdir: %s not removed\n", name); ++Errors; } } --- 106,112 ----- unlink(name); /* unlink name/. */ name[strlen(name)-2] = '\0'; if (unlink(name) < 0) { ! fprintf(stderr, "rmdir: %s not removed\n", d); ++Errors; } }