diff options
author | Aravind Srinivasan <aravind.srinivasan@isilon.com> | 2009-08-26 14:56:09 -0700 |
---|---|---|
committer | Tim Prouty <tprouty@samba.org> | 2009-08-28 16:38:57 -0700 |
commit | e046b382f24f507a19bfb020b145ea2ec8acafcb (patch) | |
tree | 867511a82c4772ee8f325c48ed1ec3f0b5e5d093 /source3/smbd | |
parent | 77e2403f1314a28722f0fb21f6682320b2e9935d (diff) | |
download | samba-e046b382f24f507a19bfb020b145ea2ec8acafcb.tar.gz samba-e046b382f24f507a19bfb020b145ea2ec8acafcb.tar.bz2 samba-e046b382f24f507a19bfb020b145ea2ec8acafcb.zip |
s3: Add a new VFS op called SMB_VFS_TRANSLATE_NAME
This vop is designed to work in tandem with SMB_VFS_READDIR to allow
vfs modules to make modifications to arbitrary filenames before
they're consumed by callers. Subsequently the core directory
enumeration code in smbd is now changed to free the memory that may be
allocated in a module. This vop enables the new version of catia in
the following patch.
Signed-off-by: Tim Prouty <tprouty@samba.org>
Diffstat (limited to 'source3/smbd')
-rw-r--r-- | source3/smbd/dir.c | 35 | ||||
-rw-r--r-- | source3/smbd/filename.c | 6 | ||||
-rw-r--r-- | source3/smbd/msdfs.c | 4 | ||||
-rw-r--r-- | source3/smbd/reply.c | 50 | ||||
-rw-r--r-- | source3/smbd/vfs.c | 21 |
5 files changed, 92 insertions, 24 deletions
diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 73c4cbb3e7..60fa0306b9 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -585,15 +585,16 @@ int dptr_dnum(struct dptr_struct *dptr) Return the next visible file name, skipping veto'd and invisible files. ****************************************************************************/ -static const char *dptr_normal_ReadDirName(struct dptr_struct *dptr, +static char *dptr_normal_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst) { /* Normal search for the next file. */ - const char *name; + char *name; while ((name = ReadDirName(dptr->dir_hnd, poffset, pst)) != NULL) { if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) { return name; } + TALLOC_FREE(name); } return NULL; } @@ -612,14 +613,12 @@ char *dptr_ReadDirName(TALLOC_CTX *ctx, char *pathreal = NULL; char *found_name = NULL; int ret; - const char *name_temp = NULL; NTSTATUS status; SET_STAT_INVALID(*pst); if (dptr->has_wild || dptr->did_stat) { - name_temp = dptr_normal_ReadDirName(dptr, poffset, pst); - name = talloc_strdup(ctx, name_temp); + name = dptr_normal_ReadDirName(dptr, poffset, pst); return name; } @@ -707,8 +706,8 @@ char *dptr_ReadDirName(TALLOC_CTX *ctx, TALLOC_FREE(pathreal); - name_temp = dptr_normal_ReadDirName(dptr, poffset, pst); - name = talloc_strdup(ctx, name_temp); + name = dptr_normal_ReadDirName(dptr, poffset, pst); + return name; clean: @@ -1337,10 +1336,10 @@ struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn, Don't check for veto or invisible files. ********************************************************************/ -const char *ReadDirName(struct smb_Dir *dirp, long *poffset, +char *ReadDirName(struct smb_Dir *dirp, long *poffset, SMB_STRUCT_STAT *sbuf) { - const char *n; + char *n; connection_struct *conn = dirp->conn; /* Cheat to allow . and .. to be the first entries returned. */ @@ -1348,11 +1347,15 @@ const char *ReadDirName(struct smb_Dir *dirp, long *poffset, (*poffset == DOT_DOT_DIRECTORY_OFFSET)) && (dirp->file_number < 2)) { if (dirp->file_number == 0) { - n = "."; + n = talloc_strdup(talloc_tos(), "."); + if (n == NULL) + return NULL; *poffset = dirp->offset = START_OF_DIRECTORY_OFFSET; } else { *poffset = dirp->offset = DOT_DOT_DIRECTORY_OFFSET; - n = ".."; + n = talloc_strdup(talloc_tos(), ".."); + if (n == NULL) + return NULL; } dirp->file_number++; return n; @@ -1368,6 +1371,7 @@ const char *ReadDirName(struct smb_Dir *dirp, long *poffset, /* Ignore . and .. - we've already returned them. */ if (*n == '.') { if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) { + TALLOC_FREE(n); continue; } } @@ -1470,7 +1474,7 @@ void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset) bool SearchDir(struct smb_Dir *dirp, const char *name, long *poffset) { int i; - const char *entry; + char *entry = NULL; connection_struct *conn = dirp->conn; /* Search back in the name cache. */ @@ -1499,8 +1503,10 @@ bool SearchDir(struct smb_Dir *dirp, const char *name, long *poffset) *poffset = START_OF_DIRECTORY_OFFSET; while ((entry = ReadDirName(dirp, poffset, NULL))) { if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) { + TALLOC_FREE(entry); return True; } + TALLOC_FREE(entry); } return False; } @@ -1514,7 +1520,7 @@ NTSTATUS can_delete_directory(struct connection_struct *conn, { NTSTATUS status = NT_STATUS_OK; long dirpos = 0; - const char *dname; + char *dname = NULL; SMB_STRUCT_STAT st; struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, dirname, NULL, 0); @@ -1527,11 +1533,13 @@ NTSTATUS can_delete_directory(struct connection_struct *conn, /* Quick check for "." and ".." */ if (dname[0] == '.') { if (!dname[1] || (dname[1] == '.' && !dname[2])) { + TALLOC_FREE(dname); continue; } } if (!is_visible_file(conn, dirname, dname, &st, True)) { + TALLOC_FREE(dname); continue; } @@ -1540,6 +1548,7 @@ NTSTATUS can_delete_directory(struct connection_struct *conn, status = NT_STATUS_DIRECTORY_NOT_EMPTY; break; } + TALLOC_FREE(dname); TALLOC_FREE(dir_hnd); return status; diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 2538bc1ea6..ee97388da2 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -829,7 +829,7 @@ static int get_real_filename_full_scan(connection_struct *conn, TALLOC_CTX *mem_ctx, char **found_name) { struct smb_Dir *cur_dir; - const char *dname; + char *dname = NULL; char *unmangled_name = NULL; long curpos; @@ -885,6 +885,7 @@ static int get_real_filename_full_scan(connection_struct *conn, /* Is it dot or dot dot. */ if (ISDOT(dname) || ISDOTDOT(dname)) { + TALLOC_FREE(dname); continue; } @@ -907,10 +908,13 @@ static int get_real_filename_full_scan(connection_struct *conn, TALLOC_FREE(cur_dir); if (!*found_name) { errno = ENOMEM; + TALLOC_FREE(dname); return -1; } + TALLOC_FREE(dname); return 0; } + TALLOC_FREE(dname); } TALLOC_FREE(unmangled_name); diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 74e46527bc..4a338fa590 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -1548,6 +1548,7 @@ static int count_dfs_links(TALLOC_CTX *ctx, int snum) NULL)) { cnt++; } + TALLOC_FREE(dname); } SMB_VFS_CLOSEDIR(conn,dirp); @@ -1647,6 +1648,7 @@ static int form_junctions(TALLOC_CTX *ctx, if (cnt >= jn_remain) { DEBUG(2, ("form_junctions: ran out of MSDFS " "junction slots")); + TALLOC_FREE(dname); goto out; } if (is_msdfs_link_internal(ctx, @@ -1664,6 +1666,7 @@ static int form_junctions(TALLOC_CTX *ctx, dname); if (!jucn[cnt].service_name || !jucn[cnt].volume_name) { + TALLOC_FREE(dname); goto out; } jucn[cnt].comment = ""; @@ -1671,6 +1674,7 @@ static int form_junctions(TALLOC_CTX *ctx, } TALLOC_FREE(link_target); } + TALLOC_FREE(dname); } out: diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index bdc71c2404..a3280cb9d4 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2577,7 +2577,7 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, } else { struct smb_Dir *dir_hnd = NULL; long offset = 0; - const char *dname; + char *dname = NULL; if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) { status = NT_STATUS_OBJECT_NAME_INVALID; @@ -2619,18 +2619,21 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, if (!is_visible_file(conn, fname_dir, dname, &smb_fname->st, true)) { TALLOC_FREE(frame); + TALLOC_FREE(dname); continue; } /* Quick check for "." and ".." */ if (ISDOT(dname) || ISDOTDOT(dname)) { TALLOC_FREE(frame); + TALLOC_FREE(dname); continue; } if(!mask_match(dname, fname_mask, conn->case_sensitive)) { TALLOC_FREE(frame); + TALLOC_FREE(dname); continue; } @@ -2643,6 +2646,7 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, TALLOC_FREE(dir_hnd); status = NT_STATUS_NO_MEMORY; TALLOC_FREE(frame); + TALLOC_FREE(dname); goto out; } @@ -2650,12 +2654,14 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(dir_hnd); TALLOC_FREE(frame); + TALLOC_FREE(dname); goto out; } status = do_unlink(conn, req, smb_fname, dirtype); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(frame); + TALLOC_FREE(dname); continue; } @@ -2664,6 +2670,7 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, smb_fname->base_name)); TALLOC_FREE(frame); + TALLOC_FREE(dname); } TALLOC_FREE(dir_hnd); } @@ -5287,7 +5294,7 @@ static bool recursive_rmdir(TALLOC_CTX *ctx, connection_struct *conn, struct smb_filename *smb_dname) { - const char *dname = NULL; + char *dname = NULL; bool ret = True; long offset = 0; SMB_STRUCT_STAT st; @@ -5306,11 +5313,13 @@ static bool recursive_rmdir(TALLOC_CTX *ctx, NTSTATUS status; if (ISDOT(dname) || ISDOTDOT(dname)) { + TALLOC_FREE(dname); continue; } if (!is_visible_file(conn, smb_dname->base_name, dname, &st, false)) { + TALLOC_FREE(dname); continue; } @@ -5353,6 +5362,7 @@ static bool recursive_rmdir(TALLOC_CTX *ctx, err_break: TALLOC_FREE(smb_dname_full); TALLOC_FREE(fullname); + TALLOC_FREE(dname); if (do_break) { ret = false; break; @@ -5406,7 +5416,7 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx, * retry. If we fail to delete any of them (and we *don't* * do a recursive delete) then fail the rmdir. */ - const char *dname; + char *dname = NULL; long dirpos = 0; struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, smb_dname->base_name, NULL, @@ -5418,16 +5428,22 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx, } while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) { - if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) + if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) { + TALLOC_FREE(dname); continue; + } if (!is_visible_file(conn, smb_dname->base_name, dname, - &st, false)) + &st, false)) { + TALLOC_FREE(dname); continue; + } if(!IS_VETO_PATH(conn, dname)) { TALLOC_FREE(dir_hnd); + TALLOC_FREE(dname); errno = ENOTEMPTY; goto err; } + TALLOC_FREE(dname); } /* We only have veto files/directories. @@ -5448,10 +5464,12 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx, NTSTATUS status; if (ISDOT(dname) || ISDOTDOT(dname)) { + TALLOC_FREE(dname); continue; } if (!is_visible_file(conn, smb_dname->base_name, dname, &st, false)) { + TALLOC_FREE(dname); continue; } @@ -5496,6 +5514,7 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx, err_break: TALLOC_FREE(fullname); TALLOC_FREE(smb_dname_full); + TALLOC_FREE(dname); if (do_break) break; } @@ -6132,7 +6151,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, int count=0; NTSTATUS status = NT_STATUS_OK; struct smb_Dir *dir_hnd = NULL; - const char *dname; + char *dname = NULL; long offset = 0; int create_options = 0; bool posix_pathnames = lp_posix_pathnames(); @@ -6320,16 +6339,19 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, if (attrs & aDIR) { sysdir_entry = True; } else { + TALLOC_FREE(dname); continue; } } if (!is_visible_file(conn, fname_src_dir, dname, &smb_fname_src->st, false)) { + TALLOC_FREE(dname); continue; } if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) { + TALLOC_FREE(dname); continue; } @@ -6353,6 +6375,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, &destname)) { DEBUG(6, ("resolve_wildcards %s %s failed\n", smb_fname_src->base_name, destname)); + TALLOC_FREE(dname); continue; } if (!destname) { @@ -6428,7 +6451,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, DEBUG(3,("rename_internals: doing rename on %s -> " "%s\n", smb_fname_str_dbg(smb_fname_src), smb_fname_str_dbg(smb_fname_src))); - + TALLOC_FREE(dname); } TALLOC_FREE(dir_hnd); @@ -6437,6 +6460,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, } out: + TALLOC_FREE(dname); TALLOC_FREE(fname_src_dir); TALLOC_FREE(fname_src_mask); return status; @@ -6901,7 +6925,7 @@ void reply_copy(struct smb_request *req) } } else { struct smb_Dir *dir_hnd = NULL; - const char *dname = NULL; + char *dname = NULL; long offset = 0; /* @@ -6946,16 +6970,19 @@ void reply_copy(struct smb_request *req) char *destname = NULL; if (ISDOT(dname) || ISDOTDOT(dname)) { + TALLOC_FREE(dname); continue; } if (!is_visible_file(conn, fname_src_dir, dname, &smb_fname_src->st, false)) { + TALLOC_FREE(dname); continue; } if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) { + TALLOC_FREE(dname); continue; } @@ -6969,6 +6996,7 @@ void reply_copy(struct smb_request *req) if (!smb_fname_src->base_name) { TALLOC_FREE(dir_hnd); + TALLOC_FREE(dname); reply_nterror(req, NT_STATUS_NO_MEMORY); goto out; } @@ -6976,10 +7004,12 @@ void reply_copy(struct smb_request *req) if (!resolve_wildcards(ctx, smb_fname_src->base_name, smb_fname_dst->base_name, &destname)) { + TALLOC_FREE(dname); continue; } if (!destname) { TALLOC_FREE(dir_hnd); + TALLOC_FREE(dname); reply_nterror(req, NT_STATUS_NO_MEMORY); goto out; } @@ -6990,6 +7020,7 @@ void reply_copy(struct smb_request *req) status = check_name(conn, smb_fname_src->base_name); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(dir_hnd); + TALLOC_FREE(dname); reply_nterror(req, status); goto out; } @@ -6997,6 +7028,7 @@ void reply_copy(struct smb_request *req) status = check_name(conn, smb_fname_dst->base_name); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(dir_hnd); + TALLOC_FREE(dname); reply_nterror(req, status); goto out; } @@ -7011,6 +7043,8 @@ void reply_copy(struct smb_request *req) if (NT_STATUS_IS_OK(status)) { count++; } + + TALLOC_FREE(dname); } TALLOC_FREE(dir_hnd); } diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 5425c55198..42ff8b19cd 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -662,7 +662,8 @@ SMB_OFF_T vfs_transfer_file(files_struct *in, files_struct *out, SMB_OFF_T n) char *vfs_readdirname(connection_struct *conn, void *p, SMB_STRUCT_STAT *sbuf) { SMB_STRUCT_DIRENT *ptr= NULL; - char *dname; + char *dname = NULL; + NTSTATUS result; if (!p) return(NULL); @@ -671,7 +672,16 @@ char *vfs_readdirname(connection_struct *conn, void *p, SMB_STRUCT_STAT *sbuf) if (!ptr) return(NULL); - dname = ptr->d_name; + dname = talloc_strdup(talloc_tos(), ptr->d_name); + if (dname == NULL) { + errno = ENOMEM; + return NULL; + } + result = SMB_VFS_TRANSLATE_NAME(conn, &dname); + if (!NT_STATUS_IS_OK(result)) { + TALLOC_FREE(dname); + return NULL; + } #ifdef NEXT2 if (telldir(p) < 0) @@ -1495,6 +1505,13 @@ void smb_vfs_call_strict_unlock(struct vfs_handle_struct *handle, handle->fns->strict_unlock(handle, fsp, plock); } +NTSTATUS smb_vfs_call_translate_name(struct vfs_handle_struct *handle, + char **mapped_name) +{ + VFS_FIND(translate_name); + return handle->fns->translate_name(handle, mapped_name); +} + NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle, struct files_struct *fsp, uint32 security_info, |