/***********************************************************/
/* ntux: native translation und extension */
/* Copyright (C) 2016--2018 Z. Gilboa */
/* Released under GPLv2 and GPLv3; see COPYING.NTUX. */
/***********************************************************/
#include <psxabi/sys_sysapi.h>
#include <psxabi/sys_stat.h>
#include <psxabi/sys_errno.h>
#include <psxxfi/xfi_base.h>
#include <psxxfi/xfi_acl.h>
#include <psxxfi/xfi_fs.h>
#include <psxxfi/xfi_ofd.h>
#include <psxxfi/xfi_unicode.h>
#include <ntapi/nt_acl.h>
#include <ntapi/nt_file.h>
#include <ntux/ntux.h>
#include "ntux_driver_impl.h"
#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)
__xfi_close_handle(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)
{
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;
uint32_t ace_flags;
size_t size;
int fd = -1;
struct __ofd * ofd = 0;
void * hasync = 0;
uint32_t buf[0x300];
/* initial version: --strmode only */
if (!dctx->cctx->strmode)
return ntux_cmd_chmod_ret(
0,0,0,
NTUX_CUSTOM_ERROR(
dctx,
NTUX_ERR_FLEE_ERROR));
/* ACE propagation: +p, -p */
if (!strcmp(dctx->cctx->strmode,"+p"))
ace_flags = NT_ACE_CONTAINER_INHERIT | NT_ACE_OBJECT_INHERIT;
else if (!strcmp(dctx->cctx->strmode,"-p"))
ace_flags = 0;
else
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 = __xfi_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 = __xfi_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;
access_admin = meta.admin_ace ? meta.admin_ace->mask : 0;
/* updated dacl */
__xfi_acl_init_common_descriptor(
&dstsd,
meta.owner,meta.group,0,0,
access_owner,access_group,access_other,
access_admin,meta.system_acc,
ace_flags);
if ((status = __xfi_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;
/* all done */
return ntux_cmd_chmod_ret(fd,ofd,hasync,0);
}