]> sourceware.org Git - newlib-cygwin.git/commitdiff
* Makefile.in (DLL_OFILES): Add quotactl.o.
authorCorinna Vinschen <corinna@vinschen.de>
Fri, 17 Oct 2014 08:19:27 +0000 (08:19 +0000)
committerCorinna Vinschen <corinna@vinschen.de>
Fri, 17 Oct 2014 08:19:27 +0000 (08:19 +0000)
* 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.

winsup/cygwin/ChangeLog
winsup/cygwin/Makefile.in
winsup/cygwin/common.din
winsup/cygwin/include/cygwin/version.h
winsup/cygwin/include/sys/mount.h
winsup/cygwin/include/sys/quota.h [new file with mode: 0644]
winsup/cygwin/ntdll.h
winsup/cygwin/quotactl.cc [new file with mode: 0644]

index 46e748db311a3115d80fdc357d1ef6fc47942976..999cd79824463cce70578ee5d0e0d980fda17290 100644 (file)
@@ -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.
index e79bf68bdc9ebefbcb12701092960b849f5d21c1..57a3d04ceb8777e8af2c1e40d5a922ed8c73273f 100644 (file)
@@ -252,6 +252,7 @@ DLL_OFILES:= \
        posix_ipc.o \
        pseudo-reloc.o \
        pthread.o \
+       quotactl.o \
        random.o \
        regcomp.o \
        regerror.o \
index 1268f83b1be4feff8ef1b5dc24223002c00a4357..1c2304631d061ce24603a342835c83136182712b 100644 (file)
@@ -920,6 +920,7 @@ putwc SIGFE
 putwchar SIGFE
 pwrite SIGFE
 qsort NOSIGFE
+quotactl SIGFE
 raise SIGFE
 rand NOSIGFE
 rand_r NOSIGFE
index 66fad063a55a708beaab50649e8a5e5a2bd87dce..fab6f641cdc2a1596c860675ae1e6837f5c328b3 100644 (file)
@@ -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
index 0f5c1724019767235e04d4cf71a155e22db3fef3..458cf801fb328e0935542e2b0b962a6f2d371699 100644 (file)
@@ -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
diff --git a/winsup/cygwin/include/sys/quota.h b/winsup/cygwin/include/sys/quota.h
new file mode 100644 (file)
index 0000000..7edb53e
--- /dev/null
@@ -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 */
index f644b407b85001c03cf4a7eb99eb091d99bcb771..7d8ccbec38a65bfb3e5e69fac62bec8c5569e94b 100644 (file)
 #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);
diff --git a/winsup/cygwin/quotactl.cc b/winsup/cygwin/quotactl.cc
new file mode 100644 (file)
index 0000000..96c6134
--- /dev/null
@@ -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;
+}
This page took 0.057399 seconds and 5 git commands to generate.