Add CAP VFS module from Monyo. Primary purpose of this module is to provide CAP-compa...
[sfrench/samba-autobuild/.git] / source3 / modules / vfs_cap.c
1 /* 
2  * CAP VFS module for Samba 3.x Version 0.3
3  *
4  * Copyright (C) Tim Potter, 1999-2000
5  * Copyright (C) Alexander Bokovoy, 2002-2003
6  * Copyright (C) Stefan (metze) Metzmacher, 2003
7  * Copyright (C) TAKAHASHI Motonobu (monyo), 2003
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *  
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *  
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  */
23
24
25 #include "includes.h"
26
27 /* cap functions */
28 static char *capencode(char *to, const char *from);
29 static char *capdecode(char *to, const char *from);
30
31 static SMB_BIG_UINT skel_disk_free(vfs_handle_struct *handle, connection_struct *conn, const char *path,
32         BOOL small_query, SMB_BIG_UINT *bsize,
33         SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
34 {
35         pstring cappath;
36         capencode(cappath, path);
37         return SMB_VFS_NEXT_DISK_FREE(handle, conn, cappath, small_query, bsize, 
38                                          dfree, dsize);
39 }
40
41 static int skel_set_quota(vfs_handle_struct *handle, connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dq)
42 {
43         return SMB_VFS_NEXT_SET_QUOTA(handle, conn, qtype, id, dq);
44 }
45
46 static DIR *cap_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname)
47 {
48         pstring capname;
49         capencode(capname, fname);
50         return SMB_VFS_NEXT_OPENDIR(handle, conn, capname);
51 }
52
53 static struct dirent *cap_readdir(vfs_handle_struct *handle, connection_struct *conn, DIR *dirp)
54 {
55         struct dirent *result;
56         DEBUG(3,("cap: cap_readdir\n"));
57         result = SMB_VFS_NEXT_READDIR(handle, conn, dirp);
58         if (result) {
59           DEBUG(3,("cap: cap_readdir: %s\n", result->d_name));
60           capdecode(result->d_name, result->d_name);
61         }
62         return result;
63 }
64
65 static int cap_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode)
66 {
67   pstring cappath;
68   capencode(cappath, path);
69   return SMB_VFS_NEXT_MKDIR(handle, conn, cappath, mode);
70 }
71
72 static int cap_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path)
73 {
74         pstring cappath;
75         capencode(cappath, path);
76         return SMB_VFS_NEXT_RMDIR(handle, conn, cappath);
77 }
78
79 static int cap_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode)
80 {
81         pstring capname;
82         DEBUG(3,("cap: cap_open for %s\n", fname));
83         capencode(capname, fname);
84         return SMB_VFS_NEXT_OPEN(handle, conn, capname, flags, mode);
85 }
86
87 static int cap_rename(vfs_handle_struct *handle, connection_struct *conn, const char *old, const char *new)
88 {
89         pstring capold, capnew;
90         capencode(capold, old);
91         capencode(capnew, new);
92
93         return SMB_VFS_NEXT_RENAME(handle, conn, capold, capnew);
94 }
95
96 static int cap_stat(vfs_handle_struct *handle, connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf)
97 {
98         pstring capname;
99         capencode(capname, fname);
100         return SMB_VFS_NEXT_STAT(handle, conn, capname, sbuf);
101 }
102
103 static int skel_lstat(vfs_handle_struct *handle, connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf)
104 {
105         pstring cappath;
106         capencode(cappath, path);
107         return SMB_VFS_NEXT_LSTAT(handle, conn, cappath, sbuf);
108 }
109
110 static int skel_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path)
111 {
112         pstring cappath;
113         capencode(cappath, path);
114         return SMB_VFS_NEXT_UNLINK(handle, conn, cappath);
115 }
116
117 static int cap_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode)
118 {
119         pstring cappath;
120         capencode(cappath, path);
121         return SMB_VFS_NEXT_CHMOD(handle, conn, cappath, mode);
122 }
123
124 static int cap_chown(vfs_handle_struct *handle, connection_struct *conn, const char *path, uid_t uid, gid_t gid)
125 {
126         pstring cappath;
127         capencode(cappath, path);
128         return SMB_VFS_NEXT_CHOWN(handle, conn, cappath, uid, gid);
129 }
130
131 static int cap_chdir(vfs_handle_struct *handle, connection_struct *conn, const char *path)
132 {
133         pstring cappath;
134         DEBUG(3,("cap: cap_chdir for %s\n", path));
135         capencode(cappath, path);
136         return SMB_VFS_NEXT_CHDIR(handle, conn, cappath);
137 }
138
139 static int skel_utime(vfs_handle_struct *handle, connection_struct *conn, const char *path, struct utimbuf *times)
140 {
141         pstring cappath;
142         capencode(cappath, path);
143         return SMB_VFS_NEXT_UTIME(handle, conn, cappath, times);
144 }
145
146
147 static BOOL skel_symlink(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath)
148 {
149         pstring capoldpath, capnewpath;
150         capencode(capoldpath, oldpath);
151         capencode(capnewpath, newpath);
152         return SMB_VFS_NEXT_SYMLINK(handle, conn, capoldpath, capnewpath);
153 }
154
155 static BOOL skel_readlink(vfs_handle_struct *handle, connection_struct *conn, const char *path, char *buf, size_t bufsiz)
156 {
157         pstring cappath;
158         capencode(cappath, path);
159         return SMB_VFS_NEXT_READLINK(handle, conn, cappath, buf, bufsiz);
160 }
161
162 static int skel_link(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath)
163 {
164         pstring capoldpath, capnewpath;
165         capencode(capoldpath, oldpath);
166         capencode(capnewpath, newpath);
167         return SMB_VFS_NEXT_LINK(handle, conn, capoldpath, capnewpath);
168 }
169
170 static int skel_mknod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode, SMB_DEV_T dev)
171 {
172         pstring cappath;
173         capencode(cappath, path);
174         return SMB_VFS_NEXT_MKNOD(handle, conn, cappath, mode, dev);
175 }
176
177 static char *skel_realpath(vfs_handle_struct *handle, connection_struct *conn, const char *path, char *resolved_path)
178 {
179         /* monyo need capencode'ed and capdecode'ed? */
180         pstring cappath;
181         capencode(cappath, path);
182         return SMB_VFS_NEXT_REALPATH(handle, conn, path, resolved_path);
183 }
184
185 static BOOL skel_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info_sent, struct security_descriptor_info *psd)
186 {
187         pstring capname;
188         capencode(capname, name);
189         return SMB_VFS_NEXT_SET_NT_ACL(handle, fsp, capname, security_info_sent, psd);
190 }
191
192 static int skel_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, const char *name, mode_t mode)
193 {
194         pstring capname;
195         capencode(capname, name);
196
197         /* If the underlying VFS doesn't have ACL support... */
198         if (!handle->vfs_next.ops.chmod_acl) {
199                 errno = ENOSYS;
200                 return -1;
201         }
202         return SMB_VFS_NEXT_CHMOD_ACL(handle, conn, capname, mode);
203 }
204
205 static SMB_ACL_T skel_sys_acl_get_file(vfs_handle_struct *handle, connection_struct *conn, const char *path_p, SMB_ACL_TYPE_T type)
206 {
207         pstring cappath_p;
208         capencode(cappath_p, path_p);
209         return SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, conn, cappath_p, type);
210 }
211
212 static int skel_sys_acl_set_file(vfs_handle_struct *handle, connection_struct *conn, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
213 {
214         pstring capname;
215         capencode(capname, name);
216         return SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, conn, capname, acltype, theacl);
217 }
218
219 static int skel_sys_acl_delete_def_file(vfs_handle_struct *handle, connection_struct *conn, const char *path)
220 {
221         pstring cappath;
222         capencode(cappath, path);
223         return SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, conn, cappath);
224 }
225
226 static ssize_t skel_getxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, void *value, size_t size)
227 {
228         pstring cappath, capname;
229         capencode(cappath, path);
230         capencode(capname, name);
231         return SMB_VFS_NEXT_GETXATTR(handle, conn, cappath, capname, value, size);
232 }
233
234 static ssize_t skel_lgetxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, void *value, size_t
235 size)
236 {
237         pstring cappath, capname;
238         capencode(cappath, path);
239         capencode(capname, name);
240         return SMB_VFS_NEXT_LGETXATTR(handle, conn, cappath, capname, value, size);
241 }
242
243 static ssize_t skel_fgetxattr(vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, void *value, size_t size)
244 {
245         pstring capname;
246         capencode(capname, name);
247         return SMB_VFS_NEXT_FGETXATTR(handle, fsp, fd, capname, value, size);
248 }
249
250 static ssize_t skel_listxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size)
251 {
252         pstring cappath;
253         capencode(cappath, path);
254         return SMB_VFS_NEXT_LISTXATTR(handle, conn, cappath, list, size);
255 }
256
257 static ssize_t skel_llistxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size)
258 {
259         pstring cappath;
260         capencode(cappath, path);
261         return SMB_VFS_NEXT_LLISTXATTR(handle, conn, cappath, list, size);
262 }
263
264 static int skel_removexattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name)
265 {
266         pstring cappath, capname;
267         capencode(cappath, path);
268         capencode(capname, name);
269         return SMB_VFS_NEXT_REMOVEXATTR(handle, conn, cappath, capname);
270 }
271
272 static int skel_lremovexattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name)
273 {
274         pstring cappath, capname;
275         capencode(cappath, path);
276         capencode(capname, name);
277         return SMB_VFS_NEXT_LREMOVEXATTR(handle, conn, cappath, capname);
278 }
279
280 static int skel_fremovexattr(vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name)
281 {
282         pstring capname;
283         capencode(capname, name);
284         return SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, fd, capname);
285 }
286
287 static int skel_setxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags)
288 {
289         pstring cappath, capname;
290         capencode(cappath, path);
291         capencode(capname, name);
292         return SMB_VFS_NEXT_SETXATTR(handle, conn, cappath, capname, value, size, flags);
293 }
294
295 static int skel_lsetxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags)
296 {
297         pstring cappath, capname;
298         capencode(cappath, path);
299         capencode(capname, name);
300         return SMB_VFS_NEXT_LSETXATTR(handle, conn, cappath, capname, value, size, flags);
301 }
302
303 static int skel_fsetxattr(vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, const void *value, size_t size, int flags)
304 {
305         pstring capname;
306         capencode(capname, name);
307         return SMB_VFS_NEXT_FSETXATTR(handle, fsp, fd, capname, value, size, flags);
308 }
309
310 /* VFS operations structure */
311
312 static vfs_op_tuple cap_op_tuples[] = {
313
314         /* Disk operations */
315
316         {SMB_VFS_OP(skel_disk_free),                    SMB_VFS_OP_DISK_FREE,           SMB_VFS_LAYER_TRANSPARENT},
317         
318         /* Directory operations */
319
320         {SMB_VFS_OP(cap_opendir),                       SMB_VFS_OP_OPENDIR,             SMB_VFS_LAYER_TRANSPARENT},
321         {SMB_VFS_OP(cap_readdir),                       SMB_VFS_OP_READDIR,             SMB_VFS_LAYER_TRANSPARENT},
322         {SMB_VFS_OP(cap_mkdir),                 SMB_VFS_OP_MKDIR,               SMB_VFS_LAYER_TRANSPARENT},
323         {SMB_VFS_OP(cap_rmdir),                 SMB_VFS_OP_RMDIR,               SMB_VFS_LAYER_TRANSPARENT},
324
325         /* File operations */
326
327         {SMB_VFS_OP(cap_open),                          SMB_VFS_OP_OPEN,                SMB_VFS_LAYER_TRANSPARENT},
328         {SMB_VFS_OP(cap_rename),                        SMB_VFS_OP_RENAME,              SMB_VFS_LAYER_TRANSPARENT},
329         {SMB_VFS_OP(cap_stat),                          SMB_VFS_OP_STAT,                SMB_VFS_LAYER_TRANSPARENT},
330         {SMB_VFS_OP(skel_lstat),                        SMB_VFS_OP_LSTAT,               SMB_VFS_LAYER_TRANSPARENT},
331         {SMB_VFS_OP(skel_unlink),                       SMB_VFS_OP_UNLINK,              SMB_VFS_LAYER_TRANSPARENT},
332         {SMB_VFS_OP(cap_chmod),                 SMB_VFS_OP_CHMOD,               SMB_VFS_LAYER_TRANSPARENT},
333         {SMB_VFS_OP(cap_chown),                 SMB_VFS_OP_CHOWN,               SMB_VFS_LAYER_TRANSPARENT},
334         {SMB_VFS_OP(cap_chdir),                 SMB_VFS_OP_CHDIR,               SMB_VFS_LAYER_TRANSPARENT},
335         {SMB_VFS_OP(skel_utime),                        SMB_VFS_OP_UTIME,               SMB_VFS_LAYER_TRANSPARENT},
336         {SMB_VFS_OP(skel_symlink),                      SMB_VFS_OP_SYMLINK,             SMB_VFS_LAYER_TRANSPARENT},
337         {SMB_VFS_OP(skel_readlink),                     SMB_VFS_OP_READLINK,            SMB_VFS_LAYER_TRANSPARENT},
338         {SMB_VFS_OP(skel_link),                         SMB_VFS_OP_LINK,                SMB_VFS_LAYER_TRANSPARENT},
339         {SMB_VFS_OP(skel_mknod),                        SMB_VFS_OP_MKNOD,               SMB_VFS_LAYER_TRANSPARENT},
340         {SMB_VFS_OP(skel_realpath),                     SMB_VFS_OP_REALPATH,            SMB_VFS_LAYER_TRANSPARENT},
341
342         /* NT File ACL operations */
343
344         {SMB_VFS_OP(skel_set_nt_acl),                   SMB_VFS_OP_SET_NT_ACL,          SMB_VFS_LAYER_TRANSPARENT},
345
346         /* POSIX ACL operations */
347
348         {SMB_VFS_OP(skel_chmod_acl),                    SMB_VFS_OP_CHMOD_ACL,           SMB_VFS_LAYER_TRANSPARENT},
349
350         {SMB_VFS_OP(skel_sys_acl_get_file),             SMB_VFS_OP_SYS_ACL_GET_FILE,            SMB_VFS_LAYER_TRANSPARENT},
351         {SMB_VFS_OP(skel_sys_acl_set_file),             SMB_VFS_OP_SYS_ACL_SET_FILE,            SMB_VFS_LAYER_TRANSPARENT},
352         {SMB_VFS_OP(skel_sys_acl_delete_def_file),      SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE,     SMB_VFS_LAYER_TRANSPARENT},
353         
354         /* EA operations. */
355         {SMB_VFS_OP(skel_getxattr),                     SMB_VFS_OP_GETXATTR,                    SMB_VFS_LAYER_TRANSPARENT},
356         {SMB_VFS_OP(skel_lgetxattr),                    SMB_VFS_OP_LGETXATTR,                   SMB_VFS_LAYER_TRANSPARENT},
357         {SMB_VFS_OP(skel_fgetxattr),                    SMB_VFS_OP_FGETXATTR,                   SMB_VFS_LAYER_TRANSPARENT},
358         {SMB_VFS_OP(skel_listxattr),                    SMB_VFS_OP_LISTXATTR,                   SMB_VFS_LAYER_TRANSPARENT},
359         {SMB_VFS_OP(skel_llistxattr),                   SMB_VFS_OP_LLISTXATTR,                  SMB_VFS_LAYER_TRANSPARENT},
360         {SMB_VFS_OP(skel_removexattr),                  SMB_VFS_OP_REMOVEXATTR,                 SMB_VFS_LAYER_TRANSPARENT},
361         {SMB_VFS_OP(skel_lremovexattr),                 SMB_VFS_OP_LREMOVEXATTR,                SMB_VFS_LAYER_TRANSPARENT},
362         {SMB_VFS_OP(skel_fremovexattr),                 SMB_VFS_OP_FREMOVEXATTR,                SMB_VFS_LAYER_TRANSPARENT},
363         {SMB_VFS_OP(skel_setxattr),                     SMB_VFS_OP_SETXATTR,                    SMB_VFS_LAYER_TRANSPARENT},
364         {SMB_VFS_OP(skel_lsetxattr),                    SMB_VFS_OP_LSETXATTR,                   SMB_VFS_LAYER_TRANSPARENT},
365         {SMB_VFS_OP(skel_fsetxattr),                    SMB_VFS_OP_FSETXATTR,                   SMB_VFS_LAYER_TRANSPARENT},
366
367         {NULL,                                          SMB_VFS_OP_NOOP,                        SMB_VFS_LAYER_NOOP}
368 };
369
370 NTSTATUS vfs_cap_init(void)
371 {
372         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "cap", cap_op_tuples);
373 }
374
375 /* For CAP functions */
376 #define hex_tag ':'
377 #define hex2bin(c)              hex2bin_table[(unsigned char)(c)]
378 #define bin2hex(c)              bin2hex_table[(unsigned char)(c)]
379 #define is_hex(s)               ((s)[0] == hex_tag)
380
381 static unsigned char hex2bin_table[256] = {
382 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 */
383 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 */
384 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 */
385 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 0x30 */
386 0000, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0000, /* 0x40 */
387 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
388 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 */
389 0000, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0000, /* 0x60 */
390 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
391 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 */
392 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 */
393 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 */
394 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 */
395 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 */
396 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 */
397 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 */
398 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 */
399 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0  /* 0xf0 */
400 };
401 static unsigned char bin2hex_table[256] = "0123456789abcdef";
402
403 /*******************************************************************
404   original code -> ":xx"  - CAP format
405 ********************************************************************/
406 static char *capencode(char *to, const char *from)
407 {
408   pstring cvtbuf;
409   char *out;
410
411   if (to == from) {
412     from = pstrcpy ((char *) cvtbuf, from);
413   }
414
415   for (out = to; *from && (out - to < sizeof(pstring)-7);) {
416     /* buffer husoku error */
417     if ((unsigned char)*from >= 0x80) {
418       *out++ = hex_tag;
419       *out++ = bin2hex (((*from)>>4)&0x0f);
420       *out++ = bin2hex ((*from)&0x0f);
421       from++;
422     } 
423     else {
424       *out++ = *from++;
425     }
426   }
427   *out = '\0';
428   return to;
429 }
430
431 /*******************************************************************
432   CAP -> original code
433 ********************************************************************/
434 /* ":xx" -> a byte */
435 static char *capdecode(char *to, const char *from)
436 {
437   pstring cvtbuf;
438   char *out;
439
440   if (to == from) {
441     from = pstrcpy ((char *) cvtbuf, from);
442   }
443   for (out = to; *from && (out - to < sizeof(pstring)-3);) {
444     if (is_hex(from)) {
445       *out++ = (hex2bin (from[1])<<4) | (hex2bin (from[2]));
446       from += 3;
447     } else {
448       *out++ = *from++;
449     }
450   }
451   *out = '\0';
452   return to;
453 }