s3: Plumb smb_filename through SMB_VFS_UNLINK
[metze/samba/wip.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  * Copyright (C) Jeremy Allison, 2007
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
25 #include "includes.h"
26
27 /* cap functions */
28 static char *capencode(TALLOC_CTX *ctx, const char *from);
29 static char *capdecode(TALLOC_CTX *ctx, const char *from);
30
31 static uint64_t cap_disk_free(vfs_handle_struct *handle, const char *path,
32         bool small_query, uint64_t *bsize,
33         uint64_t *dfree, uint64_t *dsize)
34 {
35         char *cappath = capencode(talloc_tos(), path);
36
37         if (!cappath) {
38                 errno = ENOMEM;
39                 return (uint64_t)-1;
40         }
41         return SMB_VFS_NEXT_DISK_FREE(handle, cappath, small_query, bsize,
42                                         dfree, dsize);
43 }
44
45 static SMB_STRUCT_DIR *cap_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr)
46 {
47         char *capname = capencode(talloc_tos(), fname);
48
49         if (!capname) {
50                 errno = ENOMEM;
51                 return NULL;
52         }
53         return SMB_VFS_NEXT_OPENDIR(handle, capname, mask, attr);
54 }
55
56 static SMB_STRUCT_DIRENT *cap_readdir(vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp)
57 {
58         SMB_STRUCT_DIRENT *result;
59         SMB_STRUCT_DIRENT *newdirent;
60         char *newname;
61         size_t newnamelen;
62         DEBUG(3,("cap: cap_readdir\n"));
63
64         result = SMB_VFS_NEXT_READDIR(handle, dirp, NULL);
65         if (!result) {
66                 return NULL;
67         }
68
69         newname = capdecode(talloc_tos(), result->d_name);
70         if (!newname) {
71                 return NULL;
72         }
73         DEBUG(3,("cap: cap_readdir: %s\n", newname));
74         newnamelen = strlen(newname)+1;
75         newdirent = (SMB_STRUCT_DIRENT *)TALLOC_ARRAY(talloc_tos(),
76                         char,
77                         sizeof(SMB_STRUCT_DIRENT)+
78                                 newnamelen);
79         if (!newdirent) {
80                 return NULL;
81         }
82         memcpy(newdirent, result, sizeof(SMB_STRUCT_DIRENT));
83         memcpy(&newdirent->d_name, newname, newnamelen);
84         return newdirent;
85 }
86
87 static int cap_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode)
88 {
89         char *cappath = capencode(talloc_tos(), path);
90
91         if (!cappath) {
92                 errno = ENOMEM;
93                 return -1;
94         }
95         return SMB_VFS_NEXT_MKDIR(handle, cappath, mode);
96 }
97
98 static int cap_rmdir(vfs_handle_struct *handle, const char *path)
99 {
100         char *cappath = capencode(talloc_tos(), path);
101
102         if (!cappath) {
103                 errno = ENOMEM;
104                 return -1;
105         }
106         return SMB_VFS_NEXT_RMDIR(handle, cappath);
107 }
108
109 static int cap_open(vfs_handle_struct *handle, struct smb_filename *smb_fname,
110                     files_struct *fsp, int flags, mode_t mode)
111 {
112         char *cappath;
113         char *tmp_base_name = NULL;
114         int ret;
115
116         cappath = capencode(talloc_tos(), smb_fname->base_name);
117
118         if (!cappath) {
119                 errno = ENOMEM;
120                 return -1;
121         }
122
123         tmp_base_name = smb_fname->base_name;
124         smb_fname->base_name = cappath;
125
126         DEBUG(3,("cap: cap_open for %s\n", smb_fname_str_dbg(smb_fname)));
127         ret = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
128
129         smb_fname->base_name = tmp_base_name;
130         TALLOC_FREE(cappath);
131
132         return ret;
133 }
134
135 static int cap_rename(vfs_handle_struct *handle,
136                       const struct smb_filename *smb_fname_src,
137                       const struct smb_filename *smb_fname_dst)
138 {
139         char *capold = NULL;
140         char *capnew = NULL;
141         struct smb_filename *smb_fname_src_tmp = NULL;
142         struct smb_filename *smb_fname_dst_tmp = NULL;
143         NTSTATUS status;
144         int ret = -1;
145
146         capold = capencode(talloc_tos(), smb_fname_src->base_name);
147         capnew = capencode(talloc_tos(), smb_fname_dst->base_name);
148         if (!capold || !capnew) {
149                 errno = ENOMEM;
150                 goto out;
151         }
152
153         /* Setup temporary smb_filename structs. */
154         status = copy_smb_filename(talloc_tos(), smb_fname_src,
155                                    &smb_fname_src_tmp);
156         if (!NT_STATUS_IS_OK(status)) {
157                 errno = map_errno_from_nt_status(status);
158                 goto out;
159         }
160         status = copy_smb_filename(talloc_tos(), smb_fname_dst,
161                                    &smb_fname_dst_tmp);
162         if (!NT_STATUS_IS_OK(status)) {
163                 errno = map_errno_from_nt_status(status);
164                 goto out;
165         }
166
167         smb_fname_src_tmp->base_name = capold;
168         smb_fname_dst_tmp->base_name = capnew;
169
170         ret = SMB_VFS_NEXT_RENAME(handle, smb_fname_src_tmp,
171                                   smb_fname_dst_tmp);
172  out:
173         TALLOC_FREE(capold);
174         TALLOC_FREE(capnew);
175         TALLOC_FREE(smb_fname_src_tmp);
176         TALLOC_FREE(smb_fname_dst_tmp);
177
178         return ret;
179 }
180
181 static int cap_stat(vfs_handle_struct *handle, struct smb_filename *smb_fname)
182 {
183         char *cappath;
184         char *tmp_base_name = NULL;
185         int ret;
186
187         cappath = capencode(talloc_tos(), smb_fname->base_name);
188
189         if (!cappath) {
190                 errno = ENOMEM;
191                 return -1;
192         }
193
194         tmp_base_name = smb_fname->base_name;
195         smb_fname->base_name = cappath;
196
197         ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
198
199         smb_fname->base_name = tmp_base_name;
200         TALLOC_FREE(cappath);
201
202         return ret;
203 }
204
205 static int cap_lstat(vfs_handle_struct *handle, struct smb_filename *smb_fname)
206 {
207         char *cappath;
208         char *tmp_base_name = NULL;
209         int ret;
210
211         cappath = capencode(talloc_tos(), smb_fname->base_name);
212
213         if (!cappath) {
214                 errno = ENOMEM;
215                 return -1;
216         }
217
218         tmp_base_name = smb_fname->base_name;
219         smb_fname->base_name = cappath;
220
221         ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
222
223         smb_fname->base_name = tmp_base_name;
224         TALLOC_FREE(cappath);
225
226         return ret;
227 }
228
229 static int cap_unlink(vfs_handle_struct *handle,
230                       const struct smb_filename *smb_fname)
231 {
232         struct smb_filename *smb_fname_tmp = NULL;
233         char *cappath = NULL;
234         NTSTATUS status;
235         int ret;
236
237         cappath = capencode(talloc_tos(), smb_fname->base_name);
238         if (!cappath) {
239                 errno = ENOMEM;
240                 return -1;
241         }
242
243         /* Setup temporary smb_filename structs. */
244         status = copy_smb_filename(talloc_tos(), smb_fname,
245                                    &smb_fname_tmp);
246         if (!NT_STATUS_IS_OK(status)) {
247                 errno = map_errno_from_nt_status(status);
248                 return -1;
249         }
250
251         smb_fname_tmp->base_name = cappath;
252
253         ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname_tmp);
254
255         TALLOC_FREE(smb_fname_tmp);
256         return ret;
257 }
258
259 static int cap_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
260 {
261         char *cappath = capencode(talloc_tos(), path);
262
263         if (!cappath) {
264                 errno = ENOMEM;
265                 return -1;
266         }
267         return SMB_VFS_NEXT_CHMOD(handle, cappath, mode);
268 }
269
270 static int cap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
271 {
272         char *cappath = capencode(talloc_tos(), path);
273
274         if (!cappath) {
275                 errno = ENOMEM;
276                 return -1;
277         }
278         return SMB_VFS_NEXT_CHOWN(handle, cappath, uid, gid);
279 }
280
281 static int cap_lchown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
282 {
283         char *cappath = capencode(talloc_tos(), path);
284
285         if (!cappath) {
286                 errno = ENOMEM;
287                 return -1;
288         }
289         return SMB_VFS_NEXT_LCHOWN(handle, cappath, uid, gid);
290 }
291
292 static int cap_chdir(vfs_handle_struct *handle, const char *path)
293 {
294         char *cappath = capencode(talloc_tos(), path);
295
296         if (!cappath) {
297                 errno = ENOMEM;
298                 return -1;
299         }
300         DEBUG(3,("cap: cap_chdir for %s\n", path));
301         return SMB_VFS_NEXT_CHDIR(handle, cappath);
302 }
303
304 static int cap_ntimes(vfs_handle_struct *handle, const char *path,
305                       struct smb_file_time *ft)
306 {
307         char *cappath = capencode(talloc_tos(), path);
308
309         if (!cappath) {
310                 errno = ENOMEM;
311                 return -1;
312         }
313         return SMB_VFS_NEXT_NTIMES(handle, cappath, ft);
314 }
315
316
317 static bool cap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
318 {
319         char *capold = capencode(talloc_tos(), oldpath);
320         char *capnew = capencode(talloc_tos(), newpath);
321
322         if (!capold || !capnew) {
323                 errno = ENOMEM;
324                 return -1;
325         }
326         return SMB_VFS_NEXT_SYMLINK(handle, capold, capnew);
327 }
328
329 static bool cap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
330 {
331         char *cappath = capencode(talloc_tos(), path);
332
333         if (!cappath) {
334                 errno = ENOMEM;
335                 return -1;
336         }
337         return SMB_VFS_NEXT_READLINK(handle, cappath, buf, bufsiz);
338 }
339
340 static int cap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
341 {
342         char *capold = capencode(talloc_tos(), oldpath);
343         char *capnew = capencode(talloc_tos(), newpath);
344
345         if (!capold || !capnew) {
346                 errno = ENOMEM;
347                 return -1;
348         }
349         return SMB_VFS_NEXT_LINK(handle, capold, capnew);
350 }
351
352 static int cap_mknod(vfs_handle_struct *handle, const char *path, mode_t mode, SMB_DEV_T dev)
353 {
354         char *cappath = capencode(talloc_tos(), path);
355
356         if (!cappath) {
357                 errno = ENOMEM;
358                 return -1;
359         }
360         return SMB_VFS_NEXT_MKNOD(handle, cappath, mode, dev);
361 }
362
363 static char *cap_realpath(vfs_handle_struct *handle, const char *path, char *resolved_path)
364 {
365         /* monyo need capencode'ed and capdecode'ed? */
366         char *cappath = capencode(talloc_tos(), path);
367
368         if (!cappath) {
369                 errno = ENOMEM;
370                 return NULL;
371         }
372         return SMB_VFS_NEXT_REALPATH(handle, path, resolved_path);
373 }
374
375 static int cap_chmod_acl(vfs_handle_struct *handle, const char *path, mode_t mode)
376 {
377         char *cappath = capencode(talloc_tos(), path);
378
379         /* If the underlying VFS doesn't have ACL support... */
380         if (!handle->vfs_next.ops.chmod_acl) {
381                 errno = ENOSYS;
382                 return -1;
383         }
384         if (!cappath) {
385                 errno = ENOMEM;
386                 return -1;
387         }
388         return SMB_VFS_NEXT_CHMOD_ACL(handle, cappath, mode);
389 }
390
391 static SMB_ACL_T cap_sys_acl_get_file(vfs_handle_struct *handle, const char *path, SMB_ACL_TYPE_T type)
392 {
393         char *cappath = capencode(talloc_tos(), path);
394
395         if (!cappath) {
396                 errno = ENOMEM;
397                 return (SMB_ACL_T)NULL;
398         }
399         return SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, cappath, type);
400 }
401
402 static int cap_sys_acl_set_file(vfs_handle_struct *handle, const char *path, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
403 {
404         char *cappath = capencode(talloc_tos(), path);
405
406         if (!cappath) {
407                 errno = ENOMEM;
408                 return -1;
409         }
410         return SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, cappath, acltype, theacl);
411 }
412
413 static int cap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
414 {
415         char *cappath = capencode(talloc_tos(), path);
416
417         if (!cappath) {
418                 errno = ENOMEM;
419                 return -1;
420         }
421         return SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, cappath);
422 }
423
424 static ssize_t cap_getxattr(vfs_handle_struct *handle, const char *path, const char *name, void *value, size_t size)
425 {
426         char *cappath = capencode(talloc_tos(), path);
427         char *capname = capencode(talloc_tos(), name);
428
429         if (!cappath || !capname) {
430                 errno = ENOMEM;
431                 return -1;
432         }
433         return SMB_VFS_NEXT_GETXATTR(handle, cappath, capname, value, size);
434 }
435
436 static ssize_t cap_lgetxattr(vfs_handle_struct *handle, const char *path, const char *name, void *value, size_t
437 size)
438 {
439         char *cappath = capencode(talloc_tos(), path);
440         char *capname = capencode(talloc_tos(), name);
441
442         if (!cappath || !capname) {
443                 errno = ENOMEM;
444                 return -1;
445         }
446         return SMB_VFS_NEXT_LGETXATTR(handle, cappath, capname, value, size);
447 }
448
449 static ssize_t cap_fgetxattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *path, void *value, size_t size)
450 {
451         char *cappath = capencode(talloc_tos(), path);
452
453         if (!cappath) {
454                 errno = ENOMEM;
455                 return -1;
456         }
457         return SMB_VFS_NEXT_FGETXATTR(handle, fsp, cappath, value, size);
458 }
459
460 static ssize_t cap_listxattr(vfs_handle_struct *handle, const char *path, char *list, size_t size)
461 {
462         char *cappath = capencode(talloc_tos(), path);
463
464         if (!cappath) {
465                 errno = ENOMEM;
466                 return -1;
467         }
468         return SMB_VFS_NEXT_LISTXATTR(handle, cappath, list, size);
469 }
470
471 static ssize_t cap_llistxattr(vfs_handle_struct *handle, const char *path, char *list, size_t size)
472 {
473         char *cappath = capencode(talloc_tos(), path);
474
475         if (!cappath) {
476                 errno = ENOMEM;
477                 return -1;
478         }
479         return SMB_VFS_NEXT_LLISTXATTR(handle, cappath, list, size);
480 }
481
482 static int cap_removexattr(vfs_handle_struct *handle, const char *path, const char *name)
483 {
484         char *cappath = capencode(talloc_tos(), path);
485         char *capname = capencode(talloc_tos(), name);
486
487         if (!cappath || !capname) {
488                 errno = ENOMEM;
489                 return -1;
490         }
491         return SMB_VFS_NEXT_REMOVEXATTR(handle, cappath, capname);
492 }
493
494 static int cap_lremovexattr(vfs_handle_struct *handle, const char *path, const char *name)
495 {
496         char *cappath = capencode(talloc_tos(), path);
497         char *capname = capencode(talloc_tos(), name);
498
499         if (!cappath || !capname) {
500                 errno = ENOMEM;
501                 return -1;
502         }
503         return SMB_VFS_NEXT_LREMOVEXATTR(handle, cappath, capname);
504 }
505
506 static int cap_fremovexattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *path)
507 {
508         char *cappath = capencode(talloc_tos(), path);
509
510         if (!cappath) {
511                 errno = ENOMEM;
512                 return -1;
513         }
514         return SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, cappath);
515 }
516
517 static int cap_setxattr(vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
518 {
519         char *cappath = capencode(talloc_tos(), path);
520         char *capname = capencode(talloc_tos(), name);
521
522         if (!cappath || !capname) {
523                 errno = ENOMEM;
524                 return -1;
525         }
526         return SMB_VFS_NEXT_SETXATTR(handle, cappath, capname, value, size, flags);
527 }
528
529 static int cap_lsetxattr(vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
530 {
531         char *cappath = capencode(talloc_tos(), path);
532         char *capname = capencode(talloc_tos(), name);
533
534         if (!cappath || !capname) {
535                 errno = ENOMEM;
536                 return -1;
537         }
538         return SMB_VFS_NEXT_LSETXATTR(handle, cappath, capname, value, size, flags);
539 }
540
541 static int cap_fsetxattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *path, const void *value, size_t size, int flags)
542 {
543         char *cappath = capencode(talloc_tos(), path);
544
545         if (!cappath) {
546                 errno = ENOMEM;
547                 return -1;
548         }
549         return SMB_VFS_NEXT_FSETXATTR(handle, fsp, cappath, value, size, flags);
550 }
551
552 /* VFS operations structure */
553
554 static vfs_op_tuple cap_op_tuples[] = {
555
556         /* Disk operations */
557
558         {SMB_VFS_OP(cap_disk_free),                     SMB_VFS_OP_DISK_FREE,           SMB_VFS_LAYER_TRANSPARENT},
559
560         /* Directory operations */
561
562         {SMB_VFS_OP(cap_opendir),                       SMB_VFS_OP_OPENDIR,             SMB_VFS_LAYER_TRANSPARENT},
563         {SMB_VFS_OP(cap_readdir),                       SMB_VFS_OP_READDIR,             SMB_VFS_LAYER_TRANSPARENT},
564         {SMB_VFS_OP(cap_mkdir),                 SMB_VFS_OP_MKDIR,               SMB_VFS_LAYER_TRANSPARENT},
565         {SMB_VFS_OP(cap_rmdir),                 SMB_VFS_OP_RMDIR,               SMB_VFS_LAYER_TRANSPARENT},
566
567         /* File operations */
568
569         {SMB_VFS_OP(cap_open),                          SMB_VFS_OP_OPEN,                SMB_VFS_LAYER_TRANSPARENT},
570         {SMB_VFS_OP(cap_rename),                        SMB_VFS_OP_RENAME,              SMB_VFS_LAYER_TRANSPARENT},
571         {SMB_VFS_OP(cap_stat),                          SMB_VFS_OP_STAT,                SMB_VFS_LAYER_TRANSPARENT},
572         {SMB_VFS_OP(cap_lstat),                 SMB_VFS_OP_LSTAT,               SMB_VFS_LAYER_TRANSPARENT},
573         {SMB_VFS_OP(cap_unlink),                        SMB_VFS_OP_UNLINK,              SMB_VFS_LAYER_TRANSPARENT},
574         {SMB_VFS_OP(cap_chmod),                 SMB_VFS_OP_CHMOD,               SMB_VFS_LAYER_TRANSPARENT},
575         {SMB_VFS_OP(cap_chown),                 SMB_VFS_OP_CHOWN,               SMB_VFS_LAYER_TRANSPARENT},
576         {SMB_VFS_OP(cap_lchown),                SMB_VFS_OP_LCHOWN,              SMB_VFS_LAYER_TRANSPARENT},
577         {SMB_VFS_OP(cap_chdir),                 SMB_VFS_OP_CHDIR,               SMB_VFS_LAYER_TRANSPARENT},
578         {SMB_VFS_OP(cap_ntimes),                        SMB_VFS_OP_NTIMES,              SMB_VFS_LAYER_TRANSPARENT},
579         {SMB_VFS_OP(cap_symlink),                       SMB_VFS_OP_SYMLINK,             SMB_VFS_LAYER_TRANSPARENT},
580         {SMB_VFS_OP(cap_readlink),                      SMB_VFS_OP_READLINK,            SMB_VFS_LAYER_TRANSPARENT},
581         {SMB_VFS_OP(cap_link),                          SMB_VFS_OP_LINK,                SMB_VFS_LAYER_TRANSPARENT},
582         {SMB_VFS_OP(cap_mknod),                 SMB_VFS_OP_MKNOD,               SMB_VFS_LAYER_TRANSPARENT},
583         {SMB_VFS_OP(cap_realpath),                      SMB_VFS_OP_REALPATH,            SMB_VFS_LAYER_TRANSPARENT},
584
585         /* POSIX ACL operations */
586
587         {SMB_VFS_OP(cap_chmod_acl),                     SMB_VFS_OP_CHMOD_ACL,           SMB_VFS_LAYER_TRANSPARENT},
588
589         {SMB_VFS_OP(cap_sys_acl_get_file),              SMB_VFS_OP_SYS_ACL_GET_FILE,            SMB_VFS_LAYER_TRANSPARENT},
590         {SMB_VFS_OP(cap_sys_acl_set_file),              SMB_VFS_OP_SYS_ACL_SET_FILE,            SMB_VFS_LAYER_TRANSPARENT},
591         {SMB_VFS_OP(cap_sys_acl_delete_def_file),       SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE,     SMB_VFS_LAYER_TRANSPARENT},
592
593         /* EA operations. */
594         {SMB_VFS_OP(cap_getxattr),                      SMB_VFS_OP_GETXATTR,                    SMB_VFS_LAYER_TRANSPARENT},
595         {SMB_VFS_OP(cap_lgetxattr),                     SMB_VFS_OP_LGETXATTR,                   SMB_VFS_LAYER_TRANSPARENT},
596         {SMB_VFS_OP(cap_fgetxattr),                     SMB_VFS_OP_FGETXATTR,                   SMB_VFS_LAYER_TRANSPARENT},
597         {SMB_VFS_OP(cap_listxattr),                     SMB_VFS_OP_LISTXATTR,                   SMB_VFS_LAYER_TRANSPARENT},
598         {SMB_VFS_OP(cap_llistxattr),                    SMB_VFS_OP_LLISTXATTR,                  SMB_VFS_LAYER_TRANSPARENT},
599         {SMB_VFS_OP(cap_removexattr),                   SMB_VFS_OP_REMOVEXATTR,                 SMB_VFS_LAYER_TRANSPARENT},
600         {SMB_VFS_OP(cap_lremovexattr),                  SMB_VFS_OP_LREMOVEXATTR,                SMB_VFS_LAYER_TRANSPARENT},
601         {SMB_VFS_OP(cap_fremovexattr),                  SMB_VFS_OP_FREMOVEXATTR,                SMB_VFS_LAYER_TRANSPARENT},
602         {SMB_VFS_OP(cap_setxattr),                      SMB_VFS_OP_SETXATTR,                    SMB_VFS_LAYER_TRANSPARENT},
603         {SMB_VFS_OP(cap_lsetxattr),                     SMB_VFS_OP_LSETXATTR,                   SMB_VFS_LAYER_TRANSPARENT},
604         {SMB_VFS_OP(cap_fsetxattr),                     SMB_VFS_OP_FSETXATTR,                   SMB_VFS_LAYER_TRANSPARENT},
605
606         {NULL,                                          SMB_VFS_OP_NOOP,                        SMB_VFS_LAYER_NOOP}
607 };
608
609 NTSTATUS vfs_cap_init(void);
610 NTSTATUS vfs_cap_init(void)
611 {
612         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "cap", cap_op_tuples);
613 }
614
615 /* For CAP functions */
616 #define hex_tag ':'
617 #define hex2bin(c)              hex2bin_table[(unsigned char)(c)]
618 #define bin2hex(c)              bin2hex_table[(unsigned char)(c)]
619 #define is_hex(s)               ((s)[0] == hex_tag)
620
621 static unsigned char hex2bin_table[256] = {
622 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 */
623 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 */
624 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 */
625 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 0x30 */
626 0000, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0000, /* 0x40 */
627 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
628 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 */
629 0000, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0000, /* 0x60 */
630 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
631 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 */
632 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 */
633 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 */
634 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 */
635 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 */
636 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 */
637 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 */
638 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 */
639 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0  /* 0xf0 */
640 };
641 static unsigned char bin2hex_table[256] = "0123456789abcdef";
642
643 /*******************************************************************
644   original code -> ":xx"  - CAP format
645 ********************************************************************/
646
647 static char *capencode(TALLOC_CTX *ctx, const char *from)
648 {
649         char *out = NULL;
650         const char *p1;
651         char *to = NULL;
652         size_t len = 0;
653
654         for (p1 = from; *p1; p1++) {
655                 if ((unsigned char)*p1 >= 0x80) {
656                         len += 3;
657                 } else {
658                         len++;
659                 }
660         }
661         len++;
662
663         to = TALLOC_ARRAY(ctx, char, len);
664         if (!to) {
665                 return NULL;
666         }
667
668         for (out = to; *from;) {
669                 /* buffer husoku error */
670                 if ((unsigned char)*from >= 0x80) {
671                         *out++ = hex_tag;
672                         *out++ = bin2hex (((*from)>>4)&0x0f);
673                         *out++ = bin2hex ((*from)&0x0f);
674                         from++;
675                 } else {
676                         *out++ = *from++;
677                 }
678         }
679         *out = '\0';
680         return to;
681 }
682
683 /*******************************************************************
684   CAP -> original code
685 ********************************************************************/
686 /* ":xx" -> a byte */
687
688 static char *capdecode(TALLOC_CTX *ctx, const char *from)
689 {
690         const char *p1;
691         char *out = NULL;
692         char *to = NULL;
693         size_t len = 0;
694
695         for (p1 = from; *p1; len++) {
696                 if (is_hex(from)) {
697                         p1 += 3;
698                 } else {
699                         p1++;
700                 }
701         }
702
703         to = TALLOC_ARRAY(ctx, char, len);
704         if (!to) {
705                 return NULL;
706         }
707
708         for (out = to; *from;) {
709                 if (is_hex(from)) {
710                         *out++ = (hex2bin(from[1])<<4) | (hex2bin(from[2]));
711                         from += 3;
712                 } else {
713                         *out++ = *from++;
714                 }
715         }
716         *out = '\0';
717         return to;
718 }