Blame src/cmds/ntux_cmd_chmod.c

80f43a
/***********************************************************/
80f43a
/*  ntux: native translation und extension                 */
80f43a
/*  Copyright (C) 2016--2018  Z. Gilboa                    */
80f43a
/*  Released under GPLv2 and GPLv3; see COPYING.NTUX.      */
80f43a
/***********************************************************/
80f43a
80f43a
#include <ntapi/ntapi.h>
80f43a
#include <psxabi/sys_sysapi.h>
80f43a
#include <psxabi/sys_stat.h>
80f43a
#include <psxabi/sys_errno.h>
80f43a
eb0350
#include <psxxfi/xfi_fs.h>
80f43a
#include <psxxfi/xfi_ofd.h>
80f43a
#include <psxxfi/xfi_unicode.h>
80f43a
80f43a
#include <ntux/ntux.h>
80f43a
#include "ntux_driver_impl.h"
80f43a
#include "ntux_nolibc_impl.h"
80f43a
#include "ntux_errinfo_impl.h"
80f43a
eb0350
static int ntux_cmd_chmod_ret(int fd, struct __ofd * ofd, void * hasync, int ret)
eb0350
{
eb0350
	if (hasync)
eb0350
		ntapi->zw_close(hasync);
eb0350
eb0350
	if (ofd)
eb0350
		__xfi_ofd_ref_dec(ofd);
eb0350
eb0350
	if (fd >= 0)
eb0350
		__sys_close(fd);
eb0350
eb0350
	return ret;
eb0350
}
eb0350
80f43a
int ntux_cmd_chmod(const struct ntux_driver_ctx * dctx, const char * dunit)
80f43a
{
eb0350
	intptr_t		ret;
eb0350
	int32_t			status;
eb0350
	int			fdout;
eb0350
	int			fdcwd;
eb0350
	const unsigned char *	unit;
eb0350
	nt_sd *			srcsd;
eb0350
	nt_sd_common_buffer	dstsd;
eb0350
	nt_sd_common_meta	meta;
eb0350
	uint32_t		access_owner;
eb0350
	uint32_t		access_group;
eb0350
	uint32_t		access_other;
eb0350
	uint32_t		access_admin;
eb0350
	size_t			size;
eb0350
	int			fd      = -1;
eb0350
	struct __ofd *		ofd     = 0;
eb0350
	void *			hasync  = 0;
eb0350
	uint32_t		buf[0x300];
eb0350
eb0350
	/* initial version: only support m+p */
eb0350
	if (!dctx->cctx->strmode || strcmp(dctx->cctx->strmode,"m+p"))
eb0350
		return ntux_cmd_chmod_ret(
eb0350
			0,0,0,
eb0350
			NTUX_CUSTOM_ERROR(
eb0350
				dctx,
eb0350
				NTUX_ERR_FLEE_ERROR));
eb0350
eb0350
	/* init */
eb0350
	ntux_driver_set_ectx(
eb0350
		dctx,0,dunit);
eb0350
eb0350
	unit = (const unsigned char *)dunit;
eb0350
eb0350
	/* fdctx */
eb0350
	fdout = ntux_driver_fdout(dctx);
eb0350
	fdcwd = ntux_driver_fdcwd(dctx);
eb0350
eb0350
	/* fd */
eb0350
	if ((ret = __sys_openat(fdcwd,unit,0,0)) < 0)
eb0350
		if (ntux_errno_set(dctx,ret))
eb0350
			return ntux_cmd_chmod_ret(
eb0350
				0,0,0,
eb0350
				NTUX_SYSTEM_ERROR(dctx));
eb0350
eb0350
	fd = ret;
eb0350
eb0350
	/* ofd */
eb0350
	if (!(ofd = __xfi_ofd_ref_inc(fd)))
eb0350
		return ntux_cmd_chmod_ret(
eb0350
			fd,0,0,
eb0350
			NTUX_CUSTOM_ERROR(
eb0350
				dctx,
eb0350
				NTUX_ERR_FLOW_ERROR));
eb0350
eb0350
	/* hasync */
eb0350
	if ((status = __xfi_fs_open_async(
eb0350
			&hasync,
eb0350
			ofd->info.hfile,0,
eb0350
			NT_SEC_READ_CONTROL
eb0350
				| NT_SEC_WRITE_DAC,
eb0350
			NT_FILE_SHARE_READ
eb0350
				| NT_FILE_SHARE_WRITE
eb0350
				| NT_FILE_SHARE_DELETE)))
eb0350
		return ntux_cmd_chmod_ret(
eb0350
			fd,ofd,0,
eb0350
			NTUX_SYSTEM_ERROR(dctx));
eb0350
eb0350
	/* srcsd */
eb0350
	srcsd = (nt_sd *)buf;
eb0350
eb0350
	if ((status = ntapi->zw_query_security_object(
eb0350
			hasync,
eb0350
			NT_OWNER_SECURITY_INFORMATION
eb0350
				| NT_GROUP_SECURITY_INFORMATION
eb0350
				| NT_DACL_SECURITY_INFORMATION,
eb0350
			srcsd,sizeof(buf),&size)))
eb0350
		return ntux_cmd_chmod_ret(
eb0350
			fd,ofd,hasync,
eb0350
			NTUX_SYSTEM_ERROR(dctx));
eb0350
eb0350
	if ((status = ntapi->acl_init_common_descriptor_meta(
eb0350
			&meta,srcsd,
eb0350
			NT_ACL_INIT_COMMON_DESCRIPTION_META_STRICT_MODE)))
eb0350
		return ntux_cmd_chmod_ret(
eb0350
			fd,ofd,hasync,
eb0350
			NTUX_SYSTEM_ERROR(dctx));
eb0350
eb0350
	/* source permissions */
eb0350
	access_owner  = meta.owner_ace  ? meta.owner_ace->mask  : 0;
eb0350
	access_group  = meta.group_ace  ? meta.group_ace->mask  : 0;
eb0350
	access_other  = meta.other_ace  ? meta.other_ace->mask  : 0;
eb0350
eb0350
	/* initial version: only support m+p */
eb0350
	access_admin = access_owner | NT_SEC_WRITE_DAC;
eb0350
eb0350
	/* updated dacl */
eb0350
	ntapi->acl_init_common_descriptor(
eb0350
		&dstsd,
eb0350
		meta.owner,meta.group,0,0,
eb0350
		access_owner,access_group,access_other,
eb0350
		access_admin,meta.system_acc);
eb0350
eb0350
	if ((status = ntapi->zw_set_security_object(
eb0350
			hasync,
eb0350
			NT_DACL_SECURITY_INFORMATION,
eb0350
			&dstsd.sd)))
eb0350
		return ntux_cmd_chmod_ret(
eb0350
			fd,ofd,hasync,
eb0350
			NTUX_SYSTEM_ERROR(dctx));
eb0350
eb0350
	/* changes */
eb0350
	(void)fdout;
80f43a
eb0350
	/* all done */
eb0350
	return ntux_cmd_chmod_ret(fd,ofd,hasync,0);
80f43a
}