char *dest, *d;
/* the length is bounded by the length of the two strings combined */
- dest = talloc_size(mem_ctx, strlen(fname) + strlen(pattern) + 1);
+ dest = talloc_array(mem_ctx, char, strlen(fname) + strlen(pattern) + 1);
if (dest == NULL) {
return NULL;
}
while (*p2) {
codepoint_t c1, c2;
size_t c_size1, c_size2;
- c1 = next_codepoint(iconv_convenience, p1, &c_size1);
- c2 = next_codepoint(iconv_convenience, p2, &c_size2);
+ c1 = next_codepoint_convenience(iconv_convenience, p1, &c_size1);
+ c2 = next_codepoint_convenience(iconv_convenience, p2, &c_size2);
if (c2 == '?') {
- d += push_codepoint(iconv_convenience, d, c1);
+ d += push_codepoint_convenience(iconv_convenience, d, c1);
} else if (c2 == '*') {
memcpy(d, p1, strlen(p1));
d += strlen(p1);
break;
} else {
- d += push_codepoint(iconv_convenience, d, c2);
+ d += push_codepoint_convenience(iconv_convenience, d, c2);
}
p1 += c_size1;
*d = 0;
+ talloc_set_name_const(dest, dest);
+
return dest;
}
struct odb_lock *lck,
NTSTATUS status)
{
- struct pvfs_state *pvfs = ntvfs->private_data;
+ struct pvfs_state *pvfs = talloc_get_type(ntvfs->private_data,
+ struct pvfs_state);
struct timeval end_time;
if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
/* get a pvfs_filename source object */
status = pvfs_resolve_partial(pvfs, mem_ctx,
- dir_path, fname1, &name1);
+ dir_path, fname1,
+ PVFS_RESOLVE_NO_OPENDB,
+ &name1);
if (!NT_STATUS_IS_OK(status)) {
goto failed;
}
/* get a pvfs_filename dest object */
status = pvfs_resolve_partial(pvfs, mem_ctx,
- dir_path, fname2, &name2);
+ dir_path, fname2,
+ PVFS_RESOLVE_NO_OPENDB,
+ &name2);
if (NT_STATUS_IS_OK(status)) {
status = pvfs_can_delete(pvfs, req, name2, NULL);
if (!NT_STATUS_IS_OK(status)) {
static NTSTATUS pvfs_rename_mv(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req, union smb_rename *ren)
{
- struct pvfs_state *pvfs = ntvfs->private_data;
+ struct pvfs_state *pvfs = talloc_get_type(ntvfs->private_data,
+ struct pvfs_state);
NTSTATUS status;
struct pvfs_filename *name1, *name2;
struct odb_lock *lck = NULL;
}
+/*
+ rename a stream
+*/
+static NTSTATUS pvfs_rename_stream(struct ntvfs_module_context *ntvfs,
+ struct ntvfs_request *req, union smb_rename *ren,
+ struct pvfs_filename *name1)
+{
+ struct pvfs_state *pvfs = talloc_get_type(ntvfs->private_data,
+ struct pvfs_state);
+ NTSTATUS status;
+ struct odb_lock *lck = NULL;
+
+ if (name1->has_wildcard) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (ren->ntrename.in.new_name[0] != ':') {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (!name1->exists) {
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+
+ if (ren->ntrename.in.flags != RENAME_FLAG_RENAME) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ status = pvfs_can_rename(pvfs, req, name1, &lck);
+ /*
+ * on a sharing violation we need to retry when the file is closed by
+ * the other user, or after 1 second
+ * on a non granted oplock we need to retry when the file is closed by
+ * the other user, or after 30 seconds
+ */
+ if ((NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) ||
+ NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) &&
+ (req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
+ return pvfs_rename_setup_retry(pvfs->ntvfs, req, ren, lck, status);
+ }
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ status = pvfs_access_check_simple(pvfs, req, name1, SEC_FILE_WRITE_ATTRIBUTE);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ status = pvfs_stream_rename(pvfs, name1, -1,
+ ren->ntrename.in.new_name+1,
+ true);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ return NT_STATUS_OK;
+}
+
/*
rename a set of files - ntrename interface
*/
static NTSTATUS pvfs_rename_nt(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req, union smb_rename *ren)
{
- struct pvfs_state *pvfs = ntvfs->private_data;
+ struct pvfs_state *pvfs = talloc_get_type(ntvfs->private_data,
+ struct pvfs_state);
NTSTATUS status;
struct pvfs_filename *name1, *name2;
struct odb_lock *lck = NULL;
/* resolve the cifs name to a posix name */
status = pvfs_resolve_name(pvfs, req, ren->ntrename.in.old_name,
- PVFS_RESOLVE_WILDCARD, &name1);
+ PVFS_RESOLVE_WILDCARD | PVFS_RESOLVE_STREAMS, &name1);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
+ if (name1->stream_name) {
+ /* stream renames need to be handled separately */
+ return pvfs_rename_stream(ntvfs, req, ren, name1);
+ }
+
status = pvfs_resolve_name(pvfs, req, ren->ntrename.in.new_name,
PVFS_RESOLVE_WILDCARD, &name2);
if (!NT_STATUS_IS_OK(status)) {
NTSTATUS pvfs_rename(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req, union smb_rename *ren)
{
+ struct pvfs_state *pvfs = talloc_get_type(ntvfs->private_data,
+ struct pvfs_state);
+ struct pvfs_file *f;
+
switch (ren->generic.level) {
case RAW_RENAME_RENAME:
return pvfs_rename_mv(ntvfs, req, ren);
case RAW_RENAME_NTRENAME:
return pvfs_rename_nt(ntvfs, req, ren);
+ case RAW_RENAME_NTTRANS:
+ f = pvfs_find_fd(pvfs, req, ren->nttrans.in.file.ntvfs);
+ if (!f) {
+ return NT_STATUS_INVALID_HANDLE;
+ }
+
+ /* wk23 ignores the request */
+ return NT_STATUS_OK;
+
default:
break;
}