X-Git-Url: http://git.samba.org/samba.git/?a=blobdiff_plain;f=source4%2Fntvfs%2Fposix%2Fpvfs_rename.c;h=3b9842db7f22a54d67779447eaae27700237b021;hb=7c1fdfe4b5f7dbe215a04f2c5ecb82a410ac10f8;hp=3203f7fa86de1d164b4757cc2c63dbc98ad0c5b0;hpb=ddc10d4d37984246a6547e34a32d629c689c40d1;p=gd%2Fsamba-autobuild%2F.git diff --git a/source4/ntvfs/posix/pvfs_rename.c b/source4/ntvfs/posix/pvfs_rename.c index 3203f7fa86d..3b9842db7f2 100644 --- a/source4/ntvfs/posix/pvfs_rename.c +++ b/source4/ntvfs/posix/pvfs_rename.c @@ -7,7 +7,7 @@ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -16,12 +16,73 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + along with this program. If not, see . */ #include "includes.h" #include "vfs_posix.h" +#include "librpc/gen_ndr/security.h" +#include "param/param.h" + + +/* + do a file rename, and send any notify triggers +*/ +NTSTATUS pvfs_do_rename(struct pvfs_state *pvfs, const struct pvfs_filename *name1, + const char *name2) +{ + const char *r1, *r2; + uint32_t mask; + + if (rename(name1->full_name, name2) == -1) { + return pvfs_map_errno(pvfs, errno); + } + + if (name1->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) { + mask = FILE_NOTIFY_CHANGE_DIR_NAME; + } else { + mask = FILE_NOTIFY_CHANGE_FILE_NAME; + } + /* + renames to the same directory cause a OLD_NAME->NEW_NAME notify. + renames to a different directory are considered a remove/add + */ + r1 = strrchr_m(name1->full_name, '/'); + r2 = strrchr_m(name2, '/'); + + if ((r1-name1->full_name) != (r2-name2) || + strncmp(name1->full_name, name2, r1-name1->full_name) != 0) { + notify_trigger(pvfs->notify_context, + NOTIFY_ACTION_REMOVED, + mask, + name1->full_name); + notify_trigger(pvfs->notify_context, + NOTIFY_ACTION_ADDED, + mask, + name2); + } else { + notify_trigger(pvfs->notify_context, + NOTIFY_ACTION_OLD_NAME, + mask, + name1->full_name); + notify_trigger(pvfs->notify_context, + NOTIFY_ACTION_NEW_NAME, + mask, + name2); + } + + /* this is a strange one. w2k3 gives an additional event for CHANGE_ATTRIBUTES + and CHANGE_CREATION on the new file when renaming files, but not + directories */ + if ((name1->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) == 0) { + notify_trigger(pvfs->notify_context, + NOTIFY_ACTION_MODIFIED, + FILE_NOTIFY_CHANGE_ATTRIBUTES|FILE_NOTIFY_CHANGE_CREATION, + name2); + } + + return NT_STATUS_OK; +} /* @@ -47,16 +108,16 @@ static const char *pvfs_resolve_wildcard_component(TALLOC_CTX *mem_ctx, while (*p2) { codepoint_t c1, c2; size_t c_size1, c_size2; - c1 = next_codepoint(p1, &c_size1); - c2 = next_codepoint(p2, &c_size2); + c1 = next_codepoint(lp_iconv_convenience(global_loadparm), p1, &c_size1); + c2 = next_codepoint(lp_iconv_convenience(global_loadparm), p2, &c_size2); if (c2 == '?') { - d += push_codepoint(d, c1); + d += push_codepoint(lp_iconv_convenience(global_loadparm), d, c1); } else if (c2 == '*') { memcpy(d, p1, strlen(p1)); d += strlen(p1); break; } else { - d += push_codepoint(d, c2); + d += push_codepoint(lp_iconv_convenience(global_loadparm), d, c2); } p1 += c_size1; @@ -121,7 +182,7 @@ static const char *pvfs_resolve_wildcard(TALLOC_CTX *mem_ctx, rename one file from a wildcard set */ static NTSTATUS pvfs_rename_one(struct pvfs_state *pvfs, - struct smbsrv_request *req, + struct ntvfs_request *req, const char *dir_path, const char *fname1, const char *fname2, @@ -130,6 +191,7 @@ static NTSTATUS pvfs_rename_one(struct pvfs_state *pvfs, struct pvfs_filename *name1, *name2; TALLOC_CTX *mem_ctx = talloc_new(req); NTSTATUS status; + struct odb_lock *lck, *lck2; /* resolve the wildcard pattern for this name */ fname2 = pvfs_resolve_wildcard(mem_ctx, fname1, fname2); @@ -150,7 +212,7 @@ static NTSTATUS pvfs_rename_one(struct pvfs_state *pvfs, goto failed; } - status = pvfs_can_rename(pvfs, name1); + status = pvfs_can_rename(pvfs, req, name1, &lck); if (!NT_STATUS_IS_OK(status)) { goto failed; } @@ -159,7 +221,7 @@ static NTSTATUS pvfs_rename_one(struct pvfs_state *pvfs, status = pvfs_resolve_partial(pvfs, mem_ctx, dir_path, fname2, &name2); if (NT_STATUS_IS_OK(status)) { - status = pvfs_can_delete(pvfs, req, name2); + status = pvfs_can_delete(pvfs, req, name2, &lck2); if (!NT_STATUS_IS_OK(status)) { goto failed; } @@ -172,9 +234,10 @@ static NTSTATUS pvfs_rename_one(struct pvfs_state *pvfs, return NT_STATUS_NO_MEMORY; } - if (rename(name1->full_name, fname2) == -1) { - talloc_free(mem_ctx); - return pvfs_map_errno(pvfs, errno); + status = pvfs_do_rename(pvfs, name1, fname2); + + if (NT_STATUS_IS_OK(status)) { + status = odb_rename(lck, fname2); } failed: @@ -187,14 +250,14 @@ failed: rename a set of files with wildcards */ static NTSTATUS pvfs_rename_wildcard(struct pvfs_state *pvfs, - struct smbsrv_request *req, + struct ntvfs_request *req, union smb_rename *ren, struct pvfs_filename *name1, struct pvfs_filename *name2) { struct pvfs_dir *dir; NTSTATUS status; - uint_t ofs = 0; + off_t ofs = 0; const char *fname, *fname2, *dir_path; uint16_t attrib = ren->rename.in.attrib; int total_renamed = 0; @@ -241,11 +304,12 @@ static NTSTATUS pvfs_rename_wildcard(struct pvfs_state *pvfs, rename a set of files - SMBmv interface */ static NTSTATUS pvfs_rename_mv(struct ntvfs_module_context *ntvfs, - struct smbsrv_request *req, union smb_rename *ren) + struct ntvfs_request *req, union smb_rename *ren) { struct pvfs_state *pvfs = ntvfs->private_data; NTSTATUS status; struct pvfs_filename *name1, *name2; + struct odb_lock *lck; /* resolve the cifs name to a posix name */ status = pvfs_resolve_name(pvfs, req, ren->rename.in.pattern1, @@ -281,18 +345,19 @@ static NTSTATUS pvfs_rename_mv(struct ntvfs_module_context *ntvfs, return status; } - status = pvfs_access_check_create(pvfs, req, name2); + status = pvfs_access_check_parent(pvfs, req, name2, SEC_DIR_ADD_FILE); if (!NT_STATUS_IS_OK(status)) { return status; } - status = pvfs_can_rename(pvfs, name1); + status = pvfs_can_rename(pvfs, req, name1, &lck); if (!NT_STATUS_IS_OK(status)) { return status; } - if (rename(name1->full_name, name2->full_name) == -1) { - return pvfs_map_errno(pvfs, errno); + status = pvfs_do_rename(pvfs, name1, name2->full_name); + if (NT_STATUS_IS_OK(status)) { + status = odb_rename(lck, name2->full_name); } return NT_STATUS_OK; @@ -303,11 +368,12 @@ static NTSTATUS pvfs_rename_mv(struct ntvfs_module_context *ntvfs, rename a set of files - ntrename interface */ static NTSTATUS pvfs_rename_nt(struct ntvfs_module_context *ntvfs, - struct smbsrv_request *req, union smb_rename *ren) + struct ntvfs_request *req, union smb_rename *ren) { struct pvfs_state *pvfs = ntvfs->private_data; NTSTATUS status; struct pvfs_filename *name1, *name2; + struct odb_lock *lck; switch (ren->ntrename.in.flags) { case RENAME_FLAG_RENAME: @@ -353,37 +419,30 @@ static NTSTATUS pvfs_rename_nt(struct ntvfs_module_context *ntvfs, return status; } - status = pvfs_can_rename(pvfs, name1); + status = pvfs_can_rename(pvfs, req, name1, &lck); if (!NT_STATUS_IS_OK(status)) { return status; } switch (ren->ntrename.in.flags) { case RENAME_FLAG_RENAME: - status = pvfs_access_check_create(pvfs, req, name2); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - if (rename(name1->full_name, name2->full_name) == -1) { - return pvfs_map_errno(pvfs, errno); - } + status = pvfs_access_check_parent(pvfs, req, name2, SEC_DIR_ADD_FILE); + NT_STATUS_NOT_OK_RETURN(status); + status = pvfs_do_rename(pvfs, name1, name2->full_name); + NT_STATUS_NOT_OK_RETURN(status); break; case RENAME_FLAG_HARD_LINK: - status = pvfs_access_check_create(pvfs, req, name2); - if (!NT_STATUS_IS_OK(status)) { - return status; - } + status = pvfs_access_check_parent(pvfs, req, name2, SEC_DIR_ADD_FILE); + NT_STATUS_NOT_OK_RETURN(status); if (link(name1->full_name, name2->full_name) == -1) { return pvfs_map_errno(pvfs, errno); } break; case RENAME_FLAG_COPY: - status = pvfs_access_check_create(pvfs, req, name2); - if (!NT_STATUS_IS_OK(status)) { - return status; - } + status = pvfs_access_check_parent(pvfs, req, name2, SEC_DIR_ADD_FILE); + NT_STATUS_NOT_OK_RETURN(status); return pvfs_copy_file(pvfs, name1, name2); case RENAME_FLAG_MOVE_CLUSTER_INFORMATION: @@ -401,7 +460,7 @@ static NTSTATUS pvfs_rename_nt(struct ntvfs_module_context *ntvfs, rename a set of files - ntrename interface */ NTSTATUS pvfs_rename(struct ntvfs_module_context *ntvfs, - struct smbsrv_request *req, union smb_rename *ren) + struct ntvfs_request *req, union smb_rename *ren) { switch (ren->generic.level) { case RAW_RENAME_RENAME: