summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2004-12-17 04:51:23 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:07:28 -0500
commit3b8e83a8c8f32ca658841f1fae344399a48d66a4 (patch)
treefebc6b07ebea32366b3ecc8f7b4862f7294e6798
parent50005129ab0a5c5f2422460e6d7c19616e5e1124 (diff)
downloadsamba-3b8e83a8c8f32ca658841f1fae344399a48d66a4.tar.gz
samba-3b8e83a8c8f32ca658841f1fae344399a48d66a4.tar.bz2
samba-3b8e83a8c8f32ca658841f1fae344399a48d66a4.zip
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)
-rw-r--r--source4/include/smb_interfaces.h3
-rw-r--r--source4/libcli/raw/raweas.c4
-rw-r--r--source4/libcli/raw/rawsetfileinfo.c4
-rw-r--r--source4/ntvfs/posix/pvfs_mkdir.c18
-rw-r--r--source4/ntvfs/posix/pvfs_open.c21
-rw-r--r--source4/ntvfs/posix/pvfs_setfileinfo.c54
-rw-r--r--source4/smb_server/trans2.c18
-rw-r--r--source4/torture/gentest.c8
-rw-r--r--source4/torture/raw/eas.c42
-rw-r--r--source4/torture/torture_util.c19
10 files changed, 101 insertions, 90 deletions
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;i<md->t2mkdir.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;i<io->ntcreatex.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;i<ealist->num_eas;i++) {
- if (StrCaseCmp(ealist->eas[i].name, ea->name.s) == 0) {
- ealist->eas[i].value = ea->value;
- goto save;
+ for (j=0;j<num_eas;j++) {
+ struct ea_struct *ea = &eas[j];
+ /* see if its already there */
+ for (i=0;i<ealist->num_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;i<ealist->num_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");