xref: /onnv-gate/usr/src/uts/common/fs/smbsrv/smb_fsinfo.c (revision 13082:81ec56bf6147)
111963SAfshin.Ardakani@Sun.COM /*
211963SAfshin.Ardakani@Sun.COM  * CDDL HEADER START
311963SAfshin.Ardakani@Sun.COM  *
411963SAfshin.Ardakani@Sun.COM  * The contents of this file are subject to the terms of the
511963SAfshin.Ardakani@Sun.COM  * Common Development and Distribution License (the "License").
611963SAfshin.Ardakani@Sun.COM  * You may not use this file except in compliance with the License.
711963SAfshin.Ardakani@Sun.COM  *
811963SAfshin.Ardakani@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
911963SAfshin.Ardakani@Sun.COM  * or http://www.opensolaris.org/os/licensing.
1011963SAfshin.Ardakani@Sun.COM  * See the License for the specific language governing permissions
1111963SAfshin.Ardakani@Sun.COM  * and limitations under the License.
1211963SAfshin.Ardakani@Sun.COM  *
1311963SAfshin.Ardakani@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
1411963SAfshin.Ardakani@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1511963SAfshin.Ardakani@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
1611963SAfshin.Ardakani@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
1711963SAfshin.Ardakani@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
1811963SAfshin.Ardakani@Sun.COM  *
1911963SAfshin.Ardakani@Sun.COM  * CDDL HEADER END
2011963SAfshin.Ardakani@Sun.COM  */
2111963SAfshin.Ardakani@Sun.COM /*
22*13082SJoyce.McIntosh@Sun.COM  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
2311963SAfshin.Ardakani@Sun.COM  */
2411963SAfshin.Ardakani@Sun.COM 
2511963SAfshin.Ardakani@Sun.COM #include <smbsrv/smb_kproto.h>
2611963SAfshin.Ardakani@Sun.COM #include <smbsrv/smb_fsops.h>
2711963SAfshin.Ardakani@Sun.COM #include <smbsrv/smbinfo.h>
2811963SAfshin.Ardakani@Sun.COM 
2911963SAfshin.Ardakani@Sun.COM /*
3011963SAfshin.Ardakani@Sun.COM  * smb_fssize_t
3111963SAfshin.Ardakani@Sun.COM  * volume_units and volume avail are the total allocated and
3211963SAfshin.Ardakani@Sun.COM  * available units on the volume.
3311963SAfshin.Ardakani@Sun.COM  * caller_units and caller_avail are the allocated and available
3411963SAfshin.Ardakani@Sun.COM  * units on the volume for the user associated with the calling
3511963SAfshin.Ardakani@Sun.COM  * thread.
3611963SAfshin.Ardakani@Sun.COM  */
3711963SAfshin.Ardakani@Sun.COM typedef struct smb_fssize {
3811963SAfshin.Ardakani@Sun.COM 	uint64_t	fs_volume_units;
3911963SAfshin.Ardakani@Sun.COM 	uint64_t	fs_volume_avail;
4011963SAfshin.Ardakani@Sun.COM 	uint64_t	fs_caller_units;
4111963SAfshin.Ardakani@Sun.COM 	uint64_t	fs_caller_avail;
4211963SAfshin.Ardakani@Sun.COM 	uint32_t	fs_sectors_per_unit;
4311963SAfshin.Ardakani@Sun.COM 	uint32_t	fs_bytes_per_sector;
4411963SAfshin.Ardakani@Sun.COM } smb_fssize_t;
4511963SAfshin.Ardakani@Sun.COM 
4611963SAfshin.Ardakani@Sun.COM /*
4711963SAfshin.Ardakani@Sun.COM  * File System Control Flags for smb_com_trans2_query|set_fs_information
4811963SAfshin.Ardakani@Sun.COM  * level SMB_FILE_FS_CONTROL_INFORMATION
4911963SAfshin.Ardakani@Sun.COM  */
5011963SAfshin.Ardakani@Sun.COM #define	FILE_VC_QUOTA_TRACK		0x00000001
5111963SAfshin.Ardakani@Sun.COM #define	FILE_VC_QUOTA_ENFORCE		0x00000002
5211963SAfshin.Ardakani@Sun.COM #define	FILE_VC_CONTENT_INDEX_DISABLED	0x00000008
5311963SAfshin.Ardakani@Sun.COM #define	FILE_VC_LOG_QUOTA_THRESHOLD	0x00000010
5411963SAfshin.Ardakani@Sun.COM #define	FILE_VC_LOG_QUOTA_LIMIT		0x00000020
5511963SAfshin.Ardakani@Sun.COM #define	FILE_VC_LOG_VOLUME_THRESHOLD	0x00000040
5611963SAfshin.Ardakani@Sun.COM #define	FILE_VC_LOG_VOLUME_LIMIT	0x00000080
5711963SAfshin.Ardakani@Sun.COM #define	FILE_VC_QUOTAS_INCOMPLETE	0x00000100
5811963SAfshin.Ardakani@Sun.COM #define	FILE_VC_QUOTAS_REBUILDING	0x00000200
5911963SAfshin.Ardakani@Sun.COM 
6011963SAfshin.Ardakani@Sun.COM static int smb_fssize(smb_request_t *, smb_fssize_t *);
6111963SAfshin.Ardakani@Sun.COM static int smb_trans2_set_fs_ctrl_info(smb_request_t *, smb_xa_t *);
6211963SAfshin.Ardakani@Sun.COM 
6311963SAfshin.Ardakani@Sun.COM /*
6411963SAfshin.Ardakani@Sun.COM  * smb_com_query_information_disk
6511963SAfshin.Ardakani@Sun.COM  *
6611963SAfshin.Ardakani@Sun.COM  * The SMB_COM_QUERY_INFORMATION_DISK command is used to determine the
6711963SAfshin.Ardakani@Sun.COM  * capacity and remaining free space on the drive hosting the directory
6811963SAfshin.Ardakani@Sun.COM  * structure indicated by Tid in the SMB header.
6911963SAfshin.Ardakani@Sun.COM  *
7011963SAfshin.Ardakani@Sun.COM  * The blocking/allocation units used in this response may be independent
7111963SAfshin.Ardakani@Sun.COM  * of the actual physical or logical blocking/allocation algorithm(s) used
7211963SAfshin.Ardakani@Sun.COM  * internally by the server.  However, they must accurately reflect the
7311963SAfshin.Ardakani@Sun.COM  * amount of space on the server.
7411963SAfshin.Ardakani@Sun.COM  *
7511963SAfshin.Ardakani@Sun.COM  * This SMB only returns 16 bits of information for each field, which may
7611963SAfshin.Ardakani@Sun.COM  * not be large enough for some disk systems.  In particular TotalUnits is
7711963SAfshin.Ardakani@Sun.COM  * commonly > 64K.  Fortunately, it turns out the all the client cares
7811963SAfshin.Ardakani@Sun.COM  * about is the total disk size, in bytes, and the free space, in bytes.
7911963SAfshin.Ardakani@Sun.COM  * So,  it is reasonable for a server to adjust the relative values of
8011963SAfshin.Ardakani@Sun.COM  * BlocksPerUnit and BlockSize to accommodate.  If after all adjustment,
8111963SAfshin.Ardakani@Sun.COM  * the numbers are still too high, the largest possible values for
8211963SAfshin.Ardakani@Sun.COM  * TotalUnit or FreeUnits (i.e. 0xFFFF) should be returned.
8311963SAfshin.Ardakani@Sun.COM  */
8411963SAfshin.Ardakani@Sun.COM 
8511963SAfshin.Ardakani@Sun.COM smb_sdrc_t
smb_pre_query_information_disk(smb_request_t * sr)8611963SAfshin.Ardakani@Sun.COM smb_pre_query_information_disk(smb_request_t *sr)
8711963SAfshin.Ardakani@Sun.COM {
8811963SAfshin.Ardakani@Sun.COM 	DTRACE_SMB_1(op__QueryInformationDisk__start, smb_request_t *, sr);
8911963SAfshin.Ardakani@Sun.COM 	return (SDRC_SUCCESS);
9011963SAfshin.Ardakani@Sun.COM }
9111963SAfshin.Ardakani@Sun.COM 
9211963SAfshin.Ardakani@Sun.COM void
smb_post_query_information_disk(smb_request_t * sr)9311963SAfshin.Ardakani@Sun.COM smb_post_query_information_disk(smb_request_t *sr)
9411963SAfshin.Ardakani@Sun.COM {
9511963SAfshin.Ardakani@Sun.COM 	DTRACE_SMB_1(op__QueryInformationDisk__done, smb_request_t *, sr);
9611963SAfshin.Ardakani@Sun.COM }
9711963SAfshin.Ardakani@Sun.COM 
9811963SAfshin.Ardakani@Sun.COM smb_sdrc_t
smb_com_query_information_disk(smb_request_t * sr)9911963SAfshin.Ardakani@Sun.COM smb_com_query_information_disk(smb_request_t *sr)
10011963SAfshin.Ardakani@Sun.COM {
10111963SAfshin.Ardakani@Sun.COM 	int			rc;
10211963SAfshin.Ardakani@Sun.COM 	fsblkcnt64_t		total_blocks, free_blocks;
10311963SAfshin.Ardakani@Sun.COM 	unsigned long		block_size, unit_size;
10411963SAfshin.Ardakani@Sun.COM 	unsigned short		blocks_per_unit, bytes_per_block;
10511963SAfshin.Ardakani@Sun.COM 	unsigned short		total_units, free_units;
10611963SAfshin.Ardakani@Sun.COM 	smb_fssize_t		fssize;
10711963SAfshin.Ardakani@Sun.COM 
10811963SAfshin.Ardakani@Sun.COM 	if (STYPE_ISIPC(sr->tid_tree->t_res_type)) {
10911963SAfshin.Ardakani@Sun.COM 		smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess);
11011963SAfshin.Ardakani@Sun.COM 		return (SDRC_ERROR);
11111963SAfshin.Ardakani@Sun.COM 	}
11211963SAfshin.Ardakani@Sun.COM 
11311963SAfshin.Ardakani@Sun.COM 	if (smb_fssize(sr, &fssize) != 0)
11411963SAfshin.Ardakani@Sun.COM 		return (SDRC_ERROR);
11511963SAfshin.Ardakani@Sun.COM 
11611963SAfshin.Ardakani@Sun.COM 	unit_size = fssize.fs_sectors_per_unit;
11711963SAfshin.Ardakani@Sun.COM 	block_size = fssize.fs_bytes_per_sector;
11811963SAfshin.Ardakani@Sun.COM 	total_blocks = fssize.fs_caller_units;
11911963SAfshin.Ardakani@Sun.COM 	free_blocks = fssize.fs_caller_avail;
12011963SAfshin.Ardakani@Sun.COM 
12111963SAfshin.Ardakani@Sun.COM 	/*
12211963SAfshin.Ardakani@Sun.COM 	 * It seems that DOS clients cannot handle block sizes
12311963SAfshin.Ardakani@Sun.COM 	 * bigger than 512 KB. So we have to set the block size at
12411963SAfshin.Ardakani@Sun.COM 	 * most to 512
12511963SAfshin.Ardakani@Sun.COM 	 */
12611963SAfshin.Ardakani@Sun.COM 	while (block_size > 512) {
12711963SAfshin.Ardakani@Sun.COM 		block_size >>= 1;
12811963SAfshin.Ardakani@Sun.COM 		unit_size <<= 1;
12911963SAfshin.Ardakani@Sun.COM 	}
13011963SAfshin.Ardakani@Sun.COM 
13111963SAfshin.Ardakani@Sun.COM 	/* adjust blocks and sizes until they fit into a word */
13211963SAfshin.Ardakani@Sun.COM 	while (total_blocks >= 0xFFFF) {
13311963SAfshin.Ardakani@Sun.COM 		total_blocks >>= 1;
13411963SAfshin.Ardakani@Sun.COM 		free_blocks >>= 1;
13511963SAfshin.Ardakani@Sun.COM 		if ((unit_size <<= 1) > 0xFFFF) {
13611963SAfshin.Ardakani@Sun.COM 			unit_size >>= 1;
13711963SAfshin.Ardakani@Sun.COM 			total_blocks = 0xFFFF;
13811963SAfshin.Ardakani@Sun.COM 			free_blocks <<= 1;
13911963SAfshin.Ardakani@Sun.COM 			break;
14011963SAfshin.Ardakani@Sun.COM 		}
14111963SAfshin.Ardakani@Sun.COM 	}
14211963SAfshin.Ardakani@Sun.COM 
14311963SAfshin.Ardakani@Sun.COM 	total_units = (total_blocks >= 0xFFFF) ?
14411963SAfshin.Ardakani@Sun.COM 	    0xFFFF : (unsigned short)total_blocks;
14511963SAfshin.Ardakani@Sun.COM 	free_units = (free_blocks >= 0xFFFF) ?
14611963SAfshin.Ardakani@Sun.COM 	    0xFFFF : (unsigned short)free_blocks;
14711963SAfshin.Ardakani@Sun.COM 	bytes_per_block = (unsigned short)block_size;
14811963SAfshin.Ardakani@Sun.COM 	blocks_per_unit = (unsigned short)unit_size;
14911963SAfshin.Ardakani@Sun.COM 
15011963SAfshin.Ardakani@Sun.COM 	rc = smbsr_encode_result(sr, 5, 0, "bwwww2.w",
15111963SAfshin.Ardakani@Sun.COM 	    5,
15211963SAfshin.Ardakani@Sun.COM 	    total_units,	/* total_units */
15311963SAfshin.Ardakani@Sun.COM 	    blocks_per_unit,	/* blocks_per_unit */
15411963SAfshin.Ardakani@Sun.COM 	    bytes_per_block,	/* blocksize */
15511963SAfshin.Ardakani@Sun.COM 	    free_units,		/* free_units */
15611963SAfshin.Ardakani@Sun.COM 	    0);			/* bcc */
15711963SAfshin.Ardakani@Sun.COM 
15811963SAfshin.Ardakani@Sun.COM 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
15911963SAfshin.Ardakani@Sun.COM }
16011963SAfshin.Ardakani@Sun.COM 
16111963SAfshin.Ardakani@Sun.COM /*
16211963SAfshin.Ardakani@Sun.COM  * smb_com_trans2_query_fs_information
16311963SAfshin.Ardakani@Sun.COM  *
16411963SAfshin.Ardakani@Sun.COM  * This transaction requests information about the filesystem.
16511963SAfshin.Ardakani@Sun.COM  * The following information levels are supported:
16611963SAfshin.Ardakani@Sun.COM  *
16711963SAfshin.Ardakani@Sun.COM  *  InformationLevel               	Value
16811963SAfshin.Ardakani@Sun.COM  *  ==================================  ======
16911963SAfshin.Ardakani@Sun.COM  *  SMB_INFO_ALLOCATION            	1
17011963SAfshin.Ardakani@Sun.COM  *  SMB_INFO_VOLUME                	2
17111963SAfshin.Ardakani@Sun.COM  *  SMB_QUERY_FS_VOLUME_INFO       	0x102
17211963SAfshin.Ardakani@Sun.COM  *  SMB_QUERY_FS_SIZE_INFO         	0x103
17311963SAfshin.Ardakani@Sun.COM  *  SMB_QUERY_FS_DEVICE_INFO       	0x104
17411963SAfshin.Ardakani@Sun.COM  *  SMB_QUERY_FS_ATTRIBUTE_INFO    	0x105
17511963SAfshin.Ardakani@Sun.COM  *  SMB_FILE_FS_VOLUME_INFORMATION	1001
17611963SAfshin.Ardakani@Sun.COM  *  SMB_FILE_FS_SIZE_INFORMATION	1003
17711963SAfshin.Ardakani@Sun.COM  *  SMB_FILE_FS_DEVICE_INFORMATION	1004
17811963SAfshin.Ardakani@Sun.COM  *  SMB_FILE_FS_ATTRIBUTE_INFORMATION	1005
17911963SAfshin.Ardakani@Sun.COM  *  SMB_FILE_FS_CONTROL_INFORMATION	1006
18011963SAfshin.Ardakani@Sun.COM  *  SMB_FILE_FS_FULLSIZE_INFORMATION	1007
18111963SAfshin.Ardakani@Sun.COM  *
18211963SAfshin.Ardakani@Sun.COM  * The fsid provides a system-wide unique file system ID.
18311963SAfshin.Ardakani@Sun.COM  * fsid.val[0] is the 32-bit dev for the file system of the share root
18411963SAfshin.Ardakani@Sun.COM  * smb_node.
18511963SAfshin.Ardakani@Sun.COM  * fsid.val[1] is the file system type.
18611963SAfshin.Ardakani@Sun.COM  */
18711963SAfshin.Ardakani@Sun.COM smb_sdrc_t
smb_com_trans2_query_fs_information(smb_request_t * sr,smb_xa_t * xa)18811963SAfshin.Ardakani@Sun.COM smb_com_trans2_query_fs_information(smb_request_t *sr, smb_xa_t *xa)
18911963SAfshin.Ardakani@Sun.COM {
19011963SAfshin.Ardakani@Sun.COM 	uint32_t		flags;
19111963SAfshin.Ardakani@Sun.COM 	char			*encode_str, *tmpbuf;
19211963SAfshin.Ardakani@Sun.COM 	uint64_t		max_int;
19311963SAfshin.Ardakani@Sun.COM 	uint16_t		infolev;
19411963SAfshin.Ardakani@Sun.COM 	int			rc, length, buflen;
19511963SAfshin.Ardakani@Sun.COM 	smb_tree_t		*tree;
19611963SAfshin.Ardakani@Sun.COM 	smb_node_t		*snode;
19711963SAfshin.Ardakani@Sun.COM 	char 			*fsname = "NTFS";
19811963SAfshin.Ardakani@Sun.COM 	fsid_t			fsid;
19911963SAfshin.Ardakani@Sun.COM 	smb_fssize_t		fssize;
20011963SAfshin.Ardakani@Sun.COM 	smb_msgbuf_t		mb;
20111963SAfshin.Ardakani@Sun.COM 
20211963SAfshin.Ardakani@Sun.COM 	tree = sr->tid_tree;
20311963SAfshin.Ardakani@Sun.COM 
20411963SAfshin.Ardakani@Sun.COM 	if (!STYPE_ISDSK(tree->t_res_type)) {
20511963SAfshin.Ardakani@Sun.COM 		smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
20611963SAfshin.Ardakani@Sun.COM 		    ERRDOS, ERROR_ACCESS_DENIED);
20711963SAfshin.Ardakani@Sun.COM 		return (SDRC_ERROR);
20811963SAfshin.Ardakani@Sun.COM 	}
20911963SAfshin.Ardakani@Sun.COM 
21011963SAfshin.Ardakani@Sun.COM 	if (smb_mbc_decodef(&xa->req_param_mb, "w", &infolev) != 0)
21111963SAfshin.Ardakani@Sun.COM 		return (SDRC_ERROR);
21211963SAfshin.Ardakani@Sun.COM 
21311963SAfshin.Ardakani@Sun.COM 	snode = tree->t_snode;
21411963SAfshin.Ardakani@Sun.COM 	fsid = SMB_NODE_FSID(snode);
21511963SAfshin.Ardakani@Sun.COM 
21611963SAfshin.Ardakani@Sun.COM 	switch (infolev) {
21711963SAfshin.Ardakani@Sun.COM 	case SMB_INFO_ALLOCATION:
21811963SAfshin.Ardakani@Sun.COM 		if (smb_fssize(sr, &fssize) != 0)
21911963SAfshin.Ardakani@Sun.COM 			return (SDRC_ERROR);
22011963SAfshin.Ardakani@Sun.COM 
22111963SAfshin.Ardakani@Sun.COM 		max_int = (uint64_t)UINT_MAX;
22211963SAfshin.Ardakani@Sun.COM 		if (fssize.fs_caller_units > max_int)
22311963SAfshin.Ardakani@Sun.COM 			fssize.fs_caller_units = max_int;
22411963SAfshin.Ardakani@Sun.COM 		if (fssize.fs_caller_avail > max_int)
22511963SAfshin.Ardakani@Sun.COM 			fssize.fs_caller_avail = max_int;
22611963SAfshin.Ardakani@Sun.COM 
22711963SAfshin.Ardakani@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_data_mb, "llllw",
22811963SAfshin.Ardakani@Sun.COM 		    0,
22911963SAfshin.Ardakani@Sun.COM 		    fssize.fs_sectors_per_unit,
23011963SAfshin.Ardakani@Sun.COM 		    fssize.fs_caller_units,
23111963SAfshin.Ardakani@Sun.COM 		    fssize.fs_caller_avail,
23211963SAfshin.Ardakani@Sun.COM 		    fssize.fs_bytes_per_sector);
23311963SAfshin.Ardakani@Sun.COM 		break;
23411963SAfshin.Ardakani@Sun.COM 
23511963SAfshin.Ardakani@Sun.COM 	case SMB_INFO_VOLUME:
23611963SAfshin.Ardakani@Sun.COM 		/*
23711963SAfshin.Ardakani@Sun.COM 		 * In this response, the unicode volume label is NOT
23811963SAfshin.Ardakani@Sun.COM 		 * expected to be aligned. Encode ('U') into a temporary
23911963SAfshin.Ardakani@Sun.COM 		 * buffer, then encode buffer as a byte stream ('#c').
24011963SAfshin.Ardakani@Sun.COM 		 */
24111963SAfshin.Ardakani@Sun.COM 		if ((sr->smb_flg2 & SMB_FLAGS2_UNICODE) ||
24211963SAfshin.Ardakani@Sun.COM 		    (sr->session->native_os == NATIVE_OS_WIN95)) {
24311963SAfshin.Ardakani@Sun.COM 			length = smb_wcequiv_strlen(tree->t_volume);
24411963SAfshin.Ardakani@Sun.COM 			buflen = length + sizeof (smb_wchar_t);
24511963SAfshin.Ardakani@Sun.COM 			tmpbuf = smb_srm_zalloc(sr, buflen);
24611963SAfshin.Ardakani@Sun.COM 			smb_msgbuf_init(&mb, (uint8_t *)tmpbuf, buflen,
24711963SAfshin.Ardakani@Sun.COM 			    SMB_MSGBUF_UNICODE);
24811963SAfshin.Ardakani@Sun.COM 			rc = smb_msgbuf_encode(&mb, "U", tree->t_volume);
24911963SAfshin.Ardakani@Sun.COM 			if (rc >= 0) {
25011963SAfshin.Ardakani@Sun.COM 				rc = smb_mbc_encodef(&xa->rep_data_mb,
25111963SAfshin.Ardakani@Sun.COM 				    "%lb#c", sr, fsid.val[0],
25211963SAfshin.Ardakani@Sun.COM 				    length, length, tmpbuf);
25311963SAfshin.Ardakani@Sun.COM 			}
25411963SAfshin.Ardakani@Sun.COM 			smb_msgbuf_term(&mb);
25511963SAfshin.Ardakani@Sun.COM 		} else {
25611963SAfshin.Ardakani@Sun.COM 			length = strlen(tree->t_volume);
25711963SAfshin.Ardakani@Sun.COM 			rc = smb_mbc_encodef(&xa->rep_data_mb, "%lbs", sr,
25811963SAfshin.Ardakani@Sun.COM 			    fsid.val[0], length, tree->t_volume);
25911963SAfshin.Ardakani@Sun.COM 		}
26011963SAfshin.Ardakani@Sun.COM 
26111963SAfshin.Ardakani@Sun.COM 		if (rc < 0)
26211963SAfshin.Ardakani@Sun.COM 			return (SDRC_ERROR);
26311963SAfshin.Ardakani@Sun.COM 		break;
26411963SAfshin.Ardakani@Sun.COM 
26511963SAfshin.Ardakani@Sun.COM 	case SMB_QUERY_FS_VOLUME_INFO:
26611963SAfshin.Ardakani@Sun.COM 	case SMB_FILE_FS_VOLUME_INFORMATION:
26711963SAfshin.Ardakani@Sun.COM 		if ((sr->smb_flg2 & SMB_FLAGS2_UNICODE) ||
26811963SAfshin.Ardakani@Sun.COM 		    (sr->session->native_os == NATIVE_OS_WIN95)) {
26911963SAfshin.Ardakani@Sun.COM 			length = smb_wcequiv_strlen(tree->t_volume);
27011963SAfshin.Ardakani@Sun.COM 			encode_str = "%qllb.U";
27111963SAfshin.Ardakani@Sun.COM 		} else {
27211963SAfshin.Ardakani@Sun.COM 			length = strlen(tree->t_volume);
27311963SAfshin.Ardakani@Sun.COM 			encode_str = "%qllb.s";
27411963SAfshin.Ardakani@Sun.COM 		}
27511963SAfshin.Ardakani@Sun.COM 
27611963SAfshin.Ardakani@Sun.COM 		/*
27711963SAfshin.Ardakani@Sun.COM 		 * NT has the "supports objects" flag set to 1.
27811963SAfshin.Ardakani@Sun.COM 		 */
27911963SAfshin.Ardakani@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_data_mb, encode_str, sr,
28011963SAfshin.Ardakani@Sun.COM 		    0ll,			/* Volume creation time */
28111963SAfshin.Ardakani@Sun.COM 		    fsid.val[0],		/* Volume serial number */
28211963SAfshin.Ardakani@Sun.COM 		    length,			/* label length */
28311963SAfshin.Ardakani@Sun.COM 		    0,				/* Supports objects */
28411963SAfshin.Ardakani@Sun.COM 		    tree->t_volume);
28511963SAfshin.Ardakani@Sun.COM 		break;
28611963SAfshin.Ardakani@Sun.COM 
28711963SAfshin.Ardakani@Sun.COM 	case SMB_QUERY_FS_SIZE_INFO:
28811963SAfshin.Ardakani@Sun.COM 	case SMB_FILE_FS_SIZE_INFORMATION:
28911963SAfshin.Ardakani@Sun.COM 		if (smb_fssize(sr, &fssize) != 0)
29011963SAfshin.Ardakani@Sun.COM 			return (SDRC_ERROR);
29111963SAfshin.Ardakani@Sun.COM 
29211963SAfshin.Ardakani@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_data_mb, "qqll",
29311963SAfshin.Ardakani@Sun.COM 		    fssize.fs_caller_units,
29411963SAfshin.Ardakani@Sun.COM 		    fssize.fs_caller_avail,
29511963SAfshin.Ardakani@Sun.COM 		    fssize.fs_sectors_per_unit,
29611963SAfshin.Ardakani@Sun.COM 		    fssize.fs_bytes_per_sector);
29711963SAfshin.Ardakani@Sun.COM 		break;
29811963SAfshin.Ardakani@Sun.COM 
29911963SAfshin.Ardakani@Sun.COM 	case SMB_QUERY_FS_DEVICE_INFO:
30011963SAfshin.Ardakani@Sun.COM 	case SMB_FILE_FS_DEVICE_INFORMATION:
30111963SAfshin.Ardakani@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_data_mb, "ll",
30211963SAfshin.Ardakani@Sun.COM 		    FILE_DEVICE_FILE_SYSTEM,
30311963SAfshin.Ardakani@Sun.COM 		    FILE_DEVICE_IS_MOUNTED);
30411963SAfshin.Ardakani@Sun.COM 		break;
30511963SAfshin.Ardakani@Sun.COM 
30611963SAfshin.Ardakani@Sun.COM 	case SMB_QUERY_FS_ATTRIBUTE_INFO:
30711963SAfshin.Ardakani@Sun.COM 	case SMB_FILE_FS_ATTRIBUTE_INFORMATION:
30811963SAfshin.Ardakani@Sun.COM 		if ((sr->smb_flg2 & SMB_FLAGS2_UNICODE) ||
30911963SAfshin.Ardakani@Sun.COM 		    (sr->session->native_os == NATIVE_OS_WINNT) ||
31011963SAfshin.Ardakani@Sun.COM 		    (sr->session->native_os == NATIVE_OS_WIN2000) ||
31111963SAfshin.Ardakani@Sun.COM 		    (sr->session->native_os == NATIVE_OS_WIN95) ||
31211963SAfshin.Ardakani@Sun.COM 		    (sr->session->native_os == NATIVE_OS_MACOS)) {
31311963SAfshin.Ardakani@Sun.COM 			length = smb_wcequiv_strlen(fsname);
31411963SAfshin.Ardakani@Sun.COM 			encode_str = "%lllU";
31511963SAfshin.Ardakani@Sun.COM 			sr->smb_flg2 |= SMB_FLAGS2_UNICODE;
31611963SAfshin.Ardakani@Sun.COM 		} else {
31711963SAfshin.Ardakani@Sun.COM 			length = strlen(fsname);
31811963SAfshin.Ardakani@Sun.COM 			encode_str = "%llls";
31911963SAfshin.Ardakani@Sun.COM 		}
32011963SAfshin.Ardakani@Sun.COM 
32111963SAfshin.Ardakani@Sun.COM 		flags = FILE_CASE_PRESERVED_NAMES;
32211963SAfshin.Ardakani@Sun.COM 
32311963SAfshin.Ardakani@Sun.COM 		if (tree->t_flags & SMB_TREE_UNICODE_ON_DISK)
32411963SAfshin.Ardakani@Sun.COM 			flags |= FILE_UNICODE_ON_DISK;
32511963SAfshin.Ardakani@Sun.COM 
32611963SAfshin.Ardakani@Sun.COM 		if (tree->t_flags & SMB_TREE_SUPPORTS_ACLS)
32711963SAfshin.Ardakani@Sun.COM 			flags |= FILE_PERSISTENT_ACLS;
32811963SAfshin.Ardakani@Sun.COM 
32911963SAfshin.Ardakani@Sun.COM 		if ((tree->t_flags & SMB_TREE_CASEINSENSITIVE) == 0)
33011963SAfshin.Ardakani@Sun.COM 			flags |= FILE_CASE_SENSITIVE_SEARCH;
33111963SAfshin.Ardakani@Sun.COM 
33211963SAfshin.Ardakani@Sun.COM 		if (tree->t_flags & SMB_TREE_STREAMS)
33311963SAfshin.Ardakani@Sun.COM 			flags |= FILE_NAMED_STREAMS;
33411963SAfshin.Ardakani@Sun.COM 
33511963SAfshin.Ardakani@Sun.COM 		if (tree->t_flags & SMB_TREE_QUOTA)
33611963SAfshin.Ardakani@Sun.COM 			flags |= FILE_VOLUME_QUOTAS;
33711963SAfshin.Ardakani@Sun.COM 
338*13082SJoyce.McIntosh@Sun.COM 		if (tree->t_flags & SMB_TREE_SPARSE)
339*13082SJoyce.McIntosh@Sun.COM 			flags |= FILE_SUPPORTS_SPARSE_FILES;
340*13082SJoyce.McIntosh@Sun.COM 
34111963SAfshin.Ardakani@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_data_mb, encode_str, sr,
34211963SAfshin.Ardakani@Sun.COM 		    flags,
34311963SAfshin.Ardakani@Sun.COM 		    MAXNAMELEN,	/* max name */
34411963SAfshin.Ardakani@Sun.COM 		    length,	/* label length */
34511963SAfshin.Ardakani@Sun.COM 		    fsname);
34611963SAfshin.Ardakani@Sun.COM 		break;
34711963SAfshin.Ardakani@Sun.COM 
34811963SAfshin.Ardakani@Sun.COM 	case SMB_FILE_FS_CONTROL_INFORMATION:
34911963SAfshin.Ardakani@Sun.COM 		if (!smb_tree_has_feature(sr->tid_tree, SMB_TREE_QUOTA)) {
35011963SAfshin.Ardakani@Sun.COM 			smbsr_error(sr, NT_STATUS_NOT_SUPPORTED,
35111963SAfshin.Ardakani@Sun.COM 			    ERRDOS, ERROR_NOT_SUPPORTED);
35211963SAfshin.Ardakani@Sun.COM 			return (SDRC_ERROR);
35311963SAfshin.Ardakani@Sun.COM 		}
35411963SAfshin.Ardakani@Sun.COM 
35511963SAfshin.Ardakani@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_data_mb, "qqqqqll",
35611963SAfshin.Ardakani@Sun.COM 		    0,		/* free space start filtering - MUST be 0 */
35711963SAfshin.Ardakani@Sun.COM 		    0,		/* free space threshold - MUST be 0 */
35811963SAfshin.Ardakani@Sun.COM 		    0,		/* free space stop filtering - MUST be 0 */
35911963SAfshin.Ardakani@Sun.COM 		    SMB_QUOTA_UNLIMITED,	/* default quota threshold */
36011963SAfshin.Ardakani@Sun.COM 		    SMB_QUOTA_UNLIMITED,	/* default quota limit */
36111963SAfshin.Ardakani@Sun.COM 		    FILE_VC_QUOTA_ENFORCE,	/* fs control flag */
36211963SAfshin.Ardakani@Sun.COM 		    0);				/* pad bytes */
36311963SAfshin.Ardakani@Sun.COM 		break;
36411963SAfshin.Ardakani@Sun.COM 
36511963SAfshin.Ardakani@Sun.COM 	case SMB_FILE_FS_FULLSIZE_INFORMATION:
36611963SAfshin.Ardakani@Sun.COM 		if (smb_fssize(sr, &fssize) != 0)
36711963SAfshin.Ardakani@Sun.COM 			return (SDRC_ERROR);
36811963SAfshin.Ardakani@Sun.COM 
36911963SAfshin.Ardakani@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_data_mb, "qqqll",
37011963SAfshin.Ardakani@Sun.COM 		    fssize.fs_caller_units,
37111963SAfshin.Ardakani@Sun.COM 		    fssize.fs_caller_avail,
37211963SAfshin.Ardakani@Sun.COM 		    fssize.fs_volume_avail,
37311963SAfshin.Ardakani@Sun.COM 		    fssize.fs_sectors_per_unit,
37411963SAfshin.Ardakani@Sun.COM 		    fssize.fs_bytes_per_sector);
37511963SAfshin.Ardakani@Sun.COM 		break;
37611963SAfshin.Ardakani@Sun.COM 
37711963SAfshin.Ardakani@Sun.COM 	case SMB_FILE_FS_LABEL_INFORMATION:
37811963SAfshin.Ardakani@Sun.COM 	case SMB_FILE_FS_OBJECTID_INFORMATION:
37911963SAfshin.Ardakani@Sun.COM 	case SMB_FILE_FS_DRIVERPATH_INFORMATION:
38011963SAfshin.Ardakani@Sun.COM 		smbsr_error(sr, NT_STATUS_NOT_SUPPORTED,
38111963SAfshin.Ardakani@Sun.COM 		    ERRDOS, ERROR_NOT_SUPPORTED);
38211963SAfshin.Ardakani@Sun.COM 		return (SDRC_ERROR);
38311963SAfshin.Ardakani@Sun.COM 
38411963SAfshin.Ardakani@Sun.COM 	default:
38511963SAfshin.Ardakani@Sun.COM 		smbsr_error(sr, NT_STATUS_INVALID_LEVEL,
38611963SAfshin.Ardakani@Sun.COM 		    ERRDOS, ERROR_INVALID_LEVEL);
38711963SAfshin.Ardakani@Sun.COM 		return (SDRC_ERROR);
38811963SAfshin.Ardakani@Sun.COM 	}
38911963SAfshin.Ardakani@Sun.COM 
39011963SAfshin.Ardakani@Sun.COM 	return (SDRC_SUCCESS);
39111963SAfshin.Ardakani@Sun.COM }
39211963SAfshin.Ardakani@Sun.COM 
39311963SAfshin.Ardakani@Sun.COM /*
39411963SAfshin.Ardakani@Sun.COM  * smb_fssize
39511963SAfshin.Ardakani@Sun.COM  *
39611963SAfshin.Ardakani@Sun.COM  * File system size information, for the volume and for the user
39711963SAfshin.Ardakani@Sun.COM  * initiating the request.
39811963SAfshin.Ardakani@Sun.COM  *
39911963SAfshin.Ardakani@Sun.COM  * If there's no quota entry for the user initiating the request,
40011963SAfshin.Ardakani@Sun.COM  * caller_units and caller_avail are the total and available units
40111963SAfshin.Ardakani@Sun.COM  * for the volume (volume_units, volume_avail).
40211963SAfshin.Ardakani@Sun.COM  * If there is a quota entry for the user initiating the request,
40311963SAfshin.Ardakani@Sun.COM  * and it is not SMB_QUOTA_UNLIMITED, calculate caller_units and
40411963SAfshin.Ardakani@Sun.COM  * caller_avail as follows:
40511963SAfshin.Ardakani@Sun.COM  *   caller_units = quota limit / bytes_per_unit
40611963SAfshin.Ardakani@Sun.COM  *   caller_avail = remaining quota / bytes_per_unit
40711963SAfshin.Ardakani@Sun.COM  *
40811963SAfshin.Ardakani@Sun.COM  * A quota limit of SMB_QUOTA_UNLIMITED means that the user's quota
40911963SAfshin.Ardakani@Sun.COM  * is specfied as unlimited. A quota limit of 0 means there is no
41011963SAfshin.Ardakani@Sun.COM  * quota specified for the user.
41111963SAfshin.Ardakani@Sun.COM  *
41211963SAfshin.Ardakani@Sun.COM  * Returns: 0 - success
41311963SAfshin.Ardakani@Sun.COM  *         -1 - error. Error status set in sr.
41411963SAfshin.Ardakani@Sun.COM  */
41511963SAfshin.Ardakani@Sun.COM static int
smb_fssize(smb_request_t * sr,smb_fssize_t * fssize)41611963SAfshin.Ardakani@Sun.COM smb_fssize(smb_request_t *sr, smb_fssize_t *fssize)
41711963SAfshin.Ardakani@Sun.COM {
41811963SAfshin.Ardakani@Sun.COM 	smb_node_t *node;
41911963SAfshin.Ardakani@Sun.COM 	struct statvfs64 df;
42011963SAfshin.Ardakani@Sun.COM 	uid_t uid;
42111963SAfshin.Ardakani@Sun.COM 	smb_quota_t quota;
42211963SAfshin.Ardakani@Sun.COM 	int rc, bytes_per_unit;
42311963SAfshin.Ardakani@Sun.COM 
42411963SAfshin.Ardakani@Sun.COM 	bzero(fssize, sizeof (smb_fssize_t));
42511963SAfshin.Ardakani@Sun.COM 	node = sr->tid_tree->t_snode;
42611963SAfshin.Ardakani@Sun.COM 	if ((rc = smb_fsop_statfs(sr->user_cr, node, &df)) != 0) {
42711963SAfshin.Ardakani@Sun.COM 		smbsr_errno(sr, rc);
42811963SAfshin.Ardakani@Sun.COM 		return (-1);
42911963SAfshin.Ardakani@Sun.COM 	}
43011963SAfshin.Ardakani@Sun.COM 
43111963SAfshin.Ardakani@Sun.COM 	fssize->fs_bytes_per_sector = 512;
43211963SAfshin.Ardakani@Sun.COM 	fssize->fs_sectors_per_unit = df.f_frsize >> 9;
43311963SAfshin.Ardakani@Sun.COM 	if (df.f_bavail > df.f_blocks)
43411963SAfshin.Ardakani@Sun.COM 		df.f_bavail = 0;
43511963SAfshin.Ardakani@Sun.COM 
43611963SAfshin.Ardakani@Sun.COM 	fssize->fs_volume_units = df.f_blocks;
43711963SAfshin.Ardakani@Sun.COM 	fssize->fs_volume_avail = df.f_bavail;
43811963SAfshin.Ardakani@Sun.COM 	fssize->fs_caller_units = df.f_blocks;
43911963SAfshin.Ardakani@Sun.COM 	fssize->fs_caller_avail = df.f_bavail;
44011963SAfshin.Ardakani@Sun.COM 	bytes_per_unit =
44111963SAfshin.Ardakani@Sun.COM 	    fssize->fs_bytes_per_sector * fssize->fs_sectors_per_unit;
44211963SAfshin.Ardakani@Sun.COM 
44311963SAfshin.Ardakani@Sun.COM 	if (!smb_tree_has_feature(sr->tid_tree, SMB_TREE_QUOTA))
44411963SAfshin.Ardakani@Sun.COM 		return (0);
44511963SAfshin.Ardakani@Sun.COM 
44611963SAfshin.Ardakani@Sun.COM 	uid = crgetuid(sr->uid_user->u_cred);
44711963SAfshin.Ardakani@Sun.COM 	if (smb_quota_query_user_quota(sr, uid, &quota) != NT_STATUS_SUCCESS)
44811963SAfshin.Ardakani@Sun.COM 		return (0);
44911963SAfshin.Ardakani@Sun.COM 
45011963SAfshin.Ardakani@Sun.COM 	if ((quota.q_limit != SMB_QUOTA_UNLIMITED) && (quota.q_limit != 0)) {
45111963SAfshin.Ardakani@Sun.COM 		fssize->fs_caller_units = quota.q_limit / bytes_per_unit;
45211963SAfshin.Ardakani@Sun.COM 		if (quota.q_limit <= quota.q_used)
45311963SAfshin.Ardakani@Sun.COM 			fssize->fs_caller_avail = 0;
45411963SAfshin.Ardakani@Sun.COM 		else
45511963SAfshin.Ardakani@Sun.COM 			fssize->fs_caller_avail =
45611963SAfshin.Ardakani@Sun.COM 			    (quota.q_limit - quota.q_used) / bytes_per_unit;
45711963SAfshin.Ardakani@Sun.COM 	}
45811963SAfshin.Ardakani@Sun.COM 
45911963SAfshin.Ardakani@Sun.COM 	return (0);
46011963SAfshin.Ardakani@Sun.COM }
46111963SAfshin.Ardakani@Sun.COM 
46211963SAfshin.Ardakani@Sun.COM /*
46311963SAfshin.Ardakani@Sun.COM  * smb_com_trans2_set_fs_information
46411963SAfshin.Ardakani@Sun.COM  *
46511963SAfshin.Ardakani@Sun.COM  * This transaction sets filesystem information.
46611963SAfshin.Ardakani@Sun.COM  * The following information levels are supported:
46711963SAfshin.Ardakani@Sun.COM  *
46811963SAfshin.Ardakani@Sun.COM  *  InformationLevel               	Value
46911963SAfshin.Ardakani@Sun.COM  *  ==================================  ======
47011963SAfshin.Ardakani@Sun.COM  *  SMB_FILE_FS_CONTROL_INFORMATION	1006
47111963SAfshin.Ardakani@Sun.COM  */
47211963SAfshin.Ardakani@Sun.COM smb_sdrc_t
smb_com_trans2_set_fs_information(smb_request_t * sr,smb_xa_t * xa)47311963SAfshin.Ardakani@Sun.COM smb_com_trans2_set_fs_information(smb_request_t *sr, smb_xa_t *xa)
47411963SAfshin.Ardakani@Sun.COM {
47511963SAfshin.Ardakani@Sun.COM 	smb_tree_t		*tree;
47611963SAfshin.Ardakani@Sun.COM 	uint16_t		infolev;
47711963SAfshin.Ardakani@Sun.COM 
47811963SAfshin.Ardakani@Sun.COM 	tree = sr->tid_tree;
47911963SAfshin.Ardakani@Sun.COM 	if (!STYPE_ISDSK(tree->t_res_type)) {
48011963SAfshin.Ardakani@Sun.COM 		smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
48111963SAfshin.Ardakani@Sun.COM 		    ERRDOS, ERROR_ACCESS_DENIED);
48211963SAfshin.Ardakani@Sun.COM 		return (SDRC_ERROR);
48311963SAfshin.Ardakani@Sun.COM 	}
48411963SAfshin.Ardakani@Sun.COM 
48511963SAfshin.Ardakani@Sun.COM 	if (smb_mbc_decodef(&xa->req_param_mb, "ww",
48611963SAfshin.Ardakani@Sun.COM 	    &sr->smb_fid, &infolev) != 0)
48711963SAfshin.Ardakani@Sun.COM 		return (SDRC_ERROR);
48811963SAfshin.Ardakani@Sun.COM 
48911963SAfshin.Ardakani@Sun.COM 	switch (infolev) {
49011963SAfshin.Ardakani@Sun.COM 	case SMB_FILE_FS_CONTROL_INFORMATION:
49111963SAfshin.Ardakani@Sun.COM 		if (smb_trans2_set_fs_ctrl_info(sr, xa) != 0)
49211963SAfshin.Ardakani@Sun.COM 			return (SDRC_ERROR);
49311963SAfshin.Ardakani@Sun.COM 		break;
49411963SAfshin.Ardakani@Sun.COM 
49511963SAfshin.Ardakani@Sun.COM 	case SMB_FILE_FS_VOLUME_INFORMATION:
49611963SAfshin.Ardakani@Sun.COM 	case SMB_FILE_FS_LABEL_INFORMATION:
49711963SAfshin.Ardakani@Sun.COM 	case SMB_FILE_FS_SIZE_INFORMATION:
49811963SAfshin.Ardakani@Sun.COM 	case SMB_FILE_FS_DEVICE_INFORMATION:
49911963SAfshin.Ardakani@Sun.COM 	case SMB_FILE_FS_ATTRIBUTE_INFORMATION:
50011963SAfshin.Ardakani@Sun.COM 	case SMB_FILE_FS_FULLSIZE_INFORMATION:
50111963SAfshin.Ardakani@Sun.COM 	case SMB_FILE_FS_OBJECTID_INFORMATION:
50211963SAfshin.Ardakani@Sun.COM 	case SMB_FILE_FS_DRIVERPATH_INFORMATION:
50311963SAfshin.Ardakani@Sun.COM 		smbsr_error(sr, NT_STATUS_NOT_SUPPORTED,
50411963SAfshin.Ardakani@Sun.COM 		    ERRDOS, ERROR_NOT_SUPPORTED);
50511963SAfshin.Ardakani@Sun.COM 		return (SDRC_ERROR);
50611963SAfshin.Ardakani@Sun.COM 
50711963SAfshin.Ardakani@Sun.COM 	default:
50811963SAfshin.Ardakani@Sun.COM 		smbsr_error(sr, NT_STATUS_INVALID_LEVEL,
50911963SAfshin.Ardakani@Sun.COM 		    ERRDOS, ERROR_INVALID_LEVEL);
51011963SAfshin.Ardakani@Sun.COM 		return (SDRC_ERROR);
51111963SAfshin.Ardakani@Sun.COM 	}
51211963SAfshin.Ardakani@Sun.COM 
51311963SAfshin.Ardakani@Sun.COM 	return (SDRC_SUCCESS);
51411963SAfshin.Ardakani@Sun.COM }
51511963SAfshin.Ardakani@Sun.COM 
51611963SAfshin.Ardakani@Sun.COM /*
51711963SAfshin.Ardakani@Sun.COM  * smb_trans2_set_fs_ctrl_info
51811963SAfshin.Ardakani@Sun.COM  *
51911963SAfshin.Ardakani@Sun.COM  * Only users with Admin privileges (i.e. of the BUILTIN/Administrators
52011963SAfshin.Ardakani@Sun.COM  * group) will be allowed to set quotas.
52111963SAfshin.Ardakani@Sun.COM  *
52211963SAfshin.Ardakani@Sun.COM  * Currently QUOTAS are always ENFORCED and the default values
52311963SAfshin.Ardakani@Sun.COM  * are always SMB_QUOTA_UNLIMITED (none). Any attempt to set
52411963SAfshin.Ardakani@Sun.COM  * values other than these will result in NT_STATUS_NOT_SUPPORTED.
52511963SAfshin.Ardakani@Sun.COM  */
52611963SAfshin.Ardakani@Sun.COM static int
smb_trans2_set_fs_ctrl_info(smb_request_t * sr,smb_xa_t * xa)52711963SAfshin.Ardakani@Sun.COM smb_trans2_set_fs_ctrl_info(smb_request_t *sr, smb_xa_t *xa)
52811963SAfshin.Ardakani@Sun.COM {
52911963SAfshin.Ardakani@Sun.COM 	int rc;
53011963SAfshin.Ardakani@Sun.COM 	uint64_t fstart, fthresh, fstop, qthresh, qlimit;
53111963SAfshin.Ardakani@Sun.COM 	uint32_t qctrl, qpad;
53211963SAfshin.Ardakani@Sun.COM 
53311963SAfshin.Ardakani@Sun.COM 	if (!smb_tree_has_feature(sr->tid_tree, SMB_TREE_QUOTA)) {
53411963SAfshin.Ardakani@Sun.COM 		smbsr_error(sr, NT_STATUS_NOT_SUPPORTED,
53511963SAfshin.Ardakani@Sun.COM 		    ERRDOS, ERROR_NOT_SUPPORTED);
53611963SAfshin.Ardakani@Sun.COM 		return (-1);
53711963SAfshin.Ardakani@Sun.COM 	}
53811963SAfshin.Ardakani@Sun.COM 
53911963SAfshin.Ardakani@Sun.COM 	if (!smb_user_is_admin(sr->uid_user)) {
54011963SAfshin.Ardakani@Sun.COM 		smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
54111963SAfshin.Ardakani@Sun.COM 		    ERRDOS, ERROR_ACCESS_DENIED);
54211963SAfshin.Ardakani@Sun.COM 		return (-1);
54311963SAfshin.Ardakani@Sun.COM 	}
54411963SAfshin.Ardakani@Sun.COM 
54511963SAfshin.Ardakani@Sun.COM 	rc = smb_mbc_decodef(&xa->req_data_mb, "qqqqqll", &fstart,
54611963SAfshin.Ardakani@Sun.COM 	    &fthresh, &fstop, &qthresh, &qlimit, &qctrl, &qpad);
54711963SAfshin.Ardakani@Sun.COM 
54811963SAfshin.Ardakani@Sun.COM 	if ((rc != 0) || (fstart != 0) || (fthresh != 0) || (fstop != 0)) {
54911963SAfshin.Ardakani@Sun.COM 		smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
55011963SAfshin.Ardakani@Sun.COM 		    ERRDOS, ERROR_INVALID_PARAMETER);
55111963SAfshin.Ardakani@Sun.COM 		return (-1);
55211963SAfshin.Ardakani@Sun.COM 	}
55311963SAfshin.Ardakani@Sun.COM 
55411963SAfshin.Ardakani@Sun.COM 	/* Only support ENFORCED quotas with UNLIMITED default */
55511963SAfshin.Ardakani@Sun.COM 	if ((qctrl != FILE_VC_QUOTA_ENFORCE) ||
55611963SAfshin.Ardakani@Sun.COM 	    (qlimit != SMB_QUOTA_UNLIMITED) ||
55711963SAfshin.Ardakani@Sun.COM 	    (qthresh != SMB_QUOTA_UNLIMITED)) {
55811963SAfshin.Ardakani@Sun.COM 		smbsr_error(sr, NT_STATUS_NOT_SUPPORTED,
55911963SAfshin.Ardakani@Sun.COM 		    ERRDOS, ERROR_NOT_SUPPORTED);
56011963SAfshin.Ardakani@Sun.COM 		return (-1);
56111963SAfshin.Ardakani@Sun.COM 	}
56211963SAfshin.Ardakani@Sun.COM 
56311963SAfshin.Ardakani@Sun.COM 	return (0);
56411963SAfshin.Ardakani@Sun.COM }
565