Quota code by Peter Urbanec (amiga@cse.unsw.edu.au).
****************************************************************************/
-bool disk_quotas(connection_struct *conn, const char *path, uint64_t *bsize,
- uint64_t *dfree, uint64_t *dsize)
+bool disk_quotas(connection_struct *conn, struct smb_filename *fname,
+ uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)
{
uid_t euser_id;
int ret;
SMB_STRUCT_STAT sbuf;
SMB_DEV_T devno;
bool found = false;
+ const char *path = fname->base_name;
euser_id = geteuid();
- if (sys_stat(path, &sbuf, false) == -1) {
- return false;
- }
-
- devno = sbuf.st_ex_dev ;
+ devno = fname->st.st_ex_dev;
DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n",
path, (unsigned int)devno));
if ((fd = fopen(MNTTAB, "r")) == NULL) {
return true;
}
-
-#else /* not Solaris */
-
-#if AIX
-/* AIX quota patch from Ole Holm Nielsen <ohnielse@fysik.dtu.dk> */
-#include <jfs/quota.h>
-/* AIX 4.X: Rename members of the dqblk structure (ohnielse@fysik.dtu.dk) */
-#define dqb_curfiles dqb_curinodes
-#define dqb_fhardlimit dqb_ihardlimit
-#define dqb_fsoftlimit dqb_isoftlimit
-#ifdef _AIXVERSION_530
-#include <sys/statfs.h>
-#include <sys/vmount.h>
-#endif /* AIX 5.3 */
-#else /* !AIX */
-#include <sys/quota.h>
-#include <devnm.h>
-#endif
-
-
-/****************************************************************************
-try to get the disk space from disk quotas - default version
-****************************************************************************/
-
-bool disk_quotas(connection_struct *conn, const char *path, uint64_t *bsize,
- uint64_t *dfree, uint64_t *dsize)
-{
- int r;
- struct dqblk D;
- uid_t euser_id;
-#if !defined(AIX)
- char dev_disk[256];
- SMB_STRUCT_STAT S;
-
- /* find the block device file */
-
- if ((sys_stat(path, &S, false)<0)
- || (devnm(S_IFBLK, S.st_ex_dev, dev_disk, 256, 0)<0))
- return (False);
-
-#endif /* !defined(AIX) */
-
- euser_id = geteuid();
-
-#if defined(AIX)
- /* AIX has both USER and GROUP quotas:
- Get the USER quota (ohnielse@fysik.dtu.dk) */
-#ifdef _AIXVERSION_530
- {
- struct statfs statbuf;
- quota64_t user_quota;
- if (statfs(path,&statbuf) != 0)
- return False;
- if(statbuf.f_vfstype == MNT_J2)
- {
- /* For some reason we need to be root for jfs2 */
- become_root();
- r = quotactl(path,QCMD(Q_J2GETQUOTA,USRQUOTA),euser_id,(char *) &user_quota);
- unbecome_root();
- /* Copy results to old struct to let the following code work as before */
- D.dqb_curblocks = user_quota.bused;
- D.dqb_bsoftlimit = user_quota.bsoft;
- D.dqb_bhardlimit = user_quota.bhard;
- D.dqb_curfiles = user_quota.iused;
- D.dqb_fsoftlimit = user_quota.isoft;
- D.dqb_fhardlimit = user_quota.ihard;
- }
- else if(statbuf.f_vfstype == MNT_JFS)
- {
-#endif /* AIX 5.3 */
- save_re_uid();
- if (set_re_uid() != 0)
- return False;
- r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D);
- restore_re_uid();
-#ifdef _AIXVERSION_530
- }
- else
- r = 1; /* Fail for other FS-types */
- }
-#endif /* AIX 5.3 */
-#else /* !AIX */
- r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);
-#endif /* !AIX */
-
- /* Use softlimit to determine disk space, except when it has been exceeded */
- *bsize = 1024;
-
- if (r)
- {
- if (errno == EDQUOT)
- {
- *dfree =0;
- *dsize =D.dqb_curblocks;
- return (True);
- }
- else return(False);
- }
-
- /* If softlimit is zero, set it equal to hardlimit.
- */
-
- if (D.dqb_bsoftlimit==0)
- D.dqb_bsoftlimit = D.dqb_bhardlimit;
-
- if (D.dqb_bsoftlimit==0)
- return(False);
- /* Use softlimit to determine disk space, except when it has been exceeded */
- if ((D.dqb_curblocks>D.dqb_bsoftlimit)
-||((D.dqb_curfiles>D.dqb_fsoftlimit) && (D.dqb_fsoftlimit != 0))
- ) {
- *dfree = 0;
- *dsize = D.dqb_curblocks;
- }
- else {
- *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
- *dsize = D.dqb_bsoftlimit;
- }
- return (True);
-}
-
#endif /* Solaris */
#else /* WITH_QUOTAS */
-bool disk_quotas(connection_struct *conn, const char *path, uint64_t *bsize,
- uint64_t *dfree, uint64_t *dsize)
+bool disk_quotas(connection_struct *conn, struct smb_filename *fname,
+ uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)
{
(*bsize) = 512; /* This value should be ignored */
/* wrapper to the new sys_quota interface
this file should be removed later
*/
-bool disk_quotas(connection_struct *conn, const char *path, uint64_t *bsize,
- uint64_t *dfree, uint64_t *dsize)
+bool disk_quotas(connection_struct *conn, struct smb_filename *fname,
+ uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)
{
int r;
SMB_DISK_QUOTA D;
*/
ZERO_STRUCT(D);
id.uid = -1;
- r = SMB_VFS_GET_QUOTA(conn, path, SMB_USER_FS_QUOTA_TYPE, id, &D);
+ r = SMB_VFS_GET_QUOTA(conn, fname, SMB_USER_FS_QUOTA_TYPE,
+ id, &D);
if (r == -1 && errno != ENOSYS) {
goto try_group_quota;
}
ZERO_STRUCT(D);
id.uid = geteuid();
- r = SMB_VFS_GET_QUOTA(conn, path, SMB_USER_QUOTA_TYPE, id, &D);
+ /* if new files created under this folder get this
+ * folder's UID, then available space is governed by
+ * the quota of the folder's UID, not the creating user.
+ */
+ if (lp_inherit_owner(SNUM(conn)) != INHERIT_OWNER_NO &&
+ id.uid != fname->st.st_ex_uid && id.uid != sec_initial_uid()) {
+ int save_errno;
+
+ id.uid = fname->st.st_ex_uid;
+ become_root();
+ r = SMB_VFS_GET_QUOTA(conn, fname,
+ SMB_USER_QUOTA_TYPE, id, &D);
+ save_errno = errno;
+ unbecome_root();
+ errno = save_errno;
+ } else {
+ r = SMB_VFS_GET_QUOTA(conn, fname,
+ SMB_USER_QUOTA_TYPE, id, &D);
+ }
if (r == -1) {
goto try_group_quota;
*/
ZERO_STRUCT(D);
id.gid = -1;
- r = SMB_VFS_GET_QUOTA(conn, path, SMB_GROUP_FS_QUOTA_TYPE, id, &D);
+ r = SMB_VFS_GET_QUOTA(conn, fname, SMB_GROUP_FS_QUOTA_TYPE,
+ id, &D);
if (r == -1 && errno != ENOSYS) {
return false;
}
return false;
}
- id.gid = getegid();
-
ZERO_STRUCT(D);
- r = SMB_VFS_GET_QUOTA(conn, path, SMB_GROUP_QUOTA_TYPE, id, &D);
+
+ /*
+ * If new files created under this folder get this folder's
+ * GID, then available space is governed by the quota of the
+ * folder's GID, not the primary group of the creating user.
+ */
+ if (VALID_STAT(fname->st) &&
+ S_ISDIR(fname->st.st_ex_mode) &&
+ fname->st.st_ex_mode & S_ISGID) {
+ id.gid = fname->st.st_ex_gid;
+ become_root();
+ r = SMB_VFS_GET_QUOTA(conn, fname, SMB_GROUP_QUOTA_TYPE, id,
+ &D);
+ unbecome_root();
+ } else {
+ id.gid = getegid();
+ r = SMB_VFS_GET_QUOTA(conn, fname, SMB_GROUP_QUOTA_TYPE, id,
+ &D);
+ }
if (r == -1) {
return False;