* Makefile.in (DLL_OFILES): Add quotactl.o.
* common.din (quotactl): Export. * ntdll.h: Define FILE_FS_CONTROL_INFORMATION::FileSystemControlFlags flag values. (struct _FILE_FS_CONTROL_INFORMATION): Define. (struct _FILE_GET_QUOTA_INFORMATION): Define. (typedef struct _FILE_QUOTA_INFORMATION): Define. (NtQueryObject): Use PVOID rather than VOID*. (NtQueryVolumeInformationFile): Ditto. (NtQueryQuotaInformationFile): Declare. (NtSetQuotaInformationFile): Declare. (NtSetVolumeInformationFile): Declare. * quotactl.cc: New file implementing quotactl(). * include/sys/mount.h (BLOCK_SIZE): Define. (BLOCK_SIZE_BITS): Define. * include/sys/quota.h: New header. * include/cygwin/version.h (CYGWIN_VERSION_API_MINOR): Bump.
This commit is contained in:
		| @@ -1,3 +1,23 @@ | ||||
| 2014-10-16  Corinna Vinschen  <corinna@vinschen.de> | ||||
|  | ||||
| 	* Makefile.in (DLL_OFILES): Add quotactl.o. | ||||
| 	* common.din (quotactl): Export. | ||||
| 	* ntdll.h: Define FILE_FS_CONTROL_INFORMATION::FileSystemControlFlags | ||||
| 	flag values. | ||||
| 	(struct _FILE_FS_CONTROL_INFORMATION): Define. | ||||
| 	(struct _FILE_GET_QUOTA_INFORMATION): Define. | ||||
| 	(typedef struct _FILE_QUOTA_INFORMATION): Define. | ||||
| 	(NtQueryObject): Use PVOID rather than VOID*. | ||||
| 	(NtQueryVolumeInformationFile): Ditto. | ||||
| 	(NtQueryQuotaInformationFile): Declare. | ||||
| 	(NtSetQuotaInformationFile): Declare. | ||||
| 	(NtSetVolumeInformationFile): Declare. | ||||
| 	* quotactl.cc: New file implementing quotactl(). | ||||
| 	* include/sys/mount.h (BLOCK_SIZE): Define. | ||||
| 	(BLOCK_SIZE_BITS): Define. | ||||
| 	* include/sys/quota.h: New header. | ||||
| 	* include/cygwin/version.h (CYGWIN_VERSION_API_MINOR): Bump. | ||||
|  | ||||
| 2014-10-16  Corinna Vinschen  <corinna@vinschen.de> | ||||
|  | ||||
| 	* Makefile.in (DLL_OFILES): Rearrange with one file per line. | ||||
|   | ||||
| @@ -252,6 +252,7 @@ DLL_OFILES:= \ | ||||
| 	posix_ipc.o \ | ||||
| 	pseudo-reloc.o \ | ||||
| 	pthread.o \ | ||||
| 	quotactl.o \ | ||||
| 	random.o \ | ||||
| 	regcomp.o \ | ||||
| 	regerror.o \ | ||||
|   | ||||
| @@ -920,6 +920,7 @@ putwc SIGFE | ||||
| putwchar SIGFE | ||||
| pwrite SIGFE | ||||
| qsort NOSIGFE | ||||
| quotactl SIGFE | ||||
| raise SIGFE | ||||
| rand NOSIGFE | ||||
| rand_r NOSIGFE | ||||
|   | ||||
| @@ -453,12 +453,13 @@ details. */ | ||||
| 	   CW_CYGNAME_FROM_WINNAME. | ||||
|       276: Export ffsl, ffsll. | ||||
|       277: Add setsockopt(SO_PEERCRED). | ||||
|       278: Add quotactl. | ||||
|      */ | ||||
|  | ||||
|      /* Note that we forgot to bump the api for ualarm, strtoll, strtoull */ | ||||
|  | ||||
| #define CYGWIN_VERSION_API_MAJOR 0 | ||||
| #define CYGWIN_VERSION_API_MINOR 277 | ||||
| #define CYGWIN_VERSION_API_MINOR 278 | ||||
|  | ||||
|      /* There is also a compatibity version number associated with the | ||||
| 	shared memory regions.  It is incremented when incompatible | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* sys/mount.h | ||||
|  | ||||
|    Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2008, 2009, 2010, 2012 | ||||
|    Red Hat, Inc. | ||||
|    Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2008, 2009, 2010, 2012, | ||||
|    2014 Red Hat, Inc. | ||||
|  | ||||
| This file is part of Cygwin. | ||||
|  | ||||
| @@ -12,6 +12,9 @@ details. */ | ||||
| #ifndef _SYS_MOUNT_H | ||||
| #define _SYS_MOUNT_H | ||||
|  | ||||
| #define BLOCK_SIZE 1024 | ||||
| #define BLOCK_SIZE_BITS	10 | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|   | ||||
							
								
								
									
										239
									
								
								winsup/cygwin/include/sys/quota.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										239
									
								
								winsup/cygwin/include/sys/quota.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,239 @@ | ||||
| /* Copyright (c) 1982, 1986 Regents of the University of California. | ||||
|  * All rights reserved. | ||||
|  * | ||||
|  * This code is derived from software contributed to Berkeley by | ||||
|  * Robert Elz at The University of Melbourne. | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions | ||||
|  * are met: | ||||
|  * 1. Redistributions of source code must retain the above copyright | ||||
|  *    notice, this list of conditions and the following disclaimer. | ||||
|  * 2. Redistributions in binary form must reproduce the above copyright | ||||
|  *    notice, this list of conditions and the following disclaimer in the | ||||
|  *    documentation and/or other materials provided with the distribution. | ||||
|  * 4. Neither the name of the University nor the names of its contributors | ||||
|  *    may be used to endorse or promote products derived from this software | ||||
|  *    without specific prior written permission. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | ||||
|  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||
|  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||
|  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||||
|  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||||
|  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||||
|  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
|  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||||
|  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||||
|  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||||
|  * SUCH DAMAGE. | ||||
|  */ | ||||
|  | ||||
| #ifndef _SYS_QUOTA_H | ||||
| #define _SYS_QUOTA_H 1 | ||||
|  | ||||
| #include <features.h> | ||||
| #include <sys/types.h> | ||||
|  | ||||
| /* This file is copied from Linux and kept verbatim, except for the below | ||||
|    Cygwin-specific blocks. */ | ||||
|  | ||||
| #ifdef __CYGWIN__ | ||||
| /* On Linux these defines live in <linux/quota.h>.  Move them here for easier | ||||
|    access. */ | ||||
| /* Quota format type IDs */ | ||||
| #define QFMT_VFS_OLD 1 | ||||
| #define QFMT_VFS_V0 2 | ||||
| #define QFMT_OCFS2 3 | ||||
| #define QFMT_VFS_V1 4 | ||||
| #endif | ||||
|  | ||||
| /* | ||||
|  * Select between different incompatible quota versions. | ||||
|  * Default to the version used by Linux kernel version 2.4.22 | ||||
|  * or later.  */ | ||||
| #ifndef _LINUX_QUOTA_VERSION | ||||
| # define _LINUX_QUOTA_VERSION 2 | ||||
| #endif | ||||
|  | ||||
| #if defined (__CYGWIN__) && _LINUX_QUOTA_VERSION != 2 | ||||
| #error Cygwin only supports quota version 2. | ||||
| #endif | ||||
|  | ||||
| /* | ||||
|  * Convert diskblocks to blocks and the other way around. | ||||
|  * currently only to fool the BSD source. :-) | ||||
|  */ | ||||
| #define dbtob(num) ((num) << 10) | ||||
| #define btodb(num) ((num) >> 10) | ||||
|  | ||||
| /* | ||||
|  * Convert count of filesystem blocks to diskquota blocks, meant | ||||
|  * for filesystems where i_blksize != BLOCK_SIZE | ||||
|  */ | ||||
| #define fs_to_dq_blocks(num, blksize) (((num) * (blksize)) / BLOCK_SIZE) | ||||
|  | ||||
| /* | ||||
|  * Definitions for disk quotas imposed on the average user | ||||
|  * (big brother finally hits Linux). | ||||
|  * | ||||
|  * The following constants define the amount of time given a user | ||||
|  * before the soft limits are treated as hard limits (usually resulting | ||||
|  * in an allocation failure). The timer is started when the user crosses | ||||
|  * their soft limit, it is reset when they go below their soft limit. | ||||
|  */ | ||||
| #define MAX_IQ_TIME  604800	/* (7*24*60*60) 1 week */ | ||||
| #define MAX_DQ_TIME  604800	/* (7*24*60*60) 1 week */ | ||||
|  | ||||
| #define MAXQUOTAS 2 | ||||
| #define USRQUOTA  0		/* element used for user quotas */ | ||||
| #define GRPQUOTA  1		/* element used for group quotas */ | ||||
|  | ||||
| /* | ||||
|  * Definitions for the default names of the quotas files. | ||||
|  */ | ||||
| #define INITQFNAMES { \ | ||||
|    "user",      /* USRQUOTA */ \ | ||||
|    "group",   /* GRPQUOTA */ \ | ||||
|    "undefined", \ | ||||
| }; | ||||
|  | ||||
| #define QUOTAFILENAME "quota" | ||||
| #define QUOTAGROUP "staff" | ||||
|  | ||||
| #define NR_DQHASH 43          /* Just an arbitrary number any suggestions ? */ | ||||
| #define NR_DQUOTS 256         /* Number of quotas active at one time */ | ||||
|  | ||||
| /* | ||||
|  * Command definitions for the 'quotactl' system call. | ||||
|  * The commands are broken into a main command defined below | ||||
|  * and a subcommand that is used to convey the type of | ||||
|  * quota that is being manipulated (see above). | ||||
|  */ | ||||
| #define SUBCMDMASK  0x00ff | ||||
| #define SUBCMDSHIFT 8 | ||||
| #define QCMD(cmd, type)  (((cmd) << SUBCMDSHIFT) | ((type) & SUBCMDMASK)) | ||||
|  | ||||
| #if _LINUX_QUOTA_VERSION < 2 | ||||
| # define Q_QUOTAON  0x0100	/* enable quotas */ | ||||
| # define Q_QUOTAOFF 0x0200	/* disable quotas */ | ||||
| # define Q_GETQUOTA 0x0300	/* get limits and usage */ | ||||
| # define Q_SETQUOTA 0x0400	/* set limits and usage */ | ||||
| # define Q_SETUSE   0x0500	/* set usage */ | ||||
| # define Q_SYNC     0x0600	/* sync disk copy of a filesystems quotas */ | ||||
| # define Q_SETQLIM  0x0700	/* set limits */ | ||||
| # define Q_GETSTATS 0x0800	/* get collected stats */ | ||||
| # define Q_RSQUASH  0x1000	/* set root_squash option */ | ||||
| #else | ||||
| # define Q_SYNC     0x800001	/* sync disk copy of a filesystems quotas */ | ||||
| # define Q_QUOTAON  0x800002	/* turn quotas on */ | ||||
| # define Q_QUOTAOFF 0x800003	/* turn quotas off */ | ||||
| # define Q_GETFMT   0x800004	/* get quota format used on given filesystem */ | ||||
| # define Q_GETINFO  0x800005	/* get information about quota files */ | ||||
| # define Q_SETINFO  0x800006	/* set information about quota files */ | ||||
| # define Q_GETQUOTA 0x800007	/* get user quota structure */ | ||||
| # define Q_SETQUOTA 0x800008	/* set user quota structure */ | ||||
| #endif | ||||
|  | ||||
| /* | ||||
|  * The following structure defines the format of the disk quota file | ||||
|  * (as it appears on disk) - the file is an array of these structures | ||||
|  * indexed by user or group number. | ||||
|  */ | ||||
| #if _LINUX_QUOTA_VERSION < 2 | ||||
| struct dqblk | ||||
|   { | ||||
|     u_int32_t dqb_bhardlimit;	/* absolute limit on disk blks alloc */ | ||||
|     u_int32_t dqb_bsoftlimit;	/* preferred limit on disk blks */ | ||||
|     u_int32_t dqb_curblocks;	/* current block count */ | ||||
|     u_int32_t dqb_ihardlimit;	/* maximum # allocated inodes */ | ||||
|     u_int32_t dqb_isoftlimit;	/* preferred inode limit */ | ||||
|     u_int32_t dqb_curinodes;	/* current # allocated inodes */ | ||||
|     time_t dqb_btime;		/* time limit for excessive disk use */ | ||||
|     time_t dqb_itime;		/* time limit for excessive files */ | ||||
|   }; | ||||
| #else | ||||
|  | ||||
| /* Flags that indicate which fields in dqblk structure are valid.  */ | ||||
| #define QIF_BLIMITS	1 | ||||
| #define QIF_SPACE	2 | ||||
| #define QIF_ILIMITS	4 | ||||
| #define QIF_INODES	8 | ||||
| #define QIF_BTIME	16 | ||||
| #define QIF_ITIME	32 | ||||
| #define QIF_LIMITS	(QIF_BLIMITS | QIF_ILIMITS) | ||||
| #define QIF_USAGE	(QIF_SPACE | QIF_INODES) | ||||
| #define QIF_TIMES	(QIF_BTIME | QIF_ITIME) | ||||
| #define QIF_ALL		(QIF_LIMITS | QIF_USAGE | QIF_TIMES) | ||||
|  | ||||
| struct dqblk | ||||
|   { | ||||
|     u_int64_t dqb_bhardlimit;	/* absolute limit on disk quota blocks alloc */ | ||||
|     u_int64_t dqb_bsoftlimit;	/* preferred limit on disk quota blocks */ | ||||
|     u_int64_t dqb_curspace;	/* current quota block count */ | ||||
|     u_int64_t dqb_ihardlimit;	/* maximum # allocated inodes */ | ||||
|     u_int64_t dqb_isoftlimit;	/* preferred inode limit */ | ||||
|     u_int64_t dqb_curinodes;	/* current # allocated inodes */ | ||||
|     u_int64_t dqb_btime;	/* time limit for excessive disk use */ | ||||
|     u_int64_t dqb_itime;	/* time limit for excessive files */ | ||||
|     u_int32_t dqb_valid;	/* bitmask of QIF_* constants */ | ||||
|   }; | ||||
| #endif | ||||
|  | ||||
| /* | ||||
|  * Shorthand notation. | ||||
|  */ | ||||
| #define	dq_bhardlimit	dq_dqb.dqb_bhardlimit | ||||
| #define	dq_bsoftlimit	dq_dqb.dqb_bsoftlimit | ||||
| #if _LINUX_QUOTA_VERSION < 2 | ||||
| # define dq_curblocks	dq_dqb.dqb_curblocks | ||||
| #else | ||||
| # define dq_curspace	dq_dqb.dqb_curspace | ||||
| # define dq_valid	dq_dqb.dqb_valid | ||||
| #endif | ||||
| #define	dq_ihardlimit	dq_dqb.dqb_ihardlimit | ||||
| #define	dq_isoftlimit	dq_dqb.dqb_isoftlimit | ||||
| #define	dq_curinodes	dq_dqb.dqb_curinodes | ||||
| #define	dq_btime	dq_dqb.dqb_btime | ||||
| #define	dq_itime	dq_dqb.dqb_itime | ||||
|  | ||||
| #define dqoff(UID)      ((loff_t)((UID) * sizeof (struct dqblk))) | ||||
|  | ||||
| #if _LINUX_QUOTA_VERSION < 2 | ||||
| struct dqstats | ||||
|   { | ||||
|     u_int32_t lookups; | ||||
|     u_int32_t drops; | ||||
|     u_int32_t reads; | ||||
|     u_int32_t writes; | ||||
|     u_int32_t cache_hits; | ||||
|     u_int32_t pages_allocated; | ||||
|     u_int32_t allocated_dquots; | ||||
|     u_int32_t free_dquots; | ||||
|     u_int32_t syncs; | ||||
|   }; | ||||
| #else | ||||
|  | ||||
| /* Flags that indicate which fields in dqinfo structure are valid.  */ | ||||
| # define IIF_BGRACE	1 | ||||
| # define IIF_IGRACE	2 | ||||
| # define IIF_FLAGS	4 | ||||
| # define IIF_ALL	(IIF_BGRACE | IIF_IGRACE | IIF_FLAGS) | ||||
|  | ||||
| struct dqinfo | ||||
|   { | ||||
|     u_int64_t dqi_bgrace; | ||||
|     u_int64_t dqi_igrace; | ||||
|     u_int32_t dqi_flags; | ||||
|     u_int32_t dqi_valid; | ||||
|   }; | ||||
| #endif | ||||
|  | ||||
| __BEGIN_DECLS | ||||
|  | ||||
| extern int quotactl (int __cmd, const char *__special, int __id, | ||||
| 		     caddr_t __addr) __THROW; | ||||
|  | ||||
| __END_DECLS | ||||
|  | ||||
| #endif /* sys/quota.h */ | ||||
| @@ -143,6 +143,19 @@ | ||||
| #define HEAP_FLAG_EXECUTABLE	   0x40000 | ||||
| #define HEAP_FLAG_DEBUGGED	0x40000000 | ||||
|  | ||||
| #define FILE_VC_QUOTA_NONE              0x00000000 | ||||
| #define FILE_VC_QUOTA_TRACK             0x00000001 | ||||
| #define FILE_VC_QUOTA_ENFORCE           0x00000002 | ||||
| #define FILE_VC_QUOTA_MASK              0x00000003 | ||||
| #define FILE_VC_CONTENT_INDEX_DISABLED  0x00000008 | ||||
| #define FILE_VC_LOG_QUOTA_THRESHOLD     0x00000010 | ||||
| #define FILE_VC_LOG_QUOTA_LIMIT         0x00000020 | ||||
| #define FILE_VC_LOG_VOLUME_THRESHOLD    0x00000040 | ||||
| #define FILE_VC_LOG_VOLUME_LIMIT        0x00000080 | ||||
| #define FILE_VC_QUOTAS_INCOMPLETE       0x00000100 | ||||
| #define FILE_VC_QUOTAS_REBUILDING       0x00000200 | ||||
| #define FILE_VC_VALID_MASK              0x000003ff | ||||
|  | ||||
| /* IOCTL code to impersonate client of named pipe. */ | ||||
| #define FSCTL_PIPE_IMPERSONATE CTL_CODE(FILE_DEVICE_NAMED_PIPE, 7, \ | ||||
| 					METHOD_BUFFERED, FILE_ANY_ACCESS) | ||||
| @@ -999,6 +1012,16 @@ typedef struct _FILE_FS_SIZE_INFORMATION | ||||
|   ULONG BytesPerSector; | ||||
| } FILE_FS_SIZE_INFORMATION, *PFILE_FS_SIZE_INFORMATION; | ||||
|  | ||||
| /* Checked on 64 bit. */ | ||||
| typedef struct _FILE_FS_CONTROL_INFORMATION { | ||||
|   LARGE_INTEGER FreeSpaceStartFiltering; | ||||
|   LARGE_INTEGER FreeSpaceThreshold; | ||||
|   LARGE_INTEGER FreeSpaceStopFiltering; | ||||
|   LARGE_INTEGER DefaultQuotaThreshold; | ||||
|   LARGE_INTEGER DefaultQuotaLimit; | ||||
|   ULONG FileSystemControlFlags; | ||||
| } FILE_FS_CONTROL_INFORMATION, *PFILE_FS_CONTROL_INFORMATION; | ||||
|  | ||||
| /* Checked on 64 bit. */ | ||||
| typedef struct _FILE_FS_FULL_SIZE_INFORMATION | ||||
| { | ||||
| @@ -1066,6 +1089,24 @@ typedef struct _DIRECTORY_BASIC_INFORMATION | ||||
|   UNICODE_STRING ObjectTypeName; | ||||
| } DIRECTORY_BASIC_INFORMATION, *PDIRECTORY_BASIC_INFORMATION; | ||||
|  | ||||
| /* Checked on 64 bit. */ | ||||
| typedef struct _FILE_GET_QUOTA_INFORMATION { | ||||
|   ULONG NextEntryOffset; | ||||
|   ULONG SidLength; | ||||
|   SID Sid; | ||||
| } FILE_GET_QUOTA_INFORMATION, *PFILE_GET_QUOTA_INFORMATION; | ||||
|  | ||||
| /* Checked on 64 bit. */ | ||||
| typedef struct _FILE_QUOTA_INFORMATION { | ||||
|   ULONG NextEntryOffset; | ||||
|   ULONG SidLength; | ||||
|   LARGE_INTEGER ChangeTime; | ||||
|   LARGE_INTEGER QuotaUsed; | ||||
|   LARGE_INTEGER QuotaThreshold; | ||||
|   LARGE_INTEGER QuotaLimit; | ||||
|   SID Sid; | ||||
| } FILE_QUOTA_INFORMATION, *PFILE_QUOTA_INFORMATION; | ||||
|  | ||||
| /* Checked on 64 bit. */ | ||||
| typedef struct _FILE_GET_EA_INFORMATION | ||||
| { | ||||
| @@ -1301,8 +1342,11 @@ extern "C" | ||||
| 					   ULONG, PULONG); | ||||
|   NTSTATUS NTAPI NtQueryInformationToken (HANDLE, TOKEN_INFORMATION_CLASS, | ||||
| 					  PVOID, ULONG, PULONG); | ||||
|   NTSTATUS NTAPI NtQueryObject (HANDLE, OBJECT_INFORMATION_CLASS, VOID *, | ||||
| 				ULONG, ULONG *); | ||||
|   NTSTATUS NTAPI NtQueryObject (HANDLE, OBJECT_INFORMATION_CLASS, PVOID, ULONG, | ||||
|   				PULONG); | ||||
|   NTSTATUS NTAPI NtQueryQuotaInformationFile (HANDLE, PIO_STATUS_BLOCK, PVOID, | ||||
| 					      ULONG, BOOLEAN, PVOID, ULONG, | ||||
| 					      PSID, BOOLEAN); | ||||
|   NTSTATUS NTAPI NtQuerySemaphore (HANDLE, SEMAPHORE_INFORMATION_CLASS, | ||||
| 				   PVOID, ULONG, PULONG); | ||||
|   NTSTATUS NTAPI NtQuerySystemInformation (SYSTEM_INFORMATION_CLASS, | ||||
| @@ -1319,9 +1363,8 @@ extern "C" | ||||
| 				  PULONG); | ||||
|   NTSTATUS NTAPI NtQueryVirtualMemory (HANDLE, PVOID, MEMORY_INFORMATION_CLASS, | ||||
| 				       PVOID, SIZE_T, PSIZE_T); | ||||
|   NTSTATUS NTAPI NtQueryVolumeInformationFile (HANDLE, IO_STATUS_BLOCK *, | ||||
| 					       VOID *, ULONG, | ||||
| 					       FS_INFORMATION_CLASS); | ||||
|   NTSTATUS NTAPI NtQueryVolumeInformationFile (HANDLE, PIO_STATUS_BLOCK, PVOID, | ||||
| 					       ULONG, FS_INFORMATION_CLASS); | ||||
|   NTSTATUS NTAPI NtReadFile (HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID, | ||||
| 			     PIO_STATUS_BLOCK, PVOID, ULONG, PLARGE_INTEGER, | ||||
| 			     PULONG); | ||||
| @@ -1333,6 +1376,8 @@ extern "C" | ||||
|   NTSTATUS NTAPI NtSetInformationThread (HANDLE, THREADINFOCLASS, PVOID, ULONG); | ||||
|   NTSTATUS NTAPI NtSetInformationToken (HANDLE, TOKEN_INFORMATION_CLASS, PVOID, | ||||
| 					ULONG); | ||||
|   NTSTATUS NTAPI NtSetQuotaInformationFile (HANDLE, PIO_STATUS_BLOCK, PVOID, | ||||
| 					    ULONG); | ||||
|   NTSTATUS NTAPI NtSetSecurityObject (HANDLE, SECURITY_INFORMATION, | ||||
| 				      PSECURITY_DESCRIPTOR); | ||||
|   NTSTATUS NTAPI NtSetTimer (HANDLE, PLARGE_INTEGER, PTIMER_APC_ROUTINE, PVOID, | ||||
| @@ -1340,6 +1385,8 @@ extern "C" | ||||
|   NTSTATUS NTAPI NtSetTimerResolution (ULONG, BOOLEAN, PULONG); | ||||
|   NTSTATUS NTAPI NtSetValueKey (HANDLE, PUNICODE_STRING, ULONG, ULONG, PVOID, | ||||
| 				ULONG); | ||||
|   NTSTATUS NTAPI NtSetVolumeInformationFile (HANDLE, PIO_STATUS_BLOCK, PVOID, | ||||
| 					     ULONG, FS_INFORMATION_CLASS); | ||||
|   NTSTATUS NTAPI NtUnlockFile (HANDLE, PIO_STATUS_BLOCK, PLARGE_INTEGER, | ||||
| 			       PLARGE_INTEGER, ULONG); | ||||
|   NTSTATUS NTAPI NtUnlockVirtualMemory (HANDLE, PVOID *, PSIZE_T, ULONG); | ||||
|   | ||||
							
								
								
									
										340
									
								
								winsup/cygwin/quotactl.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										340
									
								
								winsup/cygwin/quotactl.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,340 @@ | ||||
| /* quotactl.cc: code for manipulating disk quotas | ||||
|  | ||||
|    Copyright 2014 Red Hat, Inc. | ||||
|  | ||||
| This file is part of Cygwin. | ||||
|  | ||||
| This software is a copyrighted work licensed under the terms of the | ||||
| Cygwin license.  Please consult the file "CYGWIN_LICENSE" for | ||||
| details. */ | ||||
|  | ||||
| #include "winsup.h" | ||||
| #include "cygtls.h" | ||||
| #include "security.h" | ||||
| #include "path.h" | ||||
| #include "fhandler.h" | ||||
| #include "dtable.h" | ||||
| #include "cygheap.h" | ||||
| #include "ntdll.h" | ||||
| #include "tls_pbuf.h" | ||||
| #include <sys/mount.h> | ||||
| #include <sys/quota.h> | ||||
|  | ||||
| #define PGQI_SIZE (sizeof (FILE_GET_QUOTA_INFORMATION) + SECURITY_MAX_SID_SIZE) | ||||
| #define PFQI_SIZE (sizeof (FILE_QUOTA_INFORMATION) + SECURITY_MAX_SID_SIZE) | ||||
|  | ||||
| /* Modelled after the Linux quotactl function. */ | ||||
| extern "C" int | ||||
| quotactl (int cmd, const char *special, int id, caddr_t addr) | ||||
| { | ||||
|   ACCESS_MASK access = FILE_READ_DATA; | ||||
|   cygsid sid; | ||||
|   path_conv pc; | ||||
|   tmp_pathbuf tp; | ||||
|   UNICODE_STRING path; | ||||
|   OBJECT_ATTRIBUTES attr; | ||||
|   NTSTATUS status; | ||||
|   HANDLE fh; | ||||
|   IO_STATUS_BLOCK io; | ||||
|   FILE_FS_CONTROL_INFORMATION ffci; | ||||
|   int ret = 0; | ||||
|  | ||||
|   uint32_t subcmd = (uint32_t) cmd >> SUBCMDSHIFT; | ||||
|   uint32_t type = (uint32_t) cmd & SUBCMDMASK; | ||||
|  | ||||
|   if (type != USRQUOTA && type != GRPQUOTA) | ||||
|     { | ||||
|       set_errno (EINVAL); | ||||
|       return -1; | ||||
|     } | ||||
|   switch (subcmd) | ||||
|     { | ||||
|     case Q_SYNC: | ||||
|       if (!special) | ||||
| 	return 0; | ||||
|       access |= FILE_WRITE_DATA; | ||||
|       break; | ||||
|     case Q_QUOTAON: | ||||
|       if (id < QFMT_VFS_OLD || id > QFMT_VFS_V1) | ||||
| 	{ | ||||
| 	  set_errno (EINVAL); | ||||
| 	  return -1; | ||||
| 	} | ||||
|       /*FALLTHRU*/ | ||||
|     case Q_QUOTAOFF: | ||||
|     case Q_SETINFO: | ||||
|       access |= FILE_WRITE_DATA; | ||||
|       break; | ||||
|     case Q_GETFMT: | ||||
|     case Q_GETINFO: | ||||
|       break; | ||||
|     case Q_SETQUOTA: | ||||
|       access |= FILE_WRITE_DATA; | ||||
|       /*FALLTHRU*/ | ||||
|     case Q_GETQUOTA: | ||||
|       /* Windows feature: Default limits.  Get or set them with id == -1. */ | ||||
|       if (id != -1) | ||||
| 	{ | ||||
| 	  struct passwd *pw = NULL; | ||||
| 	  struct group *gr = NULL; | ||||
|  | ||||
| 	  if (type == USRQUOTA) | ||||
| 	    pw = internal_getpwuid (id); | ||||
| 	  else | ||||
| 	    gr = internal_getgrgid (id); | ||||
| 	  if (pw) | ||||
| 	    sid.getfrompw (pw); | ||||
| 	  else if (gr) | ||||
| 	    sid.getfromgr (gr); | ||||
| 	  else | ||||
| 	    { | ||||
| 	      set_errno (EINVAL); | ||||
| 	      return -1; | ||||
| 	    } | ||||
| 	} | ||||
|       break; | ||||
|     default: | ||||
|       set_errno (EINVAL); | ||||
|       return -1; | ||||
|     } | ||||
|   /* Check path */ | ||||
|   pc.check (special, PC_SYM_FOLLOW | PC_NOWARN, stat_suffixes); | ||||
|   if (pc.error) | ||||
|     { | ||||
|       set_errno (pc.error); | ||||
|       return -1; | ||||
|     } | ||||
|   if (!pc.exists ()) | ||||
|     { | ||||
|       set_errno (ENOENT); | ||||
|       return -1; | ||||
|     } | ||||
|   if (!S_ISBLK (pc.dev.mode)) | ||||
|     { | ||||
|       set_errno (ENOTBLK); | ||||
|       return -1; | ||||
|     } | ||||
|   pc.get_object_attr (attr, sec_none_nih); | ||||
|   /* For the following functions to work, we must attach the virtual path to  | ||||
|      the quota file to the device path. | ||||
|       | ||||
|      FIXME: Note that this is NTFS-specific.  Adding ReFS in another step. */ | ||||
|   tp.u_get (&path); | ||||
|   RtlCopyUnicodeString (&path, attr.ObjectName); | ||||
|   RtlAppendUnicodeToString (&path, L"\\$Extend\\$Quota:$Q:$INDEX_ALLOCATION"); | ||||
|   attr.ObjectName = &path; | ||||
|  | ||||
|   /* Open filesystem */ | ||||
|   status = NtOpenFile (&fh, access, &attr, &io, FILE_SHARE_VALID_FLAGS, 0); | ||||
|   if (NT_SUCCESS (status)) | ||||
|     switch (subcmd) | ||||
|       { | ||||
|       case Q_SYNC: | ||||
| 	/* No sync, just report success. */ | ||||
| 	status = STATUS_SUCCESS; | ||||
|       	break; | ||||
|       case Q_QUOTAON: | ||||
|       case Q_QUOTAOFF: | ||||
| 	/* Ignore filename in addr. */ | ||||
| 	status = NtQueryVolumeInformationFile (fh, &io, &ffci, sizeof ffci, | ||||
| 					       FileFsControlInformation); | ||||
| 	if (!NT_SUCCESS (status)) | ||||
| 	  break; | ||||
| 	ffci.FileSystemControlFlags &= ~FILE_VC_QUOTA_ENFORCE | ||||
| 				       & ~FILE_VC_QUOTA_TRACK | ||||
| 				       & ~FILE_VC_QUOTAS_INCOMPLETE | ||||
| 				       & ~FILE_VC_QUOTAS_REBUILDING; | ||||
| 	if (subcmd == Q_QUOTAON) | ||||
| 	  ffci.FileSystemControlFlags |= FILE_VC_QUOTA_ENFORCE; | ||||
| 	status = NtSetVolumeInformationFile (fh, &io, &ffci, sizeof ffci, | ||||
| 					     FileFsControlInformation); | ||||
| 	break; | ||||
|       case Q_GETFMT: | ||||
|       	__try | ||||
| 	  { | ||||
| 	    uint32_t *retval = (uint32_t *) addr; | ||||
|  | ||||
| 	    /* Always fake the latest format. */ | ||||
| 	    *retval = QFMT_VFS_V1; | ||||
| 	  } | ||||
| 	__except (EFAULT) | ||||
| 	  { | ||||
| 	    ret = -1; | ||||
| 	    break; | ||||
| 	  } | ||||
| 	__endtry | ||||
| 	status = STATUS_SUCCESS; | ||||
| 	break; | ||||
|       case Q_GETINFO: | ||||
| 	__try | ||||
| 	  { | ||||
| 	    struct dqinfo *dqi = (struct dqinfo *) addr; | ||||
|  | ||||
| 	    dqi->dqi_bgrace = dqi->dqi_igrace = UINT64_MAX; | ||||
| 	    dqi->dqi_flags = 0; | ||||
| 	    dqi->dqi_valid = IIF_BGRACE | IIF_IGRACE; | ||||
| 	  } | ||||
| 	__except (EFAULT) | ||||
| 	  { | ||||
| 	    ret = -1; | ||||
| 	    break; | ||||
| 	  } | ||||
| 	__endtry | ||||
| 	status = STATUS_SUCCESS; | ||||
| 	break; | ||||
|       case Q_SETINFO: | ||||
| 	/* No settings possible, just report success. */ | ||||
| 	status = STATUS_SUCCESS; | ||||
|       	break; | ||||
|       case Q_GETQUOTA: | ||||
| 	/* Windows feature: Default limits.  Get or set them with id == -1. */ | ||||
| 	if (id == -1) | ||||
| 	  { | ||||
| 	    status = NtQueryVolumeInformationFile (fh, &io, &ffci, sizeof ffci, | ||||
| 						   FileFsControlInformation); | ||||
| 	    if (!NT_SUCCESS (status)) | ||||
| 	      break; | ||||
| 	    __try | ||||
| 	      { | ||||
| 		struct dqblk *dq = (struct dqblk *) addr; | ||||
|  | ||||
| 		dq->dqb_bhardlimit = (uint64_t) ffci.DefaultQuotaLimit.QuadPart; | ||||
| 		if (dq->dqb_bhardlimit != UINT64_MAX) | ||||
| 		  dq->dqb_bhardlimit /= BLOCK_SIZE; | ||||
| 		dq->dqb_bsoftlimit = | ||||
| 				(uint64_t) ffci.DefaultQuotaThreshold.QuadPart; | ||||
| 		if (dq->dqb_bsoftlimit != UINT64_MAX) | ||||
| 		  dq->dqb_bsoftlimit /= BLOCK_SIZE; | ||||
| 		dq->dqb_curspace = 0; | ||||
| 		dq->dqb_ihardlimit = UINT64_MAX; | ||||
| 		dq->dqb_isoftlimit = UINT64_MAX; | ||||
| 		dq->dqb_curinodes = 0; | ||||
| 		dq->dqb_btime = UINT64_MAX; | ||||
| 		dq->dqb_itime = UINT64_MAX; | ||||
| 		dq->dqb_valid = QIF_BLIMITS; | ||||
| 	      } | ||||
| 	    __except (EFAULT) | ||||
| 	      { | ||||
| 		ret = -1; | ||||
| 		break; | ||||
| 	      } | ||||
| 	    __endtry | ||||
| 	  } | ||||
| 	else | ||||
| 	  { | ||||
| 	    PFILE_GET_QUOTA_INFORMATION pgqi = (PFILE_GET_QUOTA_INFORMATION) | ||||
| 					       alloca (PGQI_SIZE); | ||||
| 	    PFILE_QUOTA_INFORMATION pfqi = (PFILE_QUOTA_INFORMATION) | ||||
| 					   alloca (PFQI_SIZE); | ||||
|  | ||||
| 	    pgqi->NextEntryOffset = 0; | ||||
| 	    pgqi->SidLength = RtlLengthSid (sid); | ||||
| 	    RtlCopySid (RtlLengthSid (sid), &pgqi->Sid, sid); | ||||
| 	    status = NtQueryQuotaInformationFile (fh, &io, pfqi, PFQI_SIZE, | ||||
| 						  TRUE, pgqi, PGQI_SIZE, | ||||
| 						  NULL, TRUE); | ||||
| 	    if (!NT_SUCCESS (status)) | ||||
| 	      break; | ||||
| 	    __try | ||||
| 	      { | ||||
| 		struct dqblk *dq = (struct dqblk *) addr; | ||||
|  | ||||
| 		dq->dqb_bhardlimit = (uint64_t) pfqi->QuotaLimit.QuadPart; | ||||
| 		if (dq->dqb_bhardlimit != UINT64_MAX) | ||||
| 		  dq->dqb_bhardlimit /= BLOCK_SIZE; | ||||
| 		dq->dqb_bsoftlimit = (uint64_t) pfqi->QuotaThreshold.QuadPart; | ||||
| 		if (dq->dqb_bsoftlimit != UINT64_MAX) | ||||
| 		  dq->dqb_bsoftlimit /= BLOCK_SIZE; | ||||
| 		dq->dqb_curspace = (uint64_t) pfqi->QuotaUsed.QuadPart; | ||||
| 		if (dq->dqb_curspace != UINT64_MAX) | ||||
| 		  dq->dqb_curspace /= BLOCK_SIZE; | ||||
| 		dq->dqb_ihardlimit = UINT64_MAX; | ||||
| 		dq->dqb_isoftlimit = UINT64_MAX; | ||||
| 		dq->dqb_curinodes = 0; | ||||
| 		dq->dqb_btime = UINT64_MAX; | ||||
| 		dq->dqb_itime = UINT64_MAX; | ||||
| 		dq->dqb_valid = QIF_BLIMITS | QIF_SPACE; | ||||
| 	      } | ||||
| 	    __except (EFAULT) | ||||
| 	      { | ||||
| 		ret = -1; | ||||
| 		break; | ||||
| 	      } | ||||
| 	    __endtry | ||||
| 	  } | ||||
| 	break; | ||||
|       case Q_SETQUOTA: | ||||
| 	/* Windows feature: Default limits.  Get or set them with id == -1. */ | ||||
| 	if (id == -1) | ||||
| 	  { | ||||
| 	    status = NtQueryVolumeInformationFile (fh, &io, &ffci, sizeof ffci, | ||||
| 						   FileFsControlInformation); | ||||
| 	    if (!NT_SUCCESS (status)) | ||||
| 	      break; | ||||
| 	    __try | ||||
| 	      { | ||||
| 		struct dqblk *dq = (struct dqblk *) addr; | ||||
|  | ||||
| 		if (!(dq->dqb_valid & QIF_BLIMITS)) | ||||
| 		  break; | ||||
| 		ffci.DefaultQuotaLimit.QuadPart = dq->dqb_bhardlimit; | ||||
| 		if (ffci.DefaultQuotaLimit.QuadPart != -1) | ||||
| 		  ffci.DefaultQuotaLimit.QuadPart *= BLOCK_SIZE; | ||||
| 		ffci.DefaultQuotaThreshold.QuadPart = dq->dqb_bsoftlimit; | ||||
| 		if (ffci.DefaultQuotaThreshold.QuadPart != -1) | ||||
| 		  ffci.DefaultQuotaThreshold.QuadPart *= BLOCK_SIZE; | ||||
| 	      } | ||||
| 	    __except (EFAULT) | ||||
| 	      { | ||||
| 	        ret = -1; | ||||
| 		break; | ||||
| 	      } | ||||
| 	    __endtry | ||||
| 	    status = NtSetVolumeInformationFile (fh, &io, &ffci, sizeof ffci, | ||||
| 						 FileFsControlInformation); | ||||
| 	  } | ||||
| 	else | ||||
| 	  { | ||||
| 	    PFILE_GET_QUOTA_INFORMATION pgqi = (PFILE_GET_QUOTA_INFORMATION) | ||||
| 					       alloca (PGQI_SIZE); | ||||
| 	    PFILE_QUOTA_INFORMATION pfqi = (PFILE_QUOTA_INFORMATION) | ||||
| 					   alloca (PFQI_SIZE); | ||||
|  | ||||
| 	    pgqi->NextEntryOffset = 0; | ||||
| 	    pgqi->SidLength = RtlLengthSid (sid); | ||||
| 	    RtlCopySid (RtlLengthSid (sid), &pgqi->Sid, sid); | ||||
| 	    status = NtQueryQuotaInformationFile (fh, &io, pfqi, PFQI_SIZE, | ||||
| 						  TRUE, pgqi, PGQI_SIZE, | ||||
| 						  NULL, TRUE); | ||||
| 	    if (!NT_SUCCESS (status)) | ||||
| 	      break; | ||||
| 	    __try | ||||
| 	      { | ||||
| 		struct dqblk *dq = (struct dqblk *) addr; | ||||
|  | ||||
| 		if (!(dq->dqb_valid & QIF_BLIMITS)) | ||||
| 		  break; | ||||
| 		pfqi->QuotaLimit.QuadPart = dq->dqb_bhardlimit; | ||||
| 		if (pfqi->QuotaLimit.QuadPart != -1) | ||||
| 		  pfqi->QuotaLimit.QuadPart *= BLOCK_SIZE; | ||||
| 		pfqi->QuotaThreshold.QuadPart = dq->dqb_bsoftlimit; | ||||
| 		if (pfqi->QuotaThreshold.QuadPart != -1) | ||||
| 		  pfqi->QuotaThreshold.QuadPart *= BLOCK_SIZE; | ||||
| 	      } | ||||
| 	    __except (EFAULT) | ||||
| 	      { | ||||
| 		ret = -1; | ||||
| 		break; | ||||
| 	      } | ||||
| 	    __endtry | ||||
| 	    status = NtSetQuotaInformationFile (fh, &io, pfqi, PFQI_SIZE); | ||||
| 	  } | ||||
| 	break; | ||||
|       } | ||||
|   if (!NT_SUCCESS (status)) | ||||
|     { | ||||
|       __seterrno_from_nt_status (status); | ||||
|       ret = -1; | ||||
|     } | ||||
|   return ret; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user