s3: Plumb smb_filename through SMB_VFS_RENAME
[samba.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, const char *path)
230 {
231         char *cappath = capencode(talloc_tos(), path);
232
233         if (!cappath) {
234                 errno = ENOMEM;
235                 return -1;
236         }
237         return SMB_VFS_NEXT_UNLINK(handle, cappath);
238 }
239
240 static int cap_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
241 {
242         char *cappath = capencode(talloc_tos(), path);
243
244         if (!cappath) {
245                 errno = ENOMEM;
246                 return -1;
247         }
248         return SMB_VFS_NEXT_CHMOD(handle, cappath, mode);
249 }
250
251 static int cap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
252 {
253         char *cappath = capencode(talloc_tos(), path);
254
255         if (!cappath) {
256                 errno = ENOMEM;
257                 return -1;
258         }
259         return SMB_VFS_NEXT_CHOWN(handle, cappath, uid, gid);
260 }
261
262 static int cap_lchown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
263 {
264         char *cappath = capencode(talloc_tos(), path);
265
266         if (!cappath) {
267                 errno = ENOMEM;
268                 return -1;
269         }
270         return SMB_VFS_NEXT_LCHOWN(handle, cappath, uid, gid);
271 }
272
273 static int cap_chdir(vfs_handle_struct *handle, const char *path)
274 {
275         char *cappath = capencode(talloc_tos(), path);
276
277         if (!cappath) {
278                 errno = ENOMEM;
279                 return -1;
280         }
281         DEBUG(3,("cap: cap_chdir for %s\n", path));
282         return SMB_VFS_NEXT_CHDIR(handle, cappath);
283 }
284
285 static int cap_ntimes(vfs_handle_struct *handle, const char *path,
286                       struct smb_file_time *ft)
287 {
288         char *cappath = capencode(talloc_tos(), path);
289
290         if (!cappath) {
291                 errno = ENOMEM;
292                 return -1;
293         }
294         return SMB_VFS_NEXT_NTIMES(handle, cappath, ft);
295 }
296
297
298 static bool cap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
299 {
300         char *capold = capencode(talloc_tos(), oldpath);
301         char *capnew = capencode(talloc_tos(), newpath);
302
303         if (!capold || !capnew) {
304                 errno = ENOMEM;
305                 return -1;
306         }
307         return SMB_VFS_NEXT_SYMLINK(handle, capold, capnew);
308 }
309
310 static bool cap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
311 {
312         char *cappath = capencode(talloc_tos(), path);
313
314         if (!cappath) {
315                 errno = ENOMEM;
316                 return -1;
317         }
318         return SMB_VFS_NEXT_READLINK(handle, cappath, buf, bufsiz);
319 }
320
321 static int cap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
322 {
323         char *capold = capencode(talloc_tos(), oldpath);
324         char *capnew = capencode(talloc_tos(), newpath);
325
326         if (!capold || !capnew) {
327                 errno = ENOMEM;
328                 return -1;
329         }
330         return SMB_VFS_NEXT_LINK(handle, capold, capnew);
331 }
332
333 static int cap_mknod(vfs_handle_struct *handle, const char *path, mode_t mode, SMB_DEV_T dev)
334 {
335         char *cappath = capencode(talloc_tos(), path);
336
337         if (!cappath) {
338                 errno = ENOMEM;
339                 return -1;
340         }
341         return SMB_VFS_NEXT_MKNOD(handle, cappath, mode, dev);
342 }
343
344 static char *cap_realpath(vfs_handle_struct *handle, const char *path, char *resolved_path)
345 {
346         /* monyo need capencode'ed and capdecode'ed? */
347         char *cappath = capencode(talloc_tos(), path);
348
349         if (!cappath) {
350                 errno = ENOMEM;
351                 return NULL;
352         }
353         return SMB_VFS_NEXT_REALPATH(handle, path, resolved_path);
354 }
355
356 static int cap_chmod_acl(vfs_handle_struct *handle, const char *path, mode_t mode)
357 {
358         char *cappath = capencode(talloc_tos(), path);
359
360         /* If the underlying VFS doesn't have ACL support... */
361         if (!handle->vfs_next.ops.chmod_acl) {
362                 errno = ENOSYS;
363                 return -1;
364         }
365         if (!cappath) {
366                 errno = ENOMEM;
367                 return -1;
368         }
369         return SMB_VFS_NEXT_CHMOD_ACL(handle, cappath, mode);
370 }
371
372 static SMB_ACL_T cap_sys_acl_get_file(vfs_handle_struct *handle, const char *path, SMB_ACL_TYPE_T type)
373 {
374         char *cappath = capencode(talloc_tos(), path);
375
376         if (!cappath) {
377                 errno = ENOMEM;
378                 return (SMB_ACL_T)NULL;
379         }
380         return SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, cappath, type);
381 }
382
383 static int cap_sys_acl_set_file(vfs_handle_struct *handle, const char *path, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
384 {
385         char *cappath = capencode(talloc_tos(), path);
386
387         if (!cappath) {
388                 errno = ENOMEM;
389                 return -1;
390         }
391         return SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, cappath, acltype, theacl);
392 }
393
394 static int cap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
395 {
396         char *cappath = capencode(talloc_tos(), path);
397
398         if (!cappath) {
399                 errno = ENOMEM;
400                 return -1;
401         }
402         return SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, cappath);
403 }
404
405 static ssize_t cap_getxattr(vfs_handle_struct *handle, const char *path, const char *name, void *value, size_t size)
406 {
407         char *cappath = capencode(talloc_tos(), path);
408         char *capname = capencode(talloc_tos(), name);
409
410         if (!cappath || !capname) {
411                 errno = ENOMEM;
412                 return -1;
413         }
414         return SMB_VFS_NEXT_GETXATTR(handle, cappath, capname, value, size);
415 }
416
417 static ssize_t cap_lgetxattr(vfs_handle_struct *handle, const char *path, const char *name, void *value, size_t
418 size)
419 {
420         char *cappath = capencode(talloc_tos(), path);
421         char *capname = capencode(talloc_tos(), name);
422
423         if (!cappath || !capname) {
424                 errno = ENOMEM;
425                 return -1;
426         }
427         return SMB_VFS_NEXT_LGETXATTR(handle, cappath, capname, value, size);
428 }
429
430 static ssize_t cap_fgetxattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *path, void *value, size_t size)
431 {
432         char *cappath = capencode(talloc_tos(), path);
433
434         if (!cappath) {
435                 errno = ENOMEM;
436                 return -1;
437         }
438         return SMB_VFS_NEXT_FGETXATTR(handle, fsp, cappath, value, size);
439 }
440
441 static ssize_t cap_listxattr(vfs_handle_struct *handle, const char *path, char *list, size_t size)
442 {
443         char *cappath = capencode(talloc_tos(), path);
444
445         if (!cappath) {
446                 errno = ENOMEM;
447                 return -1;
448         }
449         return SMB_VFS_NEXT_LISTXATTR(handle, cappath, list, size);
450 }
451
452 static ssize_t cap_llistxattr(vfs_handle_struct *handle, const char *path, char *list, size_t size)
453 {
454         char *cappath = capencode(talloc_tos(), path);
455
456         if (!cappath) {
457                 errno = ENOMEM;
458                 return -1;
459         }
460         return SMB_VFS_NEXT_LLISTXATTR(handle, cappath, list, size);
461 }
462
463 static int cap_removexattr(vfs_handle_struct *handle, const char *path, const char *name)
464 {
465         char *cappath = capencode(talloc_tos(), path);
466         char *capname = capencode(talloc_tos(), name);
467
468         if (!cappath || !capname) {
469                 errno = ENOMEM;
470                 return -1;
471         }
472         return SMB_VFS_NEXT_REMOVEXATTR(handle, cappath, capname);
473 }
474
475 static int cap_lremovexattr(vfs_handle_struct *handle, const char *path, const char *name)
476 {
477         char *cappath = capencode(talloc_tos(), path);
478         char *capname = capencode(talloc_tos(), name);
479
480         if (!cappath || !capname) {
481                 errno = ENOMEM;
482                 return -1;
483         }
484         return SMB_VFS_NEXT_LREMOVEXATTR(handle, cappath, capname);
485 }
486
487 static int cap_fremovexattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *path)
488 {
489         char *cappath = capencode(talloc_tos(), path);
490
491         if (!cappath) {
492                 errno = ENOMEM;
493                 return -1;
494         }
495         return SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, cappath);
496 }
497
498 static int cap_setxattr(vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
499 {
500         char *cappath = capencode(talloc_tos(), path);
501         char *capname = capencode(talloc_tos(), name);
502
503         if (!cappath || !capname) {
504                 errno = ENOMEM;
505                 return -1;
506         }
507         return SMB_VFS_NEXT_SETXATTR(handle, cappath, capname, value, size, flags);
508 }
509
510 static int cap_lsetxattr(vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
511 {
512         char *cappath = capencode(talloc_tos(), path);
513         char *capname = capencode(talloc_tos(), name);
514
515         if (!cappath || !capname) {
516                 errno = ENOMEM;
517                 return -1;
518         }
519         return SMB_VFS_NEXT_LSETXATTR(handle, cappath, capname, value, size, flags);
520 }
521
522 static int cap_fsetxattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *path, const void *value, size_t size, int flags)
523 {
524         char *cappath = capencode(talloc_tos(), path);
525
526         if (!cappath) {
527                 errno = ENOMEM;
528                 return -1;
529         }
530         return SMB_VFS_NEXT_FSETXATTR(handle, fsp, cappath, value, size, flags);
531 }
532
533 /* VFS operations structure */
534
535 static vfs_op_tuple cap_op_tuples[] = {
536
537         /* Disk operations */
538
539         {SMB_VFS_OP(cap_disk_free),                     SMB_VFS_OP_DISK_FREE,           SMB_VFS_LAYER_TRANSPARENT},
540
541         /* Directory operations */
542
543         {SMB_VFS_OP(cap_opendir),                       SMB_VFS_OP_OPENDIR,             SMB_VFS_LAYER_TRANSPARENT},
544         {SMB_VFS_OP(cap_readdir),                       SMB_VFS_OP_READDIR,             SMB_VFS_LAYER_TRANSPARENT},
545         {SMB_VFS_OP(cap_mkdir),                 SMB_VFS_OP_MKDIR,               SMB_VFS_LAYER_TRANSPARENT},
546         {SMB_VFS_OP(cap_rmdir),                 SMB_VFS_OP_RMDIR,               SMB_VFS_LAYER_TRANSPARENT},
547
548         /* File operations */
549
550         {SMB_VFS_OP(cap_open),                          SMB_VFS_OP_OPEN,                SMB_VFS_LAYER_TRANSPARENT},
551         {SMB_VFS_OP(cap_rename),                        SMB_VFS_OP_RENAME,              SMB_VFS_LAYER_TRANSPARENT},
552         {SMB_VFS_OP(cap_stat),                          SMB_VFS_OP_STAT,                SMB_VFS_LAYER_TRANSPARENT},
553         {SMB_VFS_OP(cap_lstat),                 SMB_VFS_OP_LSTAT,               SMB_VFS_LAYER_TRANSPARENT},
554         {SMB_VFS_OP(cap_unlink),                        SMB_VFS_OP_UNLINK,              SMB_VFS_LAYER_TRANSPARENT},
555         {SMB_VFS_OP(cap_chmod),                 SMB_VFS_OP_CHMOD,               SMB_VFS_LAYER_TRANSPARENT},
556         {SMB_VFS_OP(cap_chown),                 SMB_VFS_OP_CHOWN,               SMB_VFS_LAYER_TRANSPARENT},
557         {SMB_VFS_OP(cap_lchown),                SMB_VFS_OP_LCHOWN,              SMB_VFS_LAYER_TRANSPARENT},
558         {SMB_VFS_OP(cap_chdir),                 SMB_VFS_OP_CHDIR,               SMB_VFS_LAYER_TRANSPARENT},
559         {SMB_VFS_OP(cap_ntimes),                        SMB_VFS_OP_NTIMES,              SMB_VFS_LAYER_TRANSPARENT},
560         {SMB_VFS_OP(cap_symlink),                       SMB_VFS_OP_SYMLINK,             SMB_VFS_LAYER_TRANSPARENT},
561         {SMB_VFS_OP(cap_readlink),                      SMB_VFS_OP_READLINK,            SMB_VFS_LAYER_TRANSPARENT},
562         {SMB_VFS_OP(cap_link),                          SMB_VFS_OP_LINK,                SMB_VFS_LAYER_TRANSPARENT},
563         {SMB_VFS_OP(cap_mknod),                 SMB_VFS_OP_MKNOD,               SMB_VFS_LAYER_TRANSPARENT},
564         {SMB_VFS_OP(cap_realpath),                      SMB_VFS_OP_REALPATH,            SMB_VFS_LAYER_TRANSPARENT},
565
566         /* POSIX ACL operations */
567
568         {SMB_VFS_OP(cap_chmod_acl),                     SMB_VFS_OP_CHMOD_ACL,           SMB_VFS_LAYER_TRANSPARENT},
569
570         {SMB_VFS_OP(cap_sys_acl_get_file),              SMB_VFS_OP_SYS_ACL_GET_FILE,            SMB_VFS_LAYER_TRANSPARENT},
571         {SMB_VFS_OP(cap_sys_acl_set_file),              SMB_VFS_OP_SYS_ACL_SET_FILE,            SMB_VFS_LAYER_TRANSPARENT},
572         {SMB_VFS_OP(cap_sys_acl_delete_def_file),       SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE,     SMB_VFS_LAYER_TRANSPARENT},
573
574         /* EA operations. */
575         {SMB_VFS_OP(cap_getxattr),                      SMB_VFS_OP_GETXATTR,                    SMB_VFS_LAYER_TRANSPARENT},
576         {SMB_VFS_OP(cap_lgetxattr),                     SMB_VFS_OP_LGETXATTR,                   SMB_VFS_LAYER_TRANSPARENT},
577         {SMB_VFS_OP(cap_fgetxattr),                     SMB_VFS_OP_FGETXATTR,                   SMB_VFS_LAYER_TRANSPARENT},
578         {SMB_VFS_OP(cap_listxattr),                     SMB_VFS_OP_LISTXATTR,                   SMB_VFS_LAYER_TRANSPARENT},
579         {SMB_VFS_OP(cap_llistxattr),                    SMB_VFS_OP_LLISTXATTR,                  SMB_VFS_LAYER_TRANSPARENT},
580         {SMB_VFS_OP(cap_removexattr),                   SMB_VFS_OP_REMOVEXATTR,                 SMB_VFS_LAYER_TRANSPARENT},
581         {SMB_VFS_OP(cap_lremovexattr),                  SMB_VFS_OP_LREMOVEXATTR,                SMB_VFS_LAYER_TRANSPARENT},
582         {SMB_VFS_OP(cap_fremovexattr),                  SMB_VFS_OP_FREMOVEXATTR,                SMB_VFS_LAYER_TRANSPARENT},
583         {SMB_VFS_OP(cap_setxattr),                      SMB_VFS_OP_SETXATTR,                    SMB_VFS_LAYER_TRANSPARENT},
584         {SMB_VFS_OP(cap_lsetxattr),                     SMB_VFS_OP_LSETXATTR,                   SMB_VFS_LAYER_TRANSPARENT},
585         {SMB_VFS_OP(cap_fsetxattr),                     SMB_VFS_OP_FSETXATTR,                   SMB_VFS_LAYER_TRANSPARENT},
586
587         {NULL,                                          SMB_VFS_OP_NOOP,                        SMB_VFS_LAYER_NOOP}
588 };
589
590 NTSTATUS vfs_cap_init(void);
591 NTSTATUS vfs_cap_init(void)
592 {
593         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "cap", cap_op_tuples);
594 }
595
596 /* For CAP functions */
597 #define hex_tag ':'
598 #define hex2bin(c)              hex2bin_table[(unsigned char)(c)]
599 #define bin2hex(c)              bin2hex_table[(unsigned char)(c)]
600 #define is_hex(s)               ((s)[0] == hex_tag)
601
602 static unsigned char hex2bin_table[256] = {
603 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 */
604 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 */
605 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 */
606 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 0x30 */
607 0000, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0000, /* 0x40 */
608 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
609 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 */
610 0000, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0000, /* 0x60 */
611 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
612 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 */
613 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 */
614 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 */
615 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 */
616 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 */
617 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 */
618 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 */
619 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 */
620 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0  /* 0xf0 */
621 };
622 static unsigned char bin2hex_table[256] = "0123456789abcdef";
623
624 /*******************************************************************
625   original code -> ":xx"  - CAP format
626 ********************************************************************/
627
628 static char *capencode(TALLOC_CTX *ctx, const char *from)
629 {
630         char *out = NULL;
631         const char *p1;
632         char *to = NULL;
633         size_t len = 0;
634
635         for (p1 = from; *p1; p1++) {
636                 if ((unsigned char)*p1 >= 0x80) {
637                         len += 3;
638                 } else {
639                         len++;
640                 }
641         }
642         len++;
643
644         to = TALLOC_ARRAY(ctx, char, len);
645         if (!to) {
646                 return NULL;
647         }
648
649         for (out = to; *from;) {
650                 /* buffer husoku error */
651                 if ((unsigned char)*from >= 0x80) {
652                         *out++ = hex_tag;
653                         *out++ = bin2hex (((*from)>>4)&0x0f);
654                         *out++ = bin2hex ((*from)&0x0f);
655                         from++;
656                 } else {
657                         *out++ = *from++;
658                 }
659         }
660         *out = '\0';
661         return to;
662 }
663
664 /*******************************************************************
665   CAP -> original code
666 ********************************************************************/
667 /* ":xx" -> a byte */
668
669 static char *capdecode(TALLOC_CTX *ctx, const char *from)
670 {
671         const char *p1;
672         char *out = NULL;
673         char *to = NULL;
674         size_t len = 0;
675
676         for (p1 = from; *p1; len++) {
677                 if (is_hex(from)) {
678                         p1 += 3;
679                 } else {
680                         p1++;
681                 }
682         }
683
684         to = TALLOC_ARRAY(ctx, char, len);
685         if (!to) {
686                 return NULL;
687         }
688
689         for (out = to; *from;) {
690                 if (is_hex(from)) {
691                         *out++ = (hex2bin(from[1])<<4) | (hex2bin(from[2]));
692                         from += 3;
693                 } else {
694                         *out++ = *from++;
695                 }
696         }
697         *out = '\0';
698         return to;
699 }