From 3b8e83a8c8f32ca658841f1fae344399a48d66a4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 17 Dec 2004 04:51:23 +0000 Subject: r4243: a sniff from kukks showed that the ea_set interface in trans2 setfileinfo allows for multiple EAs to be set at once. This fixes all the ea code to allow for that. (This used to be commit b26828bef5d55e5eef0e34a164e76292df45e207) --- source4/include/smb_interfaces.h | 3 +- source4/libcli/raw/raweas.c | 4 +-- source4/libcli/raw/rawsetfileinfo.c | 4 +-- source4/ntvfs/posix/pvfs_mkdir.c | 18 +++++++----- source4/ntvfs/posix/pvfs_open.c | 21 +++++++------ source4/ntvfs/posix/pvfs_setfileinfo.c | 54 ++++++++++++++++++++++------------ source4/smb_server/trans2.c | 18 ++---------- source4/torture/gentest.c | 8 +++-- source4/torture/raw/eas.c | 42 +++++++++++++------------- source4/torture/torture_util.c | 19 +++++------- 10 files changed, 101 insertions(+), 90 deletions(-) (limited to 'source4') diff --git a/source4/include/smb_interfaces.h b/source4/include/smb_interfaces.h index 4ba8ea3442..d5e43633db 100644 --- a/source4/include/smb_interfaces.h +++ b/source4/include/smb_interfaces.h @@ -764,7 +764,8 @@ union smb_setfileinfo { enum smb_setfileinfo_level level; union setfileinfo_file file; struct { - struct ea_struct ea; + uint_t num_eas; + struct ea_struct *eas; } in; } ea_set; diff --git a/source4/libcli/raw/raweas.c b/source4/libcli/raw/raweas.c index 027705b381..14d4557995 100644 --- a/source4/libcli/raw/raweas.c +++ b/source4/libcli/raw/raweas.c @@ -147,8 +147,8 @@ uint_t ea_pull_struct(const DATA_BLOB *blob, pull a ea_list from a buffer */ NTSTATUS ea_pull_list(const DATA_BLOB *blob, - TALLOC_CTX *mem_ctx, - uint_t *num_eas, struct ea_struct **eas) + TALLOC_CTX *mem_ctx, + uint_t *num_eas, struct ea_struct **eas) { int n; uint32_t ea_size, ofs; diff --git a/source4/libcli/raw/rawsetfileinfo.c b/source4/libcli/raw/rawsetfileinfo.c index 76756971ae..9576bdf356 100644 --- a/source4/libcli/raw/rawsetfileinfo.c +++ b/source4/libcli/raw/rawsetfileinfo.c @@ -56,8 +56,8 @@ static BOOL smb_raw_setinfo_backend(struct smbcli_tree *tree, return True; case RAW_SFILEINFO_EA_SET: - NEED_BLOB(ea_list_size(1, &parms->ea_set.in.ea)); - ea_put_list(blob->data, 1, &parms->ea_set.in.ea); + NEED_BLOB(ea_list_size(parms->ea_set.in.num_eas, parms->ea_set.in.eas)); + ea_put_list(blob->data, parms->ea_set.in.num_eas, parms->ea_set.in.eas); return True; case RAW_SFILEINFO_BASIC_INFO: diff --git a/source4/ntvfs/posix/pvfs_mkdir.c b/source4/ntvfs/posix/pvfs_mkdir.c index b43e67faed..549f4b9780 100644 --- a/source4/ntvfs/posix/pvfs_mkdir.c +++ b/source4/ntvfs/posix/pvfs_mkdir.c @@ -32,7 +32,6 @@ static NTSTATUS pvfs_t2mkdir(struct pvfs_state *pvfs, NTSTATUS status; struct pvfs_filename *name; mode_t mode; - int i; /* resolve the cifs name to a posix name */ status = pvfs_resolve_name(pvfs, req, md->t2mkdir.in.path, 0, &name); @@ -60,12 +59,12 @@ static NTSTATUS pvfs_t2mkdir(struct pvfs_state *pvfs, } /* setup any EAs that were asked for */ - for (i=0;it2mkdir.in.num_eas;i++) { - status = pvfs_setfileinfo_ea_set(pvfs, name, -1, &md->t2mkdir.in.eas[i]); - if (!NT_STATUS_IS_OK(status)) { - rmdir(name->full_name); - return status; - } + status = pvfs_setfileinfo_ea_set(pvfs, name, -1, + md->t2mkdir.in.num_eas, + md->t2mkdir.in.eas); + if (!NT_STATUS_IS_OK(status)) { + rmdir(name->full_name); + return status; } return NT_STATUS_OK; @@ -129,6 +128,11 @@ NTSTATUS pvfs_rmdir(struct ntvfs_module_context *ntvfs, return NT_STATUS_OBJECT_NAME_NOT_FOUND; } + status = pvfs_xattr_unlink_hook(pvfs, name->full_name); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + if (rmdir(name->full_name) == -1) { return pvfs_map_errno(pvfs, errno); } diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index e31d79b9e0..bd96b935ad 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -70,6 +70,11 @@ static int pvfs_dir_handle_destructor(void *p) struct pvfs_file_handle *h = p; if (h->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) { + NTSTATUS status = pvfs_xattr_unlink_hook(h->pvfs, h->name->full_name); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Warning: xattr rmdir hook failed for '%s' - %s\n", + h->name->full_name, nt_errstr(status))); + } if (rmdir(h->name->full_name) != 0) { DEBUG(0,("pvfs_close: failed to rmdir '%s' - %s\n", h->name->full_name, strerror(errno))); @@ -459,15 +464,13 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, /* setup any EAs that were asked for */ if (io->ntcreatex.in.ea_list) { - int i; - for (i=0;intcreatex.in.ea_list->num_eas;i++) { - status = pvfs_setfileinfo_ea_set(pvfs, name, fd, - &io->ntcreatex.in.ea_list->eas[i]); - if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->idtree_fnum, fnum); - close(fd); - return status; - } + status = pvfs_setfileinfo_ea_set(pvfs, name, fd, + io->ntcreatex.in.ea_list->num_eas, + io->ntcreatex.in.ea_list->eas); + if (!NT_STATUS_IS_OK(status)) { + idr_remove(pvfs->idtree_fnum, fnum); + close(fd); + return status; } } diff --git a/source4/ntvfs/posix/pvfs_setfileinfo.c b/source4/ntvfs/posix/pvfs_setfileinfo.c index c43ef5c40a..2a06def2b4 100644 --- a/source4/ntvfs/posix/pvfs_setfileinfo.c +++ b/source4/ntvfs/posix/pvfs_setfileinfo.c @@ -115,40 +115,53 @@ static NTSTATUS pvfs_setfileinfo_rename(struct pvfs_state *pvfs, */ NTSTATUS pvfs_setfileinfo_ea_set(struct pvfs_state *pvfs, struct pvfs_filename *name, - int fd, struct ea_struct *ea) + int fd, uint16_t num_eas, + struct ea_struct *eas) { - struct xattr_DosEAs *ealist = talloc_p(pvfs, struct xattr_DosEAs); - int i; + struct xattr_DosEAs *ealist; + int i, j; NTSTATUS status; + if (num_eas == 0) { + return NT_STATUS_OK; + } + if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) { return NT_STATUS_NOT_SUPPORTED; } + ealist = talloc_p(name, struct xattr_DosEAs); + /* load the current list */ status = pvfs_doseas_load(pvfs, name, fd, ealist); if (!NT_STATUS_IS_OK(status)) { return status; } - /* see if its already there */ - for (i=0;inum_eas;i++) { - if (StrCaseCmp(ealist->eas[i].name, ea->name.s) == 0) { - ealist->eas[i].value = ea->value; - goto save; + for (j=0;jnum_eas;i++) { + if (StrCaseCmp(ealist->eas[i].name, ea->name.s) == 0) { + ealist->eas[i].value = ea->value; + break; + } } - } - /* add it */ - ealist->eas = talloc_realloc_p(ealist, ealist->eas, struct xattr_EA, ealist->num_eas+1); - if (ealist->eas == NULL) { - return NT_STATUS_NO_MEMORY; + if (i==ealist->num_eas) { + /* add it */ + ealist->eas = talloc_realloc_p(ealist, ealist->eas, + struct xattr_EA, + ealist->num_eas+1); + if (ealist->eas == NULL) { + return NT_STATUS_NO_MEMORY; + } + ealist->eas[i].name = ea->name.s; + ealist->eas[i].value = ea->value; + ealist->num_eas++; + } } - ealist->eas[i].name = ea->name.s; - ealist->eas[i].value = ea->value; - ealist->num_eas++; -save: /* pull out any null EAs */ for (i=0;inum_eas;i++) { if (ealist->eas[i].value.length == 0) { @@ -233,7 +246,8 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs, case RAW_SFILEINFO_EA_SET: return pvfs_setfileinfo_ea_set(pvfs, h->name, h->fd, - &info->ea_set.in.ea); + info->ea_set.in.num_eas, + info->ea_set.in.eas); case RAW_SFILEINFO_BASIC_INFO: case RAW_SFILEINFO_BASIC_INFORMATION: @@ -419,7 +433,9 @@ NTSTATUS pvfs_setpathinfo(struct ntvfs_module_context *ntvfs, break; case RAW_SFILEINFO_EA_SET: - return pvfs_setfileinfo_ea_set(pvfs, name, -1, &info->ea_set.in.ea); + return pvfs_setfileinfo_ea_set(pvfs, name, -1, + info->ea_set.in.num_eas, + info->ea_set.in.eas); case RAW_SFILEINFO_BASIC_INFO: case RAW_SFILEINFO_BASIC_INFORMATION: diff --git a/source4/smb_server/trans2.c b/source4/smb_server/trans2.c index a8cad915f9..3ca9bafcfa 100644 --- a/source4/smb_server/trans2.c +++ b/source4/smb_server/trans2.c @@ -827,21 +827,9 @@ static NTSTATUS trans2_parse_sfileinfo(struct smbsrv_request *req, return NT_STATUS_OK; case RAW_SFILEINFO_EA_SET: - CHECK_MIN_BLOB_SIZE(blob, 4); - len = IVAL(blob->data, 0); - if (len > blob->length || len < 4) { - return NT_STATUS_INFO_LENGTH_MISMATCH; - } - { - DATA_BLOB blob2; - blob2.data = blob->data+4; - blob2.length = len-4; - len = ea_pull_struct(&blob2, req, &st->ea_set.in.ea); - } - if (len == 0) { - return NT_STATUS_INVALID_PARAMETER; - } - return NT_STATUS_OK; + return ea_pull_list(blob, req, + &st->ea_set.in.num_eas, + &st->ea_set.in.eas); case SMB_SFILEINFO_BASIC_INFO: case SMB_SFILEINFO_BASIC_INFORMATION: diff --git a/source4/torture/gentest.c b/source4/torture/gentest.c index 6c2f9d37fa..01b4022d32 100644 --- a/source4/torture/gentest.c +++ b/source4/torture/gentest.c @@ -1685,8 +1685,12 @@ static void gen_setfileinfo(int instance, union smb_setfileinfo *info) info->standard.in.access_time = gen_timet(); info->standard.in.write_time = gen_timet(); break; - case RAW_SFILEINFO_EA_SET: - info->ea_set.in.ea = gen_ea_struct(); + case RAW_SFILEINFO_EA_SET: { + static struct ea_struct ea; + info->ea_set.in.num_eas = 1; + info->ea_set.in.eas = &ea; + info->ea_set.in.eas[0] = gen_ea_struct(); + } break; case RAW_SFILEINFO_BASIC_INFO: case RAW_SFILEINFO_BASIC_INFORMATION: diff --git a/source4/torture/raw/eas.c b/source4/torture/raw/eas.c index 00c2fac74a..572a551d17 100644 --- a/source4/torture/raw/eas.c +++ b/source4/torture/raw/eas.c @@ -80,30 +80,28 @@ static BOOL test_eas(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) ret &= check_ea(cli, fname, "EAONE", NULL); - printf("Adding first EA\n"); + printf("Adding first two EAs\n"); setfile.generic.level = RAW_SFILEINFO_EA_SET; setfile.generic.file.fnum = fnum; - setfile.ea_set.in.ea.flags = 0; - setfile.ea_set.in.ea.name.s = "EAONE"; - setfile.ea_set.in.ea.value = data_blob_string_const("VALUE1"); + setfile.ea_set.in.num_eas = 2; + setfile.ea_set.in.eas = talloc_array_p(mem_ctx, struct ea_struct, 2); + setfile.ea_set.in.eas[0].flags = 0; + setfile.ea_set.in.eas[0].name.s = "EAONE"; + setfile.ea_set.in.eas[0].value = data_blob_string_const("VALUE1"); + setfile.ea_set.in.eas[1].flags = 0; + setfile.ea_set.in.eas[1].name.s = "SECONDEA"; + setfile.ea_set.in.eas[1].value = data_blob_string_const("ValueTwo"); status = smb_raw_setfileinfo(cli->tree, &setfile); CHECK_STATUS(status, NT_STATUS_OK); - ret &= check_ea(cli, fname, "EAONE", "VALUE1"); - - setfile.ea_set.in.ea.name.s = "SECONDEA"; - setfile.ea_set.in.ea.value = data_blob_string_const("ValueTwo"); - - printf("Adding second EA\n"); - status = smb_raw_setfileinfo(cli->tree, &setfile); - CHECK_STATUS(status, NT_STATUS_OK); - ret &= check_ea(cli, fname, "EAONE", "VALUE1"); ret &= check_ea(cli, fname, "SECONDEA", "ValueTwo"); printf("Modifying 2nd EA\n"); - setfile.ea_set.in.ea.value = data_blob_string_const(" Changed Value"); + setfile.ea_set.in.num_eas = 1; + setfile.ea_set.in.eas[0].name.s = "SECONDEA"; + setfile.ea_set.in.eas[0].value = data_blob_string_const(" Changed Value"); status = smb_raw_setfileinfo(cli->tree, &setfile); CHECK_STATUS(status, NT_STATUS_OK); @@ -111,8 +109,8 @@ static BOOL test_eas(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) ret &= check_ea(cli, fname, "SECONDEA", " Changed Value"); printf("Setting a NULL EA\n"); - setfile.ea_set.in.ea.value = data_blob(NULL, 0); - setfile.ea_set.in.ea.name.s = "NULLEA"; + setfile.ea_set.in.eas[0].value = data_blob(NULL, 0); + setfile.ea_set.in.eas[0].name.s = "NULLEA"; status = smb_raw_setfileinfo(cli->tree, &setfile); CHECK_STATUS(status, NT_STATUS_OK); @@ -121,9 +119,9 @@ static BOOL test_eas(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) ret &= check_ea(cli, fname, "NULLEA", NULL); printf("Deleting first EA\n"); - setfile.ea_set.in.ea.flags = 0; - setfile.ea_set.in.ea.name.s = "EAONE"; - setfile.ea_set.in.ea.value = data_blob(NULL, 0); + setfile.ea_set.in.eas[0].flags = 0; + setfile.ea_set.in.eas[0].name.s = "EAONE"; + setfile.ea_set.in.eas[0].value = data_blob(NULL, 0); status = smb_raw_setfileinfo(cli->tree, &setfile); CHECK_STATUS(status, NT_STATUS_OK); @@ -131,9 +129,9 @@ static BOOL test_eas(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) ret &= check_ea(cli, fname, "SECONDEA", " Changed Value"); printf("Deleting second EA\n"); - setfile.ea_set.in.ea.flags = 0; - setfile.ea_set.in.ea.name.s = "SECONDEA"; - setfile.ea_set.in.ea.value = data_blob(NULL, 0); + setfile.ea_set.in.eas[0].flags = 0; + setfile.ea_set.in.eas[0].name.s = "SECONDEA"; + setfile.ea_set.in.eas[0].value = data_blob(NULL, 0); status = smb_raw_setfileinfo(cli->tree, &setfile); CHECK_STATUS(status, NT_STATUS_OK); diff --git a/source4/torture/torture_util.c b/source4/torture/torture_util.c index 05b06c6d0e..d96a285b6f 100644 --- a/source4/torture/torture_util.c +++ b/source4/torture/torture_util.c @@ -102,17 +102,14 @@ int create_complex_file(struct smbcli_state *cli, TALLOC_CTX *mem_ctx, const cha /* setup some EAs */ setfile.generic.level = RAW_SFILEINFO_EA_SET; setfile.generic.file.fnum = fnum; - setfile.ea_set.in.ea.flags = 0; - setfile.ea_set.in.ea.name.s = "EAONE"; - setfile.ea_set.in.ea.value = data_blob_talloc(mem_ctx, "VALUE1", 6); - - status = smb_raw_setfileinfo(cli->tree, &setfile); - if (!NT_STATUS_IS_OK(status)) { - printf("Failed to setup EAs\n"); - } - - setfile.ea_set.in.ea.name.s = "SECONDEA"; - setfile.ea_set.in.ea.value = data_blob_talloc(mem_ctx, "ValueTwo", 8); + setfile.ea_set.in.num_eas = 2; + setfile.ea_set.in.eas = talloc_array_p(mem_ctx, struct ea_struct, 2); + setfile.ea_set.in.eas[0].flags = 0; + setfile.ea_set.in.eas[0].name.s = "EAONE"; + setfile.ea_set.in.eas[0].value = data_blob_talloc(mem_ctx, "VALUE1", 6); + setfile.ea_set.in.eas[1].flags = 0; + setfile.ea_set.in.eas[1].name.s = "SECONDEA"; + setfile.ea_set.in.eas[1].value = data_blob_talloc(mem_ctx, "ValueTwo", 8); status = smb_raw_setfileinfo(cli->tree, &setfile); if (!NT_STATUS_IS_OK(status)) { printf("Failed to setup EAs\n"); -- cgit