d20c024ccd6f3fc8e3485bac6a660332a432f250
[ira/wip.git] / source3 / modules / gpfs.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  Provide a connection to GPFS specific features
4  *  Copyright (C) Volker Lendecke 2005
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 #include "includes.h"
21
22 #ifdef HAVE_GPFS
23
24 #include "gpfs_gpl.h"
25 #include "vfs_gpfs.h"
26
27 static bool gpfs_share_modes;
28 static bool gpfs_leases;
29 static bool gpfs_getrealfilename;
30 static bool gpfs_winattr;
31
32 static int (*gpfs_set_share_fn)(int fd, unsigned int allow, unsigned int deny);
33 static int (*gpfs_set_lease_fn)(int fd, unsigned int leaseType);
34 static int (*gpfs_getacl_fn)(char *pathname, int flags, void *acl);
35 static int (*gpfs_putacl_fn)(char *pathname, int flags, void *acl);
36 static int (*gpfs_get_realfilename_path_fn)(char *pathname, char *filenamep,
37                                             int *buflen);
38 static int (*gpfs_set_winattrs_path_fn)(char *pathname, int flags, struct gpfs_winattr *attrs);
39 static int (*gpfs_get_winattrs_path_fn)(char *pathname, struct gpfs_winattr *attrs);
40
41
42 bool set_gpfs_sharemode(files_struct *fsp, uint32 access_mask,
43                         uint32 share_access)
44 {
45         unsigned int allow = GPFS_SHARE_NONE;
46         unsigned int deny = GPFS_DENY_NONE;
47         int result;
48
49         if (!gpfs_share_modes) {
50                 return True;
51         }
52
53         if (gpfs_set_share_fn == NULL) {
54                 return False;
55         }
56
57         if ((fsp == NULL) || (fsp->fh == NULL) || (fsp->fh->fd < 0)) {
58                 /* No real file, don't disturb */
59                 return True;
60         }
61
62         allow |= (access_mask & (FILE_WRITE_DATA|FILE_APPEND_DATA|
63                                  DELETE_ACCESS)) ? GPFS_SHARE_WRITE : 0;
64         allow |= (access_mask & (FILE_READ_DATA|FILE_EXECUTE)) ?
65                 GPFS_SHARE_READ : 0;
66
67         if (allow == GPFS_SHARE_NONE) {
68                 DEBUG(10, ("special case am=no_access:%x\n",access_mask));
69         }
70         else {  
71                 deny |= (share_access & FILE_SHARE_WRITE) ?
72                         0 : GPFS_DENY_WRITE;
73                 deny |= (share_access & (FILE_SHARE_READ)) ?
74                         0 : GPFS_DENY_READ;
75         }
76         DEBUG(10, ("am=%x, allow=%d, sa=%x, deny=%d\n",
77                    access_mask, allow, share_access, deny));
78
79         result = gpfs_set_share_fn(fsp->fh->fd, allow, deny);
80         if (result != 0) {
81                 if (errno == ENOSYS) {
82                         DEBUG(5, ("VFS module vfs_gpfs loaded, but no gpfs "
83                                   "support has been compiled into Samba. Allowing access\n"));
84                         return True;
85                 } else {
86                         DEBUG(10, ("gpfs_set_share failed: %s\n",
87                                    strerror(errno)));
88                 }
89         }
90
91         return (result == 0);
92 }
93
94 int set_gpfs_lease(int fd, int leasetype)
95 {
96         int gpfs_type = GPFS_LEASE_NONE;
97
98         if (!gpfs_leases) {
99                 return True;
100         }
101
102         if (gpfs_set_lease_fn == NULL) {
103                 errno = EINVAL;
104                 return -1;
105         }
106
107         if (leasetype == F_RDLCK) {
108                 gpfs_type = GPFS_LEASE_READ;
109         }
110         if (leasetype == F_WRLCK) {
111                 gpfs_type = GPFS_LEASE_WRITE;
112         }
113
114         /* we unconditionally set CAP_LEASE, rather than looking for
115            -1/EACCES as there is a bug in some versions of
116            libgpfs_gpl.so which results in a leaked fd on /dev/ss0
117            each time we try this with the wrong capabilities set
118         */
119         linux_set_lease_capability();
120         return gpfs_set_lease_fn(fd, gpfs_type);
121 }
122
123 int smbd_gpfs_getacl(char *pathname, int flags, void *acl)
124 {
125         if (gpfs_getacl_fn == NULL) {
126                 errno = ENOSYS;
127                 return -1;
128         }
129
130         return gpfs_getacl_fn(pathname, flags, acl);
131 }
132
133 int smbd_gpfs_putacl(char *pathname, int flags, void *acl)
134 {
135         if (gpfs_putacl_fn == NULL) {
136                 errno = ENOSYS;
137                 return -1;
138         }
139
140         return gpfs_putacl_fn(pathname, flags, acl);
141 }
142
143 int smbd_gpfs_get_realfilename_path(char *pathname, char *filenamep,
144                                     int *buflen)
145 {
146         if ((!gpfs_getrealfilename)
147             || (gpfs_get_realfilename_path_fn == NULL)) {
148                 errno = ENOSYS;
149                 return -1;
150         }
151
152         return gpfs_get_realfilename_path_fn(pathname, filenamep, buflen);
153 }
154
155 int get_gpfs_winattrs(char *pathname,struct gpfs_winattr *attrs)
156 {
157
158         if ((!gpfs_winattr) || (gpfs_get_winattrs_path_fn == NULL)) {
159                 errno = ENOSYS;
160                 return -1;
161         }
162         DEBUG(0, ("gpfs_get_winattrs_path:open call %s\n",pathname));
163         return gpfs_get_winattrs_path_fn(pathname, attrs);
164 }
165
166 int set_gpfs_winattrs(char *pathname,int flags,struct gpfs_winattr *attrs)
167 {
168         if ((!gpfs_winattr) || (gpfs_set_winattrs_path_fn == NULL)) {
169                 errno = ENOSYS;
170                 return -1;
171         }
172
173         DEBUG(0, ("gpfs_set_winattrs_path:open call %s\n",pathname));
174         return gpfs_set_winattrs_path_fn(pathname,flags, attrs);
175 }
176
177 static bool init_gpfs_function_lib(void *plibhandle_pointer,
178                                    const char *libname,
179                                    void *pfn_pointer, const char *fn_name)
180 {
181         bool did_open_here = false;
182         void **libhandle_pointer = (void **)plibhandle_pointer;
183         void **fn_pointer = (void **)pfn_pointer;
184
185         DEBUG(10, ("trying to load name %s from %s\n",
186                    fn_name, libname));
187
188         if (*libhandle_pointer == NULL) {
189                 *libhandle_pointer = dlopen(libname, RTLD_LAZY);
190                 did_open_here = true;
191         }
192         if (*libhandle_pointer == NULL) {
193                 DEBUG(10, ("Could not open lib %s\n", libname));
194                 return false;
195         }
196
197         *fn_pointer = dlsym(*libhandle_pointer, fn_name);
198         if (*fn_pointer == NULL) {
199                 DEBUG(10, ("Did not find symbol %s in lib %s\n",
200                            fn_name, libname));
201                 if (did_open_here) {
202                         dlclose(*libhandle_pointer);
203                         *libhandle_pointer = NULL;
204                 }
205                 return false;
206         }
207
208         return true;
209 }
210
211 static bool init_gpfs_function(void *fn_pointer, const char *fn_name)
212 {
213         static void *libgpfs_handle = NULL;
214         static void *libgpfs_gpl_handle = NULL;
215
216         if (init_gpfs_function_lib(&libgpfs_handle, "libgpfs.so",
217                                    fn_pointer, fn_name)) {
218                 return true;
219         }
220         if (init_gpfs_function_lib(&libgpfs_gpl_handle, "libgpfs_gpl.so",
221                                    fn_pointer, fn_name)) {
222                 return true;
223         }
224         return false;
225 }
226
227 void init_gpfs(void)
228 {
229         init_gpfs_function(&gpfs_set_share_fn, "gpfs_set_share");
230         init_gpfs_function(&gpfs_set_lease_fn, "gpfs_set_lease");
231         init_gpfs_function(&gpfs_getacl_fn, "gpfs_getacl");
232         init_gpfs_function(&gpfs_putacl_fn, "gpfs_putacl");
233         init_gpfs_function(&gpfs_get_realfilename_path_fn,
234                            "gpfs_get_realfilename_path");
235         init_gpfs_function(&gpfs_get_winattrs_path_fn,"gpfs_get_winattrs_path");
236         init_gpfs_function(&gpfs_set_winattrs_path_fn,"gpfs_set_winattrs_path");
237
238
239         gpfs_share_modes = lp_parm_bool(-1, "gpfs", "sharemodes", True);
240         gpfs_leases      = lp_parm_bool(-1, "gpfs", "leases", True);
241         gpfs_getrealfilename = lp_parm_bool(-1, "gpfs", "getrealfilename",
242                                             True);
243         gpfs_winattr = lp_parm_bool(-1, "gpfs", "winattr", False);
244
245         return;
246 }
247
248 #else
249
250 int set_gpfs_lease(int snum, int leasetype)
251 {
252         DEBUG(0, ("'VFS module smbgpfs loaded, without gpfs support compiled\n"));
253
254         /* We need to indicate that no GPFS is around by returning ENOSYS, so
255          * that the normal linux kernel oplock code is called. */
256         errno = ENOSYS;
257         return -1;
258 }
259
260 bool set_gpfs_sharemode(files_struct *fsp, uint32 access_mask,
261                         uint32 share_access)
262 {
263         DEBUG(0, ("VFS module - smbgpfs.so loaded, without gpfs support compiled\n"));
264         /* Don't disturb but complain */
265         return True;
266 }
267
268 int smbd_gpfs_getacl(char *pathname, int flags, void *acl)
269 {
270         errno = ENOSYS;
271         return -1;
272 }
273
274 int smbd_gpfs_putacl(char *pathname, int flags, void *acl)
275 {
276         errno = ENOSYS;
277         return -1;
278 }
279
280 int smbd_gpfs_get_realfilename_path(char *pathname, char *fileamep,
281                                     int *buflen)
282 {
283         errno = ENOSYS;
284         return -1;
285 }
286
287 int set_gpfs_winattrs(char *pathname,int flags,struct gpfs_winattr *attrs)
288 {
289         errno = ENOSYS;
290         return -1;
291 }
292
293 int get_gpfs_winattrs(char *pathname,struct gpfs_winattr *attrs)
294 {
295         errno = ENOSYS;
296         return -1;
297 }
298
299 void init_gpfs(void)
300 {
301         return;
302 }
303
304 #endif /* HAVE_GPFS */