diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cmds/ntux_cmd_chmod.c | 131 |
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); } |