From f6384eca672565bf820f86721de5cf25a5e5e9fe Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Thu, 3 Jul 1997 19:44:06 +0000 Subject: Fix for deleting directories that contain only veto files. Needed for interoperability with netatalk volumes. Jeremy (jallison@whistle.com) (This used to be commit e72a8513bccf77177f6fb6002057fee608947a32) --- source3/include/proto.h | 2 +- source3/smbd/chgpasswd.c | 2 +- source3/smbd/dir.c | 8 +++--- source3/smbd/reply.c | 74 +++++++++++++++++++++++++++++++++++++++++++++--- source3/smbd/server.c | 2 +- 5 files changed, 77 insertions(+), 11 deletions(-) diff --git a/source3/include/proto.h b/source3/include/proto.h index 3929348da6..ef9382279e 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -79,7 +79,7 @@ void *dptr_fetch(char *buf,int *num); void *dptr_fetch_lanman2(char *params,int dptr_num); BOOL dir_check_ftype(int cnum,int mode,struct stat *st,int dirtype); BOOL get_dir_entry(int cnum,char *mask,int dirtype,char *fname,int *size,int *mode,time_t *date,BOOL check_descend); -void *OpenDir(char *name); +void *OpenDir(char *name, BOOL use_veto); void CloseDir(void *p); char *ReadDirName(void *p); BOOL SeekDir(void *p,int pos); diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 883ad5214a..e0dd7fc0ae 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -56,7 +56,7 @@ static int findpty(char **slave) #else strcpy( line, "/dev/ptyXX" ); - dirp = OpenDir("/dev"); + dirp = OpenDir("/dev", True); if (!dirp) return(-1); while ((dpname = ReadDirName(dirp)) != NULL) { if (strncmp(dpname, "pty", 3) == 0 && strlen(dpname) == 5) { diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index bc099dd1e8..1d0228864c 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -116,7 +116,7 @@ static void *dptr_get(int key,uint32 lastused) if (dptrs_open >= MAXDIR) dptr_idleoldest(); DEBUG(4,("Reopening dptr key %d\n",key)); - if ((dirptrs[key].ptr = OpenDir(dirptrs[key].path))) + if ((dirptrs[key].ptr = OpenDir(dirptrs[key].path, True))) dptrs_open++; } return(dirptrs[key].ptr); @@ -259,7 +259,7 @@ static BOOL start_dir(int cnum,char *directory) if (! *directory) directory = "."; - Connections[cnum].dirptr = OpenDir(directory); + Connections[cnum].dirptr = OpenDir(directory, True); if (Connections[cnum].dirptr) { dptrs_open++; string_set(&Connections[cnum].dirpath,directory); @@ -520,7 +520,7 @@ typedef struct /******************************************************************* open a directory ********************************************************************/ -void *OpenDir(char *name) +void *OpenDir(char *name, BOOL use_veto) { Dir *dirp; char *n; @@ -539,7 +539,7 @@ void *OpenDir(char *name) while ((n = readdirname(p))) { int l = strlen(n)+1; /* If it's a vetoed file, pretend it doesn't even exist */ - if(is_vetoed_name(n)) + if(use_veto && is_vetoed_name(n)) continue; if (used + l > dirp->mallocsize) { int s = MAX(used+l,used+2000); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 8af4536c19..5f030d5372 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1326,7 +1326,7 @@ int reply_unlink(char *inbuf,char *outbuf) char *dname; if (check_name(directory,cnum)) - dirptr = OpenDir(directory); + dirptr = OpenDir(directory, True); /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then the pattern matches against the long name, otherwise the short name @@ -2449,10 +2449,76 @@ int reply_rmdir(char *inbuf,char *outbuf) if (check_name(directory,cnum)) { + dptr_closepath(directory,SVAL(inbuf,smb_pid)); ok = (sys_rmdir(directory) == 0); + if(!ok && (errno == ENOTEMPTY) && lp_veto_files()) + { + /* Check to see if the only thing in this directory are + vetoed files/directories. If so then delete them and + retry. If we fail to delete any of them (and we *don't* + do a recursive delete) then fail the rmdir. */ + BOOL all_veto_files = True; + char *dname; + void *dirptr = OpenDir(directory, False); + + if(dirptr != NULL) + { + int dirpos = TellDir(dirptr); + while ((dname = ReadDirName(dirptr))) + { + if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) + continue; + if(!is_vetoed_name(dname)) + { + all_veto_files = False; + break; + } + } + if(all_veto_files) + { + SeekDir(dirptr,dirpos); + while ((dname = ReadDirName(dirptr))) + { + pstring fullname; + struct stat st; + + if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) + continue; + + /* Construct the full name. */ + if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) + { + errno = ENOMEM; + break; + } + strcpy(fullname, directory); + strcat(fullname, "/"); + strcat(fullname, dname); + + if(sys_lstat(fullname, &st) != 0) + break; + if(st.st_mode & S_IFDIR) + { + if(sys_rmdir(fullname) != 0) + break; + } + else if(sys_unlink(fullname) != 0) + break; + } + CloseDir(dirptr); + /* Retry the rmdir */ + ok = (sys_rmdir(directory) == 0); + } + else + CloseDir(dirptr); + } + else + errno = ENOTEMPTY; + } + if (!ok) - DEBUG(3,("couldn't remove directory %s : %s\n", + DEBUG(3,("couldn't remove directory %s : %s\n", directory,strerror(errno))); } @@ -2670,7 +2736,7 @@ int reply_mv(char *inbuf,char *outbuf) pstring destname; if (check_name(directory,cnum)) - dirptr = OpenDir(directory); + dirptr = OpenDir(directory, True); if (dirptr) { @@ -2861,7 +2927,7 @@ int reply_copy(char *inbuf,char *outbuf) pstring destname; if (check_name(directory,cnum)) - dirptr = OpenDir(directory); + dirptr = OpenDir(directory, True); if (dirptr) { diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 8c40734ce4..30d8ce3d2a 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -361,7 +361,7 @@ static BOOL scan_directory(char *path, char *name,int snum,BOOL docache) check_mangled_stack(name); /* open the directory */ - if (!(cur_dir = OpenDir(path))) + if (!(cur_dir = OpenDir(path, True))) { DEBUG(3,("scan dir didn't open dir [%s]\n",path)); return(False); -- cgit