* 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:
parent
5fedfc22b8
commit
1db937e986
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue