summaryrefslogtreecommitdiff
path: root/source4/ntvfs
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2011-12-01 13:40:49 +1100
committerAndrew Tridgell <tridge@samba.org>2011-12-01 05:14:49 +0100
commit3c4af39aa506a25fc6d6753dbe34e4e1c0dd0b43 (patch)
tree7ac56983f5a5d2d2de177cc21f056270d892334c /source4/ntvfs
parentd1274f7f6236b47a1c6aa1737b054ed521d31b67 (diff)
downloadsamba-3c4af39aa506a25fc6d6753dbe34e4e1c0dd0b43.tar.gz
s4-ntvfs: added allow_override check based on use of NT ACL
This disables the posix permission override if the calculated permissions did not come from a NT ACL. Autobuild-User: Andrew Tridgell <tridge@samba.org> Autobuild-Date: Thu Dec 1 05:14:49 CET 2011 on sn-devel-104
Diffstat (limited to 'source4/ntvfs')
-rw-r--r--source4/ntvfs/posix/pvfs_acl.c14
-rw-r--r--source4/ntvfs/posix/pvfs_mkdir.c12
-rw-r--r--source4/ntvfs/posix/pvfs_open.c16
-rw-r--r--source4/ntvfs/posix/pvfs_rename.c5
-rw-r--r--source4/ntvfs/posix/pvfs_resolve.c3
-rw-r--r--source4/ntvfs/posix/pvfs_setfileinfo.c4
-rw-r--r--source4/ntvfs/posix/pvfs_sys.c28
-rw-r--r--source4/ntvfs/posix/pvfs_unlink.c2
-rw-r--r--source4/ntvfs/posix/pvfs_util.c15
-rw-r--r--source4/ntvfs/posix/vfs_posix.h1
10 files changed, 59 insertions, 41 deletions
diff --git a/source4/ntvfs/posix/pvfs_acl.c b/source4/ntvfs/posix/pvfs_acl.c
index 664196ab3e4..810dcddbd30 100644
--- a/source4/ntvfs/posix/pvfs_acl.c
+++ b/source4/ntvfs/posix/pvfs_acl.c
@@ -643,6 +643,14 @@ NTSTATUS pvfs_access_check(struct pvfs_state *pvfs,
/* check the acl against the required access mask */
status = se_access_check(sd, token, *access_mask, access_mask);
talloc_free(acl);
+
+ /* if we used a NT acl, then allow access override if the
+ share allows for posix permission override
+ */
+ if (NT_STATUS_IS_OK(status)) {
+ name->allow_override = (pvfs->flags & PVFS_FLAG_PERM_OVERRIDE) != 0;
+ }
+
done:
if (pvfs->ntvfs->ctx->protocol < PROTOCOL_SMB2_02) {
/* on SMB, this bit is always granted, even if not
@@ -771,7 +779,11 @@ NTSTATUS pvfs_access_check_parent(struct pvfs_state *pvfs,
return status;
}
- return pvfs_access_check_simple(pvfs, req, parent, access_mask);
+ status = pvfs_access_check_simple(pvfs, req, parent, access_mask);
+ if (NT_STATUS_IS_OK(status) && parent->allow_override) {
+ name->allow_override = true;
+ }
+ return status;
}
diff --git a/source4/ntvfs/posix/pvfs_mkdir.c b/source4/ntvfs/posix/pvfs_mkdir.c
index 10de1d6d5c1..2cf43ab1e1d 100644
--- a/source4/ntvfs/posix/pvfs_mkdir.c
+++ b/source4/ntvfs/posix/pvfs_mkdir.c
@@ -51,7 +51,7 @@ static NTSTATUS pvfs_t2mkdir(struct pvfs_state *pvfs,
mode = pvfs_fileperms(pvfs, FILE_ATTRIBUTE_DIRECTORY);
- if (pvfs_sys_mkdir(pvfs, name->full_name, mode) == -1) {
+ if (pvfs_sys_mkdir(pvfs, name->full_name, mode, name->allow_override) == -1) {
return pvfs_map_errno(pvfs, errno);
}
@@ -69,7 +69,7 @@ static NTSTATUS pvfs_t2mkdir(struct pvfs_state *pvfs,
/* setup an inherited acl from the parent */
status = pvfs_acl_inherit(pvfs, req, name, -1);
if (!NT_STATUS_IS_OK(status)) {
- pvfs_sys_rmdir(pvfs, name->full_name);
+ pvfs_sys_rmdir(pvfs, name->full_name, name->allow_override);
return status;
}
@@ -78,7 +78,7 @@ static NTSTATUS pvfs_t2mkdir(struct pvfs_state *pvfs,
md->t2mkdir.in.num_eas,
md->t2mkdir.in.eas);
if (!NT_STATUS_IS_OK(status)) {
- pvfs_sys_rmdir(pvfs, name->full_name);
+ pvfs_sys_rmdir(pvfs, name->full_name, name->allow_override);
return status;
}
@@ -127,7 +127,7 @@ NTSTATUS pvfs_mkdir(struct ntvfs_module_context *ntvfs,
mode = pvfs_fileperms(pvfs, FILE_ATTRIBUTE_DIRECTORY);
- if (pvfs_sys_mkdir(pvfs, name->full_name, mode) == -1) {
+ if (pvfs_sys_mkdir(pvfs, name->full_name, mode, name->allow_override) == -1) {
return pvfs_map_errno(pvfs, errno);
}
@@ -136,7 +136,7 @@ NTSTATUS pvfs_mkdir(struct ntvfs_module_context *ntvfs,
/* setup an inherited acl from the parent */
status = pvfs_acl_inherit(pvfs, req, name, -1);
if (!NT_STATUS_IS_OK(status)) {
- pvfs_sys_rmdir(pvfs, name->full_name);
+ pvfs_sys_rmdir(pvfs, name->full_name, name->allow_override);
return status;
}
@@ -179,7 +179,7 @@ NTSTATUS pvfs_rmdir(struct ntvfs_module_context *ntvfs,
return status;
}
- if (pvfs_sys_rmdir(pvfs, name->full_name) == -1) {
+ if (pvfs_sys_rmdir(pvfs, name->full_name, name->allow_override) == -1) {
/* some olders systems don't return ENOTEMPTY to rmdir() */
if (errno == EEXIST) {
return NT_STATUS_DIRECTORY_NOT_EMPTY;
diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c
index c0f55e8e73c..a095f746331 100644
--- a/source4/ntvfs/posix/pvfs_open.c
+++ b/source4/ntvfs/posix/pvfs_open.c
@@ -73,7 +73,7 @@ static int pvfs_dir_handle_destructor(struct pvfs_file_handle *h)
DEBUG(0,("Warning: xattr unlink hook failed for '%s' - %s\n",
delete_path, nt_errstr(status)));
}
- if (pvfs_sys_rmdir(h->pvfs, delete_path) != 0) {
+ if (pvfs_sys_rmdir(h->pvfs, delete_path, h->name->allow_override) != 0) {
DEBUG(0,("pvfs_dir_handle_destructor: failed to rmdir '%s' - %s\n",
delete_path, strerror(errno)));
}
@@ -344,7 +344,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs,
uint32_t attrib = io->generic.in.file_attr | FILE_ATTRIBUTE_DIRECTORY;
mode_t mode = pvfs_fileperms(pvfs, attrib);
- if (pvfs_sys_mkdir(pvfs, name->full_name, mode) == -1) {
+ if (pvfs_sys_mkdir(pvfs, name->full_name, mode, name->allow_override) == -1) {
return pvfs_map_errno(pvfs,errno);
}
@@ -432,7 +432,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs,
return NT_STATUS_OK;
cleanup_delete:
- pvfs_sys_rmdir(pvfs, name->full_name);
+ pvfs_sys_rmdir(pvfs, name->full_name, name->allow_override);
return status;
}
@@ -514,7 +514,7 @@ static int pvfs_handle_destructor(struct pvfs_file_handle *h)
DEBUG(0,("Warning: xattr unlink hook failed for '%s' - %s\n",
delete_path, nt_errstr(status)));
}
- if (pvfs_sys_unlink(h->pvfs, delete_path) != 0) {
+ if (pvfs_sys_unlink(h->pvfs, delete_path, h->name->allow_override) != 0) {
DEBUG(0,("pvfs_close: failed to delete '%s' - %s\n",
delete_path, strerror(errno)));
} else {
@@ -677,7 +677,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs,
mode = pvfs_fileperms(pvfs, attrib);
/* create the file */
- fd = pvfs_sys_open(pvfs, name->full_name, flags | O_CREAT | O_EXCL| O_NONBLOCK, mode);
+ fd = pvfs_sys_open(pvfs, name->full_name, flags | O_CREAT | O_EXCL| O_NONBLOCK, mode, name->allow_override);
if (fd == -1) {
return pvfs_map_errno(pvfs, errno);
}
@@ -856,7 +856,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs,
cleanup_delete:
close(fd);
- pvfs_sys_unlink(pvfs, name->full_name);
+ pvfs_sys_unlink(pvfs, name->full_name, name->allow_override);
return status;
}
@@ -1549,7 +1549,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
}
/* do the actual open */
- fd = pvfs_sys_open(pvfs, f->handle->name->full_name, flags | O_NONBLOCK, 0);
+ fd = pvfs_sys_open(pvfs, f->handle->name->full_name, flags | O_NONBLOCK, 0, name->allow_override);
if (fd == -1) {
status = pvfs_map_errno(f->pvfs, errno);
@@ -1635,7 +1635,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
mode_t mode = pvfs_fileperms(pvfs, attrib);
if (f->handle->name->st.st_mode != mode &&
f->handle->name->dos.attrib != attrib &&
- pvfs_sys_fchmod(pvfs, fd, mode) == -1) {
+ pvfs_sys_fchmod(pvfs, fd, mode, name->allow_override) == -1) {
talloc_free(lck);
return pvfs_map_errno(pvfs, errno);
}
diff --git a/source4/ntvfs/posix/pvfs_rename.c b/source4/ntvfs/posix/pvfs_rename.c
index 5296811f022..432716130c6 100644
--- a/source4/ntvfs/posix/pvfs_rename.c
+++ b/source4/ntvfs/posix/pvfs_rename.c
@@ -37,7 +37,8 @@ NTSTATUS pvfs_do_rename(struct pvfs_state *pvfs,
uint32_t mask;
NTSTATUS status;
- if (pvfs_sys_rename(pvfs, name1->full_name, name2) == -1) {
+ if (pvfs_sys_rename(pvfs, name1->full_name, name2,
+ name1->allow_override) == -1) {
return pvfs_map_errno(pvfs, errno);
}
@@ -624,7 +625,7 @@ static NTSTATUS pvfs_rename_nt(struct ntvfs_module_context *ntvfs,
case RENAME_FLAG_COPY:
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);
+ return pvfs_copy_file(pvfs, name1, name2, name1->allow_override && name2->allow_override);
case RENAME_FLAG_MOVE_CLUSTER_INFORMATION:
DEBUG(3,(__location__ ": Invalid rename cluster for %s\n",
diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c
index 255728382eb..837ea174d62 100644
--- a/source4/ntvfs/posix/pvfs_resolve.c
+++ b/source4/ntvfs/posix/pvfs_resolve.c
@@ -518,6 +518,7 @@ NTSTATUS pvfs_resolve_name(struct pvfs_state *pvfs,
(*name)->exists = false;
(*name)->stream_exists = false;
+ (*name)->allow_override = false;
if (!(pvfs->fs_attribs & FS_ATTR_NAMED_STREAMS)) {
flags &= ~PVFS_RESOLVE_STREAMS;
@@ -630,6 +631,7 @@ NTSTATUS pvfs_resolve_partial(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx,
(*name)->original_name = talloc_strdup(*name, fname);
(*name)->stream_name = NULL;
(*name)->stream_id = 0;
+ (*name)->allow_override = false;
status = pvfs_fill_dos_info(pvfs, *name, flags, -1);
@@ -815,6 +817,7 @@ NTSTATUS pvfs_resolve_parent(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx,
}
(*name)->stream_name = NULL;
(*name)->stream_id = 0;
+ (*name)->allow_override = false;
status = pvfs_fill_dos_info(pvfs, *name, PVFS_RESOLVE_NO_OPENDB, -1);
diff --git a/source4/ntvfs/posix/pvfs_setfileinfo.c b/source4/ntvfs/posix/pvfs_setfileinfo.c
index cbb5c7853cb..3c9b18d91ce 100644
--- a/source4/ntvfs/posix/pvfs_setfileinfo.c
+++ b/source4/ntvfs/posix/pvfs_setfileinfo.c
@@ -534,7 +534,7 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs,
}
mode = pvfs_fileperms(pvfs, newstats.dos.attrib);
if (!(h->name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)) {
- if (pvfs_sys_fchmod(pvfs, h->fd, mode) == -1) {
+ if (pvfs_sys_fchmod(pvfs, h->fd, mode, h->name->allow_override) == -1) {
return pvfs_map_errno(pvfs, errno);
}
}
@@ -859,7 +859,7 @@ NTSTATUS pvfs_setpathinfo(struct ntvfs_module_context *ntvfs,
newstats.dos.attrib |= (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY);
if (newstats.dos.attrib != name->dos.attrib) {
mode_t mode = pvfs_fileperms(pvfs, newstats.dos.attrib);
- if (pvfs_sys_chmod(pvfs, name->full_name, mode) == -1) {
+ if (pvfs_sys_chmod(pvfs, name->full_name, mode, name->allow_override) == -1) {
return pvfs_map_errno(pvfs, errno);
}
change_mask |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
diff --git a/source4/ntvfs/posix/pvfs_sys.c b/source4/ntvfs/posix/pvfs_sys.c
index f1105901539..9112848bfef 100644
--- a/source4/ntvfs/posix/pvfs_sys.c
+++ b/source4/ntvfs/posix/pvfs_sys.c
@@ -256,7 +256,7 @@ static int pvfs_sys_chown(struct pvfs_state *pvfs, struct pvfs_sys_ctx *ctx, con
/*
wrap open for system override
*/
-int pvfs_sys_open(struct pvfs_state *pvfs, const char *filename, int flags, mode_t mode)
+int pvfs_sys_open(struct pvfs_state *pvfs, const char *filename, int flags, mode_t mode, bool allow_override)
{
int fd, ret;
struct pvfs_sys_ctx *ctx;
@@ -267,7 +267,7 @@ int pvfs_sys_open(struct pvfs_state *pvfs, const char *filename, int flags, mode
fd = open(filename, flags, mode);
if (fd != -1 ||
- !(pvfs->flags & PVFS_FLAG_PERM_OVERRIDE) ||
+ !allow_override ||
errno != EACCES) {
return fd;
}
@@ -366,7 +366,7 @@ int pvfs_sys_open(struct pvfs_state *pvfs, const char *filename, int flags, mode
/*
wrap unlink for system override
*/
-int pvfs_sys_unlink(struct pvfs_state *pvfs, const char *filename)
+int pvfs_sys_unlink(struct pvfs_state *pvfs, const char *filename, bool allow_override)
{
int ret;
struct pvfs_sys_ctx *ctx;
@@ -376,7 +376,7 @@ int pvfs_sys_unlink(struct pvfs_state *pvfs, const char *filename)
ret = unlink(filename);
if (ret != -1 ||
- !(pvfs->flags & PVFS_FLAG_PERM_OVERRIDE) ||
+ !allow_override ||
errno != EACCES) {
return ret;
}
@@ -415,7 +415,7 @@ static bool contains_symlink(const char *path)
/*
wrap rename for system override
*/
-int pvfs_sys_rename(struct pvfs_state *pvfs, const char *name1, const char *name2)
+int pvfs_sys_rename(struct pvfs_state *pvfs, const char *name1, const char *name2, bool allow_override)
{
int ret;
struct pvfs_sys_ctx *ctx;
@@ -425,7 +425,7 @@ int pvfs_sys_rename(struct pvfs_state *pvfs, const char *name1, const char *name
ret = rename(name1, name2);
if (ret != -1 ||
- !(pvfs->flags & PVFS_FLAG_PERM_OVERRIDE) ||
+ !allow_override ||
errno != EACCES) {
return ret;
}
@@ -480,7 +480,7 @@ int pvfs_sys_rename(struct pvfs_state *pvfs, const char *name1, const char *name
/*
wrap mkdir for system override
*/
-int pvfs_sys_mkdir(struct pvfs_state *pvfs, const char *dirname, mode_t mode)
+int pvfs_sys_mkdir(struct pvfs_state *pvfs, const char *dirname, mode_t mode, bool allow_override)
{
int ret;
struct pvfs_sys_ctx *ctx;
@@ -490,7 +490,7 @@ int pvfs_sys_mkdir(struct pvfs_state *pvfs, const char *dirname, mode_t mode)
ret = mkdir(dirname, mode);
if (ret != -1 ||
- !(pvfs->flags & PVFS_FLAG_PERM_OVERRIDE) ||
+ !allow_override ||
errno != EACCES) {
return ret;
}
@@ -525,7 +525,7 @@ int pvfs_sys_mkdir(struct pvfs_state *pvfs, const char *dirname, mode_t mode)
/*
wrap rmdir for system override
*/
-int pvfs_sys_rmdir(struct pvfs_state *pvfs, const char *dirname)
+int pvfs_sys_rmdir(struct pvfs_state *pvfs, const char *dirname, bool allow_override)
{
int ret;
struct pvfs_sys_ctx *ctx;
@@ -535,7 +535,7 @@ int pvfs_sys_rmdir(struct pvfs_state *pvfs, const char *dirname)
ret = rmdir(dirname);
if (ret != -1 ||
- !(pvfs->flags & PVFS_FLAG_PERM_OVERRIDE) ||
+ !allow_override ||
errno != EACCES) {
return ret;
}
@@ -563,7 +563,7 @@ int pvfs_sys_rmdir(struct pvfs_state *pvfs, const char *dirname)
/*
wrap fchmod for system override
*/
-int pvfs_sys_fchmod(struct pvfs_state *pvfs, int fd, mode_t mode)
+int pvfs_sys_fchmod(struct pvfs_state *pvfs, int fd, mode_t mode, bool allow_override)
{
int ret;
struct pvfs_sys_ctx *ctx;
@@ -573,7 +573,7 @@ int pvfs_sys_fchmod(struct pvfs_state *pvfs, int fd, mode_t mode)
ret = fchmod(fd, mode);
if (ret != -1 ||
- !(pvfs->flags & PVFS_FLAG_PERM_OVERRIDE) ||
+ !allow_override ||
errno != EACCES) {
return ret;
}
@@ -602,7 +602,7 @@ int pvfs_sys_fchmod(struct pvfs_state *pvfs, int fd, mode_t mode)
/*
wrap chmod for system override
*/
-int pvfs_sys_chmod(struct pvfs_state *pvfs, const char *filename, mode_t mode)
+int pvfs_sys_chmod(struct pvfs_state *pvfs, const char *filename, mode_t mode, bool allow_override)
{
int ret;
struct pvfs_sys_ctx *ctx;
@@ -612,7 +612,7 @@ int pvfs_sys_chmod(struct pvfs_state *pvfs, const char *filename, mode_t mode)
ret = chmod(filename, mode);
if (ret != -1 ||
- !(pvfs->flags & PVFS_FLAG_PERM_OVERRIDE) ||
+ !allow_override ||
errno != EACCES) {
return ret;
}
diff --git a/source4/ntvfs/posix/pvfs_unlink.c b/source4/ntvfs/posix/pvfs_unlink.c
index be2ba531488..a4b51d1d7d3 100644
--- a/source4/ntvfs/posix/pvfs_unlink.c
+++ b/source4/ntvfs/posix/pvfs_unlink.c
@@ -123,7 +123,7 @@ static NTSTATUS pvfs_unlink_file(struct pvfs_state *pvfs,
}
/* finally try the actual unlink */
- if (pvfs_sys_unlink(pvfs, name->full_name) == -1) {
+ if (pvfs_sys_unlink(pvfs, name->full_name, name->allow_override) == -1) {
status = pvfs_map_errno(pvfs, errno);
}
diff --git a/source4/ntvfs/posix/pvfs_util.c b/source4/ntvfs/posix/pvfs_util.c
index c6c6eaa13c8..6afb928d73c 100644
--- a/source4/ntvfs/posix/pvfs_util.c
+++ b/source4/ntvfs/posix/pvfs_util.c
@@ -90,7 +90,8 @@ uint32_t pvfs_attrib_normalise(uint32_t attrib, mode_t mode)
*/
NTSTATUS pvfs_copy_file(struct pvfs_state *pvfs,
struct pvfs_filename *name1,
- struct pvfs_filename *name2)
+ struct pvfs_filename *name2,
+ bool allow_override)
{
int fd1, fd2;
mode_t mode;
@@ -102,13 +103,13 @@ NTSTATUS pvfs_copy_file(struct pvfs_state *pvfs,
return NT_STATUS_NO_MEMORY;
}
- fd1 = pvfs_sys_open(pvfs, name1->full_name, O_RDONLY, 0);
+ fd1 = pvfs_sys_open(pvfs, name1->full_name, O_RDONLY, 0, allow_override);
if (fd1 == -1) {
talloc_free(buf);
return pvfs_map_errno(pvfs, errno);
}
- fd2 = pvfs_sys_open(pvfs, name2->full_name, O_CREAT|O_EXCL|O_WRONLY, 0);
+ fd2 = pvfs_sys_open(pvfs, name2->full_name, O_CREAT|O_EXCL|O_WRONLY, 0, allow_override);
if (fd2 == -1) {
close(fd1);
talloc_free(buf);
@@ -133,7 +134,7 @@ NTSTATUS pvfs_copy_file(struct pvfs_state *pvfs,
close(fd1);
close(fd2);
talloc_free(buf);
- pvfs_sys_unlink(pvfs, name2->full_name);
+ pvfs_sys_unlink(pvfs, name2->full_name, allow_override);
if (ret2 == -1) {
return pvfs_map_errno(pvfs, errno);
}
@@ -145,10 +146,10 @@ NTSTATUS pvfs_copy_file(struct pvfs_state *pvfs,
close(fd1);
mode = pvfs_fileperms(pvfs, name1->dos.attrib);
- if (pvfs_sys_fchmod(pvfs, fd2, mode) == -1) {
+ if (pvfs_sys_fchmod(pvfs, fd2, mode, allow_override) == -1) {
status = pvfs_map_errno(pvfs, errno);
close(fd2);
- pvfs_sys_unlink(pvfs, name2->full_name);
+ pvfs_sys_unlink(pvfs, name2->full_name, allow_override);
return status;
}
@@ -158,7 +159,7 @@ NTSTATUS pvfs_copy_file(struct pvfs_state *pvfs,
status = pvfs_dosattrib_save(pvfs, name2, fd2);
if (!NT_STATUS_IS_OK(status)) {
close(fd2);
- pvfs_sys_unlink(pvfs, name2->full_name);
+ pvfs_sys_unlink(pvfs, name2->full_name, allow_override);
return status;
}
diff --git a/source4/ntvfs/posix/vfs_posix.h b/source4/ntvfs/posix/vfs_posix.h
index e1593a38cf5..9a03658040f 100644
--- a/source4/ntvfs/posix/vfs_posix.h
+++ b/source4/ntvfs/posix/vfs_posix.h
@@ -131,6 +131,7 @@ struct pvfs_filename {
bool has_wildcard;
bool exists; /* true if the base filename exists */
bool stream_exists; /* true if the stream exists */
+ bool allow_override;
struct stat st;
struct pvfs_dos_fileinfo dos;
};