summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/cmds/ntux_cmd_chmod.c131
1 files changed, 128 insertions, 3 deletions
diff --git a/src/cmds/ntux_cmd_chmod.c b/src/cmds/ntux_cmd_chmod.c
index 00788eb..03ab8f5 100644
--- a/src/cmds/ntux_cmd_chmod.c
+++ b/src/cmds/ntux_cmd_chmod.c
@@ -9,6 +9,7 @@
#include <psxabi/sys_stat.h>
#include <psxabi/sys_errno.h>
+#include <psxxfi/xfi_fs.h>
#include <psxxfi/xfi_ofd.h>
#include <psxxfi/xfi_unicode.h>
@@ -17,10 +18,134 @@
#include "ntux_nolibc_impl.h"
#include "ntux_errinfo_impl.h"
+static int ntux_cmd_chmod_ret(int fd, struct __ofd * ofd, void * hasync, int ret)
+{
+ if (hasync)
+ ntapi->zw_close(hasync);
+
+ if (ofd)
+ __xfi_ofd_ref_dec(ofd);
+
+ if (fd >= 0)
+ __sys_close(fd);
+
+ return ret;
+}
+
int ntux_cmd_chmod(const struct ntux_driver_ctx * dctx, const char * dunit)
{
- (void)dctx;
- (void)dunit;
+ intptr_t ret;
+ int32_t status;
+ int fdout;
+ int fdcwd;
+ const unsigned char * unit;
+ nt_sd * srcsd;
+ nt_sd_common_buffer dstsd;
+ nt_sd_common_meta meta;
+ uint32_t access_owner;
+ uint32_t access_group;
+ uint32_t access_other;
+ uint32_t access_admin;
+ size_t size;
+ int fd = -1;
+ struct __ofd * ofd = 0;
+ void * hasync = 0;
+ uint32_t buf[0x300];
+
+ /* initial version: only support m+p */
+ if (!dctx->cctx->strmode || strcmp(dctx->cctx->strmode,"m+p"))
+ return ntux_cmd_chmod_ret(
+ 0,0,0,
+ NTUX_CUSTOM_ERROR(
+ dctx,
+ NTUX_ERR_FLEE_ERROR));
+
+ /* init */
+ ntux_driver_set_ectx(
+ dctx,0,dunit);
+
+ unit = (const unsigned char *)dunit;
+
+ /* fdctx */
+ fdout = ntux_driver_fdout(dctx);
+ fdcwd = ntux_driver_fdcwd(dctx);
+
+ /* fd */
+ if ((ret = __sys_openat(fdcwd,unit,0,0)) < 0)
+ if (ntux_errno_set(dctx,ret))
+ return ntux_cmd_chmod_ret(
+ 0,0,0,
+ NTUX_SYSTEM_ERROR(dctx));
+
+ fd = ret;
+
+ /* ofd */
+ if (!(ofd = __xfi_ofd_ref_inc(fd)))
+ return ntux_cmd_chmod_ret(
+ fd,0,0,
+ NTUX_CUSTOM_ERROR(
+ dctx,
+ NTUX_ERR_FLOW_ERROR));
+
+ /* hasync */
+ if ((status = __xfi_fs_open_async(
+ &hasync,
+ ofd->info.hfile,0,
+ NT_SEC_READ_CONTROL
+ | NT_SEC_WRITE_DAC,
+ NT_FILE_SHARE_READ
+ | NT_FILE_SHARE_WRITE
+ | NT_FILE_SHARE_DELETE)))
+ return ntux_cmd_chmod_ret(
+ fd,ofd,0,
+ NTUX_SYSTEM_ERROR(dctx));
+
+ /* srcsd */
+ srcsd = (nt_sd *)buf;
+
+ if ((status = ntapi->zw_query_security_object(
+ hasync,
+ NT_OWNER_SECURITY_INFORMATION
+ | NT_GROUP_SECURITY_INFORMATION
+ | NT_DACL_SECURITY_INFORMATION,
+ srcsd,sizeof(buf),&size)))
+ return ntux_cmd_chmod_ret(
+ fd,ofd,hasync,
+ NTUX_SYSTEM_ERROR(dctx));
+
+ if ((status = ntapi->acl_init_common_descriptor_meta(
+ &meta,srcsd,
+ NT_ACL_INIT_COMMON_DESCRIPTION_META_STRICT_MODE)))
+ return ntux_cmd_chmod_ret(
+ fd,ofd,hasync,
+ NTUX_SYSTEM_ERROR(dctx));
+
+ /* source permissions */
+ access_owner = meta.owner_ace ? meta.owner_ace->mask : 0;
+ access_group = meta.group_ace ? meta.group_ace->mask : 0;
+ access_other = meta.other_ace ? meta.other_ace->mask : 0;
+
+ /* initial version: only support m+p */
+ access_admin = access_owner | NT_SEC_WRITE_DAC;
+
+ /* updated dacl */
+ ntapi->acl_init_common_descriptor(
+ &dstsd,
+ meta.owner,meta.group,0,0,
+ access_owner,access_group,access_other,
+ access_admin,meta.system_acc);
+
+ if ((status = ntapi->zw_set_security_object(
+ hasync,
+ NT_DACL_SECURITY_INFORMATION,
+ &dstsd.sd)))
+ return ntux_cmd_chmod_ret(
+ fd,ofd,hasync,
+ NTUX_SYSTEM_ERROR(dctx));
+
+ /* changes */
+ (void)fdout;
- return 0;
+ /* all done */
+ return ntux_cmd_chmod_ret(fd,ofd,hasync,0);
}