s3: VFS: Change SMB_VFS_GET_QUOTA to use const struct smb_filename * instead of const...
[bbaumbach/samba-autobuild/.git] / source3 / modules / vfs_fake_dfq.c
1 /*
2  * Fake Disk-Free and Quota VFS module.  Implements passthrough operation
3  * of all VFS calls, except for "disk free" and "get quota" which
4  * are handled by reading a text file named ".dfq" in the current directory.
5  *
6  * This module is intended for testing purposes.
7  *
8  * Copyright (C) Uri Simchoni, 2016
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, see <http://www.gnu.org/licenses/>.
22  */
23
24 #include "includes.h"
25 #include "smbd/smbd.h"
26
27 #undef DBGC_CLASS
28 #define DBGC_CLASS DBGC_VFS
29
30 static int dfq_get_quota(struct vfs_handle_struct *handle,
31                         const struct smb_filename *smb_fname,
32                         enum SMB_QUOTA_TYPE qtype,
33                         unid_t id,
34                         SMB_DISK_QUOTA *qt);
35
36 static uint64_t dfq_load_param(int snum, const char *path, const char *section,
37                                const char *param, uint64_t def_val)
38 {
39         uint64_t ret;
40
41         char *option =
42             talloc_asprintf(talloc_tos(), "%s/%s/%s", section, param, path);
43         if (option == NULL) {
44                 return def_val;
45         }
46
47         ret = (uint64_t)lp_parm_ulonglong(snum, "fake_dfq", option,
48                                           (unsigned long long)def_val);
49
50         TALLOC_FREE(option);
51
52         return ret;
53 }
54
55 static uint64_t dfq_disk_free(vfs_handle_struct *handle,
56                                 const struct smb_filename *smb_fname,
57                                 uint64_t *bsize,
58                                 uint64_t *dfree,
59                                 uint64_t *dsize)
60 {
61         uint64_t free_1k;
62         int snum = SNUM(handle->conn);
63         uint64_t dfq_bsize = 0;
64         char *rpath = NULL;
65
66         /* look up the params based on real path to be resilient
67          * to refactoring of path<->realpath
68          */
69         rpath = SMB_VFS_NEXT_REALPATH(handle, smb_fname->base_name);
70         if (rpath != NULL) {
71                 dfq_bsize = dfq_load_param(snum, rpath, "df", "block size", 0);
72         }
73         if (dfq_bsize == 0) {
74                 SAFE_FREE(rpath);
75                 return SMB_VFS_NEXT_DISK_FREE(handle, smb_fname, bsize, dfree,
76                                               dsize);
77         }
78
79         *bsize = dfq_bsize;
80         *dfree = dfq_load_param(snum, rpath, "df", "disk free", 0);
81         *dsize = dfq_load_param(snum, rpath, "df", "disk size", 0);
82
83         if ((*bsize) < 1024) {
84                 free_1k = (*dfree) / (1024 / (*bsize));
85         } else {
86                 free_1k = ((*bsize) / 1024) * (*dfree);
87         }
88
89         SAFE_FREE(rpath);
90         return free_1k;
91 }
92
93 static int dfq_get_quota(struct vfs_handle_struct *handle,
94                         const struct smb_filename *smb_fname,
95                         enum SMB_QUOTA_TYPE qtype,
96                         unid_t id,
97                         SMB_DISK_QUOTA *qt)
98 {
99         int rc = 0;
100         int save_errno;
101         char *section = NULL;
102         int snum = SNUM(handle->conn);
103         uint64_t bsize = 0;
104         char *rpath = NULL;
105
106         rpath = SMB_VFS_NEXT_REALPATH(handle, smb_fname->base_name);
107         if (rpath == NULL) {
108                 goto dflt;
109         }
110
111         switch (qtype) {
112         case SMB_USER_QUOTA_TYPE:
113                 section = talloc_asprintf(talloc_tos(), "u%llu",
114                                           (unsigned long long)id.uid);
115                 break;
116         case SMB_GROUP_QUOTA_TYPE:
117                 section = talloc_asprintf(talloc_tos(), "g%llu",
118                                           (unsigned long long)id.gid);
119                 break;
120         case SMB_USER_FS_QUOTA_TYPE:
121                 section = talloc_strdup(talloc_tos(), "udflt");
122                 break;
123         case SMB_GROUP_FS_QUOTA_TYPE:
124                 section = talloc_strdup(talloc_tos(), "gdflt");
125                 break;
126         default:
127                 break;
128         }
129
130         if (section == NULL) {
131                 goto dflt;
132         }
133
134         bsize = dfq_load_param(snum, rpath, section, "block size", 4096);
135         if (bsize == 0) {
136                 goto dflt;
137         }
138
139         if (dfq_load_param(snum, rpath, section, "err", 0) != 0) {
140                 errno = ENOTSUP;
141                 rc = -1;
142                 goto out;
143         }
144
145         if (dfq_load_param(snum, rpath, section, "nosys", 0) != 0) {
146                 errno = ENOSYS;
147                 rc = -1;
148                 goto out;
149         }
150
151         ZERO_STRUCTP(qt);
152
153         qt->bsize = bsize;
154         qt->hardlimit = dfq_load_param(snum, rpath, section, "hard limit", 0);
155         qt->softlimit = dfq_load_param(snum, rpath, section, "soft limit", 0);
156         qt->curblocks = dfq_load_param(snum, rpath, section, "cur blocks", 0);
157         qt->ihardlimit =
158             dfq_load_param(snum, rpath, section, "inode hard limit", 0);
159         qt->isoftlimit =
160             dfq_load_param(snum, rpath, section, "inode soft limit", 0);
161         qt->curinodes = dfq_load_param(snum, rpath, section, "cur inodes", 0);
162         qt->qflags = dfq_load_param(snum, rpath, section, "qflags", QUOTAS_DENY_DISK);
163
164         goto out;
165
166 dflt:
167         rc = SMB_VFS_NEXT_GET_QUOTA(handle, smb_fname, qtype, id, qt);
168
169 out:
170         save_errno = errno;
171         TALLOC_FREE(section);
172         SAFE_FREE(rpath);
173         errno = save_errno;
174         return rc;
175 }
176
177 struct vfs_fn_pointers vfs_fake_dfq_fns = {
178     /* Disk operations */
179
180     .disk_free_fn = dfq_disk_free,
181     .get_quota_fn = dfq_get_quota,
182 };
183
184 static_decl_vfs;
185 NTSTATUS vfs_fake_dfq_init(TALLOC_CTX *ctx)
186 {
187         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "fake_dfq",
188                                 &vfs_fake_dfq_fns);
189 }