Coverage Report

Created: 2025-07-23 07:04

/src/samba/source3/lib/sysquotas_linux.c
Line
Count
Source (jump to first uncovered line)
1
/* 
2
   Unix SMB/CIFS implementation.
3
   System QUOTA function wrappers for LINUX
4
   Copyright (C) Stefan (metze) Metzmacher  2003
5
   
6
   This program is free software; you can redistribute it and/or modify
7
   it under the terms of the GNU General Public License as published by
8
   the Free Software Foundation; either version 3 of the License, or
9
   (at your option) any later version.
10
   
11
   This program is distributed in the hope that it will be useful,
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
   GNU General Public License for more details.
15
   
16
   You should have received a copy of the GNU General Public License
17
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
*/
19
20
21
#include "includes.h"
22
23
#undef DBGC_CLASS
24
0
#define DBGC_CLASS DBGC_QUOTA
25
26
#ifndef HAVE_SYS_QUOTAS
27
#ifdef HAVE_QUOTACTL_LINUX
28
#undef HAVE_QUOTACTL_LINUX
29
#endif
30
#endif
31
32
#ifdef HAVE_QUOTACTL_LINUX
33
34
#include <sys/quota.h>
35
36
/****************************************************************************
37
 Linux quota get calls.
38
****************************************************************************/
39
int sys_get_vfs_quota(const char *path, const char *bdev,
40
          enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
41
0
{
42
0
  int ret = -1;
43
0
  uint32_t qflags = 0;
44
0
  struct dqblk D;
45
0
  uint64_t bsize = (uint64_t)QUOTABLOCK_SIZE;
46
47
0
  if (!path || !bdev || !dp) {
48
0
    smb_panic("sys_get_vfs_quota: called with NULL pointer");
49
0
  }
50
51
0
  ZERO_STRUCT(*dp);
52
0
  dp->qtype = qtype;
53
54
0
  ZERO_STRUCT(D);
55
56
0
  switch (qtype) {
57
0
    case SMB_USER_QUOTA_TYPE:
58
0
      DEBUG(10, ("sys_get_vfs_quota: path[%s] bdev[%s] "
59
0
           "SMB_USER_QUOTA_TYPE uid[%u]\n",
60
0
           path, bdev, (unsigned)id.uid));
61
62
0
      if ((ret = quotactl(QCMD(Q_GETQUOTA, USRQUOTA), bdev,
63
0
              id.uid, (caddr_t)&D))) {
64
0
        return ret;
65
0
      }
66
67
0
      break;
68
0
    case SMB_GROUP_QUOTA_TYPE:
69
0
      DEBUG(10, ("sys_get_vfs_quota: path[%s] bdev[%s] "
70
0
           "SMB_GROUP_QUOTA_TYPE gid[%u]\n",
71
0
           path, bdev, (unsigned)id.gid));
72
73
0
      if ((ret = quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), bdev,
74
0
              id.gid, (caddr_t)&D))) {
75
0
        return ret;
76
0
      }
77
78
0
      break;
79
0
    case SMB_USER_FS_QUOTA_TYPE:
80
0
      DEBUG(10, ("sys_get_vfs_quota: path[%s] bdev[%s] "
81
0
           "SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
82
0
           path, bdev, (unsigned)geteuid()));
83
84
0
      if ((ret = quotactl(QCMD(Q_GETQUOTA, USRQUOTA), bdev,
85
0
              geteuid(), (caddr_t)&D)) == 0) {
86
0
        qflags |= QUOTAS_DENY_DISK;
87
0
      }
88
89
0
      ret = 0;
90
91
0
      break;
92
0
    case SMB_GROUP_FS_QUOTA_TYPE:
93
0
      DEBUG(10, ("sys_get_vfs_quota: path[%s] bdev[%s] "
94
0
           "SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
95
0
           path, bdev, (unsigned)getegid()));
96
97
0
      if ((ret = quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), bdev,
98
0
              getegid(), (caddr_t)&D)) == 0) {
99
0
        qflags |= QUOTAS_DENY_DISK;
100
0
      }
101
102
0
      ret = 0;
103
0
      break;
104
0
    default:
105
0
      errno = ENOSYS;
106
0
      return -1;
107
0
  }
108
109
0
  dp->bsize = bsize;
110
0
  dp->softlimit = (uint64_t)D.dqb_bsoftlimit;
111
0
  dp->hardlimit = (uint64_t)D.dqb_bhardlimit;
112
0
  dp->ihardlimit = (uint64_t)D.dqb_ihardlimit;
113
0
  dp->isoftlimit = (uint64_t)D.dqb_isoftlimit;
114
0
  dp->curinodes = (uint64_t)D.dqb_curinodes;
115
0
  dp->curblocks = (uint64_t)D.dqb_curspace/bsize;
116
117
118
0
  dp->qflags = qflags;
119
120
0
  return ret;
121
0
}
122
123
/****************************************************************************
124
 Linux quota set calls.
125
****************************************************************************/
126
int sys_set_vfs_quota(const char *path, const char *bdev,
127
          enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
128
0
{
129
0
  int ret = -1;
130
0
  struct dqblk D;
131
0
  uint64_t bsize = (uint64_t)QUOTABLOCK_SIZE;
132
0
  bool cur_enf, new_enf;
133
134
0
  if (!path || !bdev || !dp) {
135
0
    smb_panic("sys_set_vfs_quota: called with NULL pointer");
136
0
  }
137
138
0
  ZERO_STRUCT(D);
139
140
0
  if (bsize == dp->bsize) {
141
0
    D.dqb_bsoftlimit = dp->softlimit;
142
0
    D.dqb_bhardlimit = dp->hardlimit;
143
0
  } else {
144
0
    D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize;
145
0
    D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize;
146
0
  }
147
0
  D.dqb_ihardlimit = dp->ihardlimit;
148
0
  D.dqb_isoftlimit = dp->isoftlimit;
149
0
  D.dqb_valid = QIF_LIMITS;
150
151
0
  switch (qtype) {
152
0
    case SMB_USER_QUOTA_TYPE:
153
0
      DEBUG(10, ("sys_set_vfs_quota: path[%s] bdev[%s] "
154
0
           "SMB_USER_QUOTA_TYPE uid[%u]\n",
155
0
           path, bdev, (unsigned)id.uid));
156
157
0
      ret = quotactl(QCMD(Q_SETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D);
158
0
      break;
159
0
    case SMB_GROUP_QUOTA_TYPE:
160
0
      DEBUG(10, ("sys_set_vfs_quota: path[%s] bdev[%s] "
161
0
           "SMB_GROUP_QUOTA_TYPE gid[%u]\n",
162
0
           path, bdev, (unsigned)id.gid));
163
164
0
      ret = quotactl(QCMD(Q_SETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D);
165
0
      break;
166
0
    case SMB_USER_FS_QUOTA_TYPE:
167
0
      DEBUG(10, ("sys_set_vfs_quota: path[%s] bdev[%s] "
168
0
           "SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
169
0
           path, bdev, (unsigned)geteuid()));
170
171
0
      ret = quotactl(QCMD(Q_GETQUOTA, USRQUOTA), bdev,
172
0
               geteuid(), (caddr_t)&D);
173
0
      cur_enf = (ret == 0);
174
0
      new_enf = ((dp->qflags & QUOTAS_DENY_DISK) != 0);
175
      /* We're not changing quota enforcement, so return
176
       * success
177
       * IFF the wanted state is identical to the current
178
       * state */
179
0
      if (cur_enf == new_enf) {
180
0
        ret = 0;
181
0
      } else {
182
0
        errno = EPERM;
183
0
        ret = -1;
184
0
      }
185
186
0
      break;
187
0
    case SMB_GROUP_FS_QUOTA_TYPE:
188
0
      DEBUG(10, ("sys_set_vfs_quota: path[%s] bdev[%s] "
189
0
           "SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
190
0
           path, bdev, (unsigned)getegid()));
191
192
0
      ret = quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), bdev,
193
0
               getegid(), (caddr_t)&D);
194
0
      cur_enf = (ret == 0);
195
0
      new_enf = ((dp->qflags & QUOTAS_DENY_DISK) != 0);
196
      /* We're not changing quota enforcement, so return
197
       * success
198
       * IFF the wanted state is identical to the current
199
       * state */
200
0
      if (cur_enf == new_enf) {
201
0
        ret = 0;
202
0
      } else {
203
0
        errno = EPERM;
204
0
        ret = -1;
205
0
      }
206
207
0
      break;
208
0
    default:
209
0
      errno = ENOSYS;
210
0
      return -1;
211
0
  }
212
213
0
  return ret;
214
0
}
215
216
#else /* HAVE_QUOTACTL_LINUX */
217
 void dummy_sysquotas_linux(void);
218
219
 void dummy_sysquotas_linux(void){}
220
#endif /* HAVE_QUOTACTL_LINUX */