vfstest: Convert cmd_rename to synthetic_smb_fname
[bbaumbach/samba-autobuild/.git] / source3 / torture / cmd_vfs.c
1 /*
2    Unix SMB/CIFS implementation.
3    VFS module functions
4
5    Copyright (C) Simo Sorce 2002
6    Copyright (C) Eric Lorimer 2002
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "smbd/smbd.h"
24 #include "system/passwd.h"
25 #include "system/filesys.h"
26 #include "vfstest.h"
27 #include "../lib/util/util_pw.h"
28 #include "libcli/security/security.h"
29 #include "passdb/machine_sid.h"
30
31 static const char *null_string = "";
32
33 static NTSTATUS cmd_load_module(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
34 {
35         int i;
36
37         if (argc < 2) {
38                 printf("Usage: load <modules>\n");
39                 return NT_STATUS_OK;
40         }
41
42         for (i=argc-1;i>0;i--) {
43                 if (!vfs_init_custom(vfs->conn, argv[i])) {
44                         DEBUG(0, ("load: (vfs_init_custom failed for %s)\n", argv[i]));
45                         return NT_STATUS_UNSUCCESSFUL;
46                 }
47         }
48         printf("load: ok\n");
49         return NT_STATUS_OK;
50 }
51
52 static NTSTATUS cmd_populate(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
53 {
54         char c;
55         size_t size;
56         if (argc != 3) {
57                 printf("Usage: populate <char> <size>\n");
58                 return NT_STATUS_OK;
59         }
60         c = argv[1][0];
61         size = atoi(argv[2]);
62         vfs->data = talloc_array(mem_ctx, char, size);
63         if (vfs->data == NULL) {
64                 printf("populate: error=-1 (not enough memory)");
65                 return NT_STATUS_UNSUCCESSFUL;
66         }
67         memset(vfs->data, c, size);
68         vfs->data_size = size;
69         return NT_STATUS_OK;
70 }
71
72 static NTSTATUS cmd_show_data(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
73 {
74         size_t offset;
75         size_t len;
76         if (argc != 1 && argc != 3) {
77                 printf("Usage: showdata [<offset> <len>]\n");
78                 return NT_STATUS_OK;
79         }
80         if (vfs->data == NULL || vfs->data_size == 0) {
81                 printf("show_data: error=-1 (buffer empty)\n");
82                 return NT_STATUS_UNSUCCESSFUL;
83         }
84
85         if (argc == 3) {
86                 offset = atoi(argv[1]);
87                 len = atoi(argv[2]);
88         } else {
89                 offset = 0;
90                 len = vfs->data_size;
91         }
92         if ((offset + len) > vfs->data_size) {
93                 printf("show_data: error=-1 (not enough data in buffer)\n");
94                 return NT_STATUS_UNSUCCESSFUL;
95         }
96         dump_data(0, (uint8 *)(vfs->data) + offset, len);
97         return NT_STATUS_OK;
98 }
99
100 static NTSTATUS cmd_connect(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
101 {
102         SMB_VFS_CONNECT(vfs->conn, lp_servicename(talloc_tos(), SNUM(vfs->conn)), "vfstest");
103         return NT_STATUS_OK;
104 }
105
106 static NTSTATUS cmd_disconnect(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
107 {
108         SMB_VFS_DISCONNECT(vfs->conn);
109         return NT_STATUS_OK;
110 }
111
112 static NTSTATUS cmd_disk_free(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
113 {
114         uint64_t diskfree, bsize, dfree, dsize;
115         if (argc != 2) {
116                 printf("Usage: disk_free <path>\n");
117                 return NT_STATUS_OK;
118         }
119
120         diskfree = SMB_VFS_DISK_FREE(vfs->conn, argv[1], False, &bsize, &dfree, &dsize);
121         printf("disk_free: %lu, bsize = %lu, dfree = %lu, dsize = %lu\n",
122                         (unsigned long)diskfree,
123                         (unsigned long)bsize,
124                         (unsigned long)dfree,
125                         (unsigned long)dsize);
126         return NT_STATUS_OK;
127 }
128
129
130 static NTSTATUS cmd_opendir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
131 {
132         if (argc != 2) {
133                 printf("Usage: opendir <fname>\n");
134                 return NT_STATUS_OK;
135         }
136
137         vfs->currentdir = SMB_VFS_OPENDIR(vfs->conn, argv[1], NULL, 0);
138         if (vfs->currentdir == NULL) {
139                 printf("opendir error=%d (%s)\n", errno, strerror(errno));
140                 return NT_STATUS_UNSUCCESSFUL;
141         }
142
143         printf("opendir: ok\n");
144         return NT_STATUS_OK;
145 }
146
147
148 static NTSTATUS cmd_readdir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
149 {
150         SMB_STRUCT_STAT st;
151         struct dirent *dent = NULL;
152
153         if (vfs->currentdir == NULL) {
154                 printf("readdir: error=-1 (no open directory)\n");
155                 return NT_STATUS_UNSUCCESSFUL;
156         }
157
158         dent = SMB_VFS_READDIR(vfs->conn, vfs->currentdir, &st);
159         if (dent == NULL) {
160                 printf("readdir: NULL\n");
161                 return NT_STATUS_OK;
162         }
163
164         printf("readdir: %s\n", dent->d_name);
165         if (VALID_STAT(st)) {
166                 time_t tmp_time;
167                 printf("  stat available");
168                 if (S_ISREG(st.st_ex_mode)) printf("  Regular File\n");
169                 else if (S_ISDIR(st.st_ex_mode)) printf("  Directory\n");
170                 else if (S_ISCHR(st.st_ex_mode)) printf("  Character Device\n");
171                 else if (S_ISBLK(st.st_ex_mode)) printf("  Block Device\n");
172                 else if (S_ISFIFO(st.st_ex_mode)) printf("  Fifo\n");
173                 else if (S_ISLNK(st.st_ex_mode)) printf("  Symbolic Link\n");
174                 else if (S_ISSOCK(st.st_ex_mode)) printf("  Socket\n");
175                 printf("  Size: %10u", (unsigned int)st.st_ex_size);
176 #ifdef HAVE_STAT_ST_BLOCKS
177                 printf(" Blocks: %9u", (unsigned int)st.st_ex_blocks);
178 #endif
179 #ifdef HAVE_STAT_ST_BLKSIZE
180                 printf(" IO Block: %u\n", (unsigned int)st.st_ex_blksize);
181 #endif
182                 printf("  Device: 0x%10x", (unsigned int)st.st_ex_dev);
183                 printf(" Inode: %10u", (unsigned int)st.st_ex_ino);
184                 printf(" Links: %10u\n", (unsigned int)st.st_ex_nlink);
185                 printf("  Access: %05o", (int)((st.st_ex_mode) & 007777));
186                 printf(" Uid: %5lu Gid: %5lu\n",
187                        (unsigned long)st.st_ex_uid,
188                        (unsigned long)st.st_ex_gid);
189                 tmp_time = convert_timespec_to_time_t(st.st_ex_atime);
190                 printf("  Access: %s", ctime(&tmp_time));
191                 tmp_time = convert_timespec_to_time_t(st.st_ex_mtime);
192                 printf("  Modify: %s", ctime(&tmp_time));
193                 tmp_time = convert_timespec_to_time_t(st.st_ex_ctime);
194                 printf("  Change: %s", ctime(&tmp_time));
195         }
196
197         return NT_STATUS_OK;
198 }
199
200
201 static NTSTATUS cmd_mkdir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
202 {
203         if (argc != 2) {
204                 printf("Usage: mkdir <path>\n");
205                 return NT_STATUS_OK;
206         }
207
208         if (SMB_VFS_MKDIR(vfs->conn, argv[1], 00755) == -1) {
209                 printf("mkdir error=%d (%s)\n", errno, strerror(errno));
210                 return NT_STATUS_UNSUCCESSFUL;
211         }
212
213         printf("mkdir: ok\n");
214         return NT_STATUS_OK;
215 }
216
217
218 static NTSTATUS cmd_closedir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
219 {
220         int ret;
221
222         if (vfs->currentdir == NULL) {
223                 printf("closedir: failure (no directory open)\n");
224                 return NT_STATUS_UNSUCCESSFUL;
225         }
226
227         ret = SMB_VFS_CLOSEDIR(vfs->conn, vfs->currentdir);
228         if (ret == -1) {
229                 printf("closedir failure: %s\n", strerror(errno));
230                 return NT_STATUS_UNSUCCESSFUL;
231         }
232
233         printf("closedir: ok\n");
234         vfs->currentdir = NULL;
235         return NT_STATUS_OK;
236 }
237
238
239 static NTSTATUS cmd_open(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
240 {
241         int flags;
242         mode_t mode;
243         const char *flagstr;
244         files_struct *fsp;
245         struct smb_filename *smb_fname = NULL;
246         NTSTATUS status;
247         int ret;
248
249         mode = 00400;
250
251         if (argc < 3 || argc > 5) {
252                 printf("Usage: open <filename> <flags> <mode>\n");
253                 printf("  flags: O = O_RDONLY\n");
254                 printf("         R = O_RDWR\n");
255                 printf("         W = O_WRONLY\n");
256                 printf("         C = O_CREAT\n");
257                 printf("         E = O_EXCL\n");
258                 printf("         T = O_TRUNC\n");
259                 printf("         A = O_APPEND\n");
260                 printf("         N = O_NONBLOCK/O_NDELAY\n");
261 #ifdef O_SYNC
262                 printf("         S = O_SYNC\n");
263 #endif
264 #ifdef O_NOFOLLOW
265                 printf("         F = O_NOFOLLOW\n");
266 #endif
267                 printf("  mode: see open.2\n");
268                 printf("        mode is ignored if C flag not present\n");
269                 printf("        mode defaults to 00400\n");
270                 return NT_STATUS_OK;
271         }
272         flags = 0;
273         flagstr = argv[2];
274         while (*flagstr) {
275                 switch (*flagstr) {
276                 case 'O':
277                         flags |= O_RDONLY;
278                         break;
279                 case 'R':
280                         flags |= O_RDWR;
281                         break;
282                 case 'W':
283                         flags |= O_WRONLY;
284                         break;
285                 case 'C':
286                         flags |= O_CREAT;
287                         break;
288                 case 'E':
289                         flags |= O_EXCL;
290                         break;
291                 case 'T':
292                         flags |= O_TRUNC;
293                         break;
294                 case 'A':
295                         flags |= O_APPEND;
296                         break;
297                 case 'N':
298                         flags |= O_NONBLOCK;
299                         break;
300 #ifdef O_SYNC
301                 case 'S':
302                         flags |= O_SYNC;
303                         break;
304 #endif
305 #ifdef O_NOFOLLOW
306                 case 'F':
307                         flags |= O_NOFOLLOW;
308                         break;
309 #endif
310                 default:
311                         printf("open: error=-1 (invalid flag!)\n");
312                         return NT_STATUS_UNSUCCESSFUL;
313                 }
314                 flagstr++;
315         }
316         if ((flags & O_CREAT) && argc == 4) {
317                 if (sscanf(argv[3], "%ho", (unsigned short *)&mode) == 0) {
318                         printf("open: error=-1 (invalid mode!)\n");
319                         return NT_STATUS_UNSUCCESSFUL;
320                 }
321         }
322
323         fsp = talloc_zero(vfs, struct files_struct);
324         if (fsp == NULL) {
325                 return NT_STATUS_NO_MEMORY;
326         }
327         fsp->fh = talloc_zero(fsp, struct fd_handle);
328         if (fsp->fh == NULL) {
329                 TALLOC_FREE(fsp);
330                 return NT_STATUS_NO_MEMORY;
331         }
332         fsp->conn = vfs->conn;
333
334         smb_fname = synthetic_smb_fname_split(NULL, argv[1], NULL);
335         if (smb_fname == NULL) {
336                 TALLOC_FREE(fsp);
337                 return NT_STATUS_NO_MEMORY;
338         }
339
340         fsp->fsp_name = smb_fname;
341
342         fsp->fh->fd = SMB_VFS_OPEN(vfs->conn, smb_fname, fsp, flags, mode);
343         if (fsp->fh->fd == -1) {
344                 printf("open: error=%d (%s)\n", errno, strerror(errno));
345                 TALLOC_FREE(fsp);
346                 TALLOC_FREE(smb_fname);
347                 return NT_STATUS_UNSUCCESSFUL;
348         }
349
350         ret = SMB_VFS_FSTAT(fsp, &smb_fname->st);
351         if (ret == -1) {
352                 /* If we have an fd, this stat should succeed. */
353                 DEBUG(0,("Error doing fstat on open file %s "
354                          "(%s)\n",
355                          smb_fname_str_dbg(smb_fname),
356                          strerror(errno) ));
357                 status = map_nt_error_from_unix(errno);
358         } else if (S_ISDIR(smb_fname->st.st_ex_mode)) {
359                 errno = EISDIR;
360                 status = NT_STATUS_FILE_IS_A_DIRECTORY;
361         }
362         
363         if (!NT_STATUS_IS_OK(status)) {
364                 SMB_VFS_CLOSE(fsp);
365                 TALLOC_FREE(fsp);
366                 TALLOC_FREE(smb_fname);
367                 return status;
368         }
369
370         fsp->file_id = vfs_file_id_from_sbuf(vfs->conn, &smb_fname->st);
371         fsp->vuid = UID_FIELD_INVALID;
372         fsp->file_pid = 0;
373         fsp->can_lock = True;
374         fsp->can_read = True;
375         fsp->can_write =
376                 CAN_WRITE(vfs->conn);
377         fsp->print_file = NULL;
378         fsp->modified = False;
379         fsp->sent_oplock_break = NO_BREAK_SENT;
380         fsp->is_directory = False;
381
382         vfs->files[fsp->fh->fd] = fsp;
383         printf("open: fd=%d\n", fsp->fh->fd);
384         return NT_STATUS_OK;
385 }
386
387
388 static NTSTATUS cmd_pathfunc(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
389 {
390         int ret = -1;
391
392         if (argc != 2) {
393                 printf("Usage: %s <path>\n", argv[0]);
394                 return NT_STATUS_OK;
395         }
396
397         if (strcmp("rmdir", argv[0]) == 0 ) {
398                 ret = SMB_VFS_RMDIR(vfs->conn, argv[1]);
399         } else if (strcmp("unlink", argv[0]) == 0 ) {
400                 struct smb_filename *smb_fname;
401
402                 smb_fname = synthetic_smb_fname_split(mem_ctx, argv[1], NULL);
403                 if (smb_fname == NULL) {
404                         return NT_STATUS_NO_MEMORY;
405                 }
406
407                 ret = SMB_VFS_UNLINK(vfs->conn, smb_fname);
408                 TALLOC_FREE(smb_fname);
409         } else if (strcmp("chdir", argv[0]) == 0 ) {
410                 ret = SMB_VFS_CHDIR(vfs->conn, argv[1]);
411         } else {
412                 printf("%s: error=%d (invalid function name!)\n", argv[0], errno);
413                 return NT_STATUS_UNSUCCESSFUL;
414         }
415
416         if (ret == -1) {
417                 printf("%s: error=%d (%s)\n", argv[0], errno, strerror(errno));
418                 return NT_STATUS_UNSUCCESSFUL;
419         }
420
421         printf("%s: ok\n", argv[0]);
422         return NT_STATUS_OK;
423 }
424
425
426 static NTSTATUS cmd_close(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
427 {
428         int fd, ret;
429
430         if (argc != 2) {
431                 printf("Usage: close <fd>\n");
432                 return NT_STATUS_OK;
433         }
434
435         fd = atoi(argv[1]);
436         if (vfs->files[fd] == NULL) {
437                 printf("close: error=-1 (invalid file descriptor)\n");
438                 return NT_STATUS_OK;
439         }
440
441         ret = SMB_VFS_CLOSE(vfs->files[fd]);
442         if (ret == -1 )
443                 printf("close: error=%d (%s)\n", errno, strerror(errno));
444         else
445                 printf("close: ok\n");
446
447         TALLOC_FREE(vfs->files[fd]);
448         vfs->files[fd] = NULL;
449         return NT_STATUS_OK;
450 }
451
452
453 static NTSTATUS cmd_read(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
454 {
455         int fd;
456         size_t size, rsize;
457
458         if (argc != 3) {
459                 printf("Usage: read <fd> <size>\n");
460                 return NT_STATUS_OK;
461         }
462
463         /* do some error checking on these */
464         fd = atoi(argv[1]);
465         size = atoi(argv[2]);
466         vfs->data = talloc_array(mem_ctx, char, size);
467         if (vfs->data == NULL) {
468                 printf("read: error=-1 (not enough memory)");
469                 return NT_STATUS_UNSUCCESSFUL;
470         }
471         vfs->data_size = size;
472
473         rsize = SMB_VFS_READ(vfs->files[fd], vfs->data, size);
474         if (rsize == -1) {
475                 printf("read: error=%d (%s)\n", errno, strerror(errno));
476                 return NT_STATUS_UNSUCCESSFUL;
477         }
478
479         printf("read: ok\n");
480         return NT_STATUS_OK;
481 }
482
483
484 static NTSTATUS cmd_write(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
485 {
486         int fd, size, wsize;
487
488         if (argc != 3) {
489                 printf("Usage: write <fd> <size>\n");
490                 return NT_STATUS_OK;
491         }
492
493         /* some error checking should go here */
494         fd = atoi(argv[1]);
495         size = atoi(argv[2]);
496         if (vfs->data == NULL) {
497                 printf("write: error=-1 (buffer empty, please populate it before writing)");
498                 return NT_STATUS_UNSUCCESSFUL;
499         }
500
501         if (vfs->data_size < size) {
502                 printf("write: error=-1 (buffer too small, please put some more data in)");
503                 return NT_STATUS_UNSUCCESSFUL;
504         }
505
506         wsize = SMB_VFS_WRITE(vfs->files[fd], vfs->data, size);
507
508         if (wsize == -1) {
509                 printf("write: error=%d (%s)\n", errno, strerror(errno));
510                 return NT_STATUS_UNSUCCESSFUL;
511         }
512
513         printf("write: ok\n");
514         return NT_STATUS_OK;
515 }
516
517
518 static NTSTATUS cmd_lseek(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
519 {
520         int fd, offset, whence;
521         off_t pos;
522
523         if (argc != 4) {
524                 printf("Usage: lseek <fd> <offset> <whence>\n...where whence is 1 => SEEK_SET, 2 => SEEK_CUR, 3 => SEEK_END\n");
525                 return NT_STATUS_OK;
526         }
527
528         fd = atoi(argv[1]);
529         offset = atoi(argv[2]);
530         whence = atoi(argv[3]);
531         switch (whence) {
532                 case 1:         whence = SEEK_SET; break;
533                 case 2:         whence = SEEK_CUR; break;
534                 default:        whence = SEEK_END;
535         }
536
537         pos = SMB_VFS_LSEEK(vfs->files[fd], offset, whence);
538         if (pos == (off_t)-1) {
539                 printf("lseek: error=%d (%s)\n", errno, strerror(errno));
540                 return NT_STATUS_UNSUCCESSFUL;
541         }
542
543         printf("lseek: ok\n");
544         return NT_STATUS_OK;
545 }
546
547
548 static NTSTATUS cmd_rename(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
549 {
550         int ret;
551         struct smb_filename *smb_fname_src = NULL;
552         struct smb_filename *smb_fname_dst = NULL;
553
554         if (argc != 3) {
555                 printf("Usage: rename <old> <new>\n");
556                 return NT_STATUS_OK;
557         }
558
559         smb_fname_src = synthetic_smb_fname_split(mem_ctx, argv[1], NULL);
560         if (smb_fname_src == NULL) {
561                 return NT_STATUS_NO_MEMORY;
562         }
563
564         smb_fname_dst = synthetic_smb_fname_split(mem_ctx, argv[2], NULL);
565         if (smb_fname_dst == NULL) {
566                 TALLOC_FREE(smb_fname_src);
567                 return NT_STATUS_NO_MEMORY;
568         }
569
570         ret = SMB_VFS_RENAME(vfs->conn, smb_fname_src, smb_fname_dst);
571         TALLOC_FREE(smb_fname_src);
572         TALLOC_FREE(smb_fname_dst);
573         if (ret == -1) {
574                 printf("rename: error=%d (%s)\n", errno, strerror(errno));
575                 return NT_STATUS_UNSUCCESSFUL;
576         }
577
578         printf("rename: ok\n");
579         return NT_STATUS_OK;
580 }
581
582
583 static NTSTATUS cmd_fsync(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
584 {
585         int ret, fd;
586         if (argc != 2) {
587                 printf("Usage: fsync <fd>\n");
588                 return NT_STATUS_OK;
589         }
590
591         fd = atoi(argv[1]);
592         ret = SMB_VFS_FSYNC(vfs->files[fd]);
593         if (ret == -1) {
594                 printf("fsync: error=%d (%s)\n", errno, strerror(errno));
595                 return NT_STATUS_UNSUCCESSFUL;
596         }
597
598         printf("fsync: ok\n");
599         return NT_STATUS_OK;
600 }
601
602
603 static NTSTATUS cmd_stat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
604 {
605         int ret;
606         const char *user;
607         const char *group;
608         struct passwd *pwd = NULL;
609         struct group *grp = NULL;
610         struct smb_filename *smb_fname = NULL;
611         SMB_STRUCT_STAT st;
612         time_t tmp_time;
613         NTSTATUS status;
614
615         if (argc != 2) {
616                 printf("Usage: stat <fname>\n");
617                 return NT_STATUS_OK;
618         }
619
620         status = create_synthetic_smb_fname_split(mem_ctx, argv[1], NULL,
621                                                   &smb_fname);
622         if (!NT_STATUS_IS_OK(status)) {
623                 return status;
624         }
625
626         ret = SMB_VFS_STAT(vfs->conn, smb_fname);
627         if (ret == -1) {
628                 printf("stat: error=%d (%s)\n", errno, strerror(errno));
629                 TALLOC_FREE(smb_fname);
630                 return NT_STATUS_UNSUCCESSFUL;
631         }
632         st = smb_fname->st;
633         TALLOC_FREE(smb_fname);
634
635         pwd = getpwuid(st.st_ex_uid);
636         if (pwd != NULL) user = pwd->pw_name;
637         else user = null_string;
638         grp = getgrgid(st.st_ex_gid);
639         if (grp != NULL) group = grp->gr_name;
640         else group = null_string;
641
642         printf("stat: ok\n");
643         printf("  File: %s", argv[1]);
644         if (S_ISREG(st.st_ex_mode)) printf("  Regular File\n");
645         else if (S_ISDIR(st.st_ex_mode)) printf("  Directory\n");
646         else if (S_ISCHR(st.st_ex_mode)) printf("  Character Device\n");
647         else if (S_ISBLK(st.st_ex_mode)) printf("  Block Device\n");
648         else if (S_ISFIFO(st.st_ex_mode)) printf("  Fifo\n");
649         else if (S_ISLNK(st.st_ex_mode)) printf("  Symbolic Link\n");
650         else if (S_ISSOCK(st.st_ex_mode)) printf("  Socket\n");
651         printf("  Size: %10u", (unsigned int)st.st_ex_size);
652 #ifdef HAVE_STAT_ST_BLOCKS
653         printf(" Blocks: %9u", (unsigned int)st.st_ex_blocks);
654 #endif
655 #ifdef HAVE_STAT_ST_BLKSIZE
656         printf(" IO Block: %u\n", (unsigned int)st.st_ex_blksize);
657 #endif
658         printf("  Device: 0x%10x", (unsigned int)st.st_ex_dev);
659         printf(" Inode: %10u", (unsigned int)st.st_ex_ino);
660         printf(" Links: %10u\n", (unsigned int)st.st_ex_nlink);
661         printf("  Access: %05o", (int)((st.st_ex_mode) & 007777));
662         printf(" Uid: %5lu/%.16s Gid: %5lu/%.16s\n", (unsigned long)st.st_ex_uid, user,
663                (unsigned long)st.st_ex_gid, group);
664         tmp_time = convert_timespec_to_time_t(st.st_ex_atime);
665         printf("  Access: %s", ctime(&tmp_time));
666         tmp_time = convert_timespec_to_time_t(st.st_ex_mtime);
667         printf("  Modify: %s", ctime(&tmp_time));
668         tmp_time = convert_timespec_to_time_t(st.st_ex_ctime);
669         printf("  Change: %s", ctime(&tmp_time));
670
671         return NT_STATUS_OK;
672 }
673
674
675 static NTSTATUS cmd_fstat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
676 {
677         int fd;
678         const char *user;
679         const char *group;
680         struct passwd *pwd = NULL;
681         struct group *grp = NULL;
682         SMB_STRUCT_STAT st;
683         time_t tmp_time;
684
685         if (argc != 2) {
686                 printf("Usage: fstat <fd>\n");
687                 return NT_STATUS_OK;
688         }
689
690         fd = atoi(argv[1]);
691         if (fd < 0 || fd >= 1024) {
692                 printf("fstat: error=%d (file descriptor out of range)\n", EBADF);
693                 return NT_STATUS_OK;
694         }
695
696         if (vfs->files[fd] == NULL) {
697                 printf("fstat: error=%d (invalid file descriptor)\n", EBADF);
698                 return NT_STATUS_OK;
699         }
700
701         if (SMB_VFS_FSTAT(vfs->files[fd], &st) == -1) {
702                 printf("fstat: error=%d (%s)\n", errno, strerror(errno));
703                 return NT_STATUS_UNSUCCESSFUL;
704         }
705
706         pwd = getpwuid(st.st_ex_uid);
707         if (pwd != NULL) user = pwd->pw_name;
708         else user = null_string;
709         grp = getgrgid(st.st_ex_gid);
710         if (grp != NULL) group = grp->gr_name;
711         else group = null_string;
712
713         printf("fstat: ok\n");
714         if (S_ISREG(st.st_ex_mode)) printf("  Regular File\n");
715         else if (S_ISDIR(st.st_ex_mode)) printf("  Directory\n");
716         else if (S_ISCHR(st.st_ex_mode)) printf("  Character Device\n");
717         else if (S_ISBLK(st.st_ex_mode)) printf("  Block Device\n");
718         else if (S_ISFIFO(st.st_ex_mode)) printf("  Fifo\n");
719         else if (S_ISLNK(st.st_ex_mode)) printf("  Symbolic Link\n");
720         else if (S_ISSOCK(st.st_ex_mode)) printf("  Socket\n");
721         printf("  Size: %10u", (unsigned int)st.st_ex_size);
722 #ifdef HAVE_STAT_ST_BLOCKS
723         printf(" Blocks: %9u", (unsigned int)st.st_ex_blocks);
724 #endif
725 #ifdef HAVE_STAT_ST_BLKSIZE
726         printf(" IO Block: %u\n", (unsigned int)st.st_ex_blksize);
727 #endif
728         printf("  Device: 0x%10x", (unsigned int)st.st_ex_dev);
729         printf(" Inode: %10u", (unsigned int)st.st_ex_ino);
730         printf(" Links: %10u\n", (unsigned int)st.st_ex_nlink);
731         printf("  Access: %05o", (int)((st.st_ex_mode) & 007777));
732         printf(" Uid: %5lu/%.16s Gid: %5lu/%.16s\n", (unsigned long)st.st_ex_uid, user,
733                (unsigned long)st.st_ex_gid, group);
734         tmp_time = convert_timespec_to_time_t(st.st_ex_atime);
735         printf("  Access: %s", ctime(&tmp_time));
736         tmp_time = convert_timespec_to_time_t(st.st_ex_mtime);
737         printf("  Modify: %s", ctime(&tmp_time));
738         tmp_time = convert_timespec_to_time_t(st.st_ex_ctime);
739         printf("  Change: %s", ctime(&tmp_time));
740
741         return NT_STATUS_OK;
742 }
743
744
745 static NTSTATUS cmd_lstat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
746 {
747         const char *user;
748         const char *group;
749         struct passwd *pwd = NULL;
750         struct group *grp = NULL;
751         struct smb_filename *smb_fname = NULL;
752         SMB_STRUCT_STAT st;
753         time_t tmp_time;
754         NTSTATUS status;
755
756         if (argc != 2) {
757                 printf("Usage: lstat <path>\n");
758                 return NT_STATUS_OK;
759         }
760
761         status = create_synthetic_smb_fname_split(mem_ctx, argv[1], NULL,
762                                                   &smb_fname);
763         if (!NT_STATUS_IS_OK(status)) {
764                 return status;
765         }
766
767         if (SMB_VFS_LSTAT(vfs->conn, smb_fname) == -1) {
768                 printf("lstat: error=%d (%s)\n", errno, strerror(errno));
769                 TALLOC_FREE(smb_fname);
770                 return NT_STATUS_UNSUCCESSFUL;
771         }
772         st = smb_fname->st;
773         TALLOC_FREE(smb_fname);
774
775         pwd = getpwuid(st.st_ex_uid);
776         if (pwd != NULL) user = pwd->pw_name;
777         else user = null_string;
778         grp = getgrgid(st.st_ex_gid);
779         if (grp != NULL) group = grp->gr_name;
780         else group = null_string;
781
782         printf("lstat: ok\n");
783         if (S_ISREG(st.st_ex_mode)) printf("  Regular File\n");
784         else if (S_ISDIR(st.st_ex_mode)) printf("  Directory\n");
785         else if (S_ISCHR(st.st_ex_mode)) printf("  Character Device\n");
786         else if (S_ISBLK(st.st_ex_mode)) printf("  Block Device\n");
787         else if (S_ISFIFO(st.st_ex_mode)) printf("  Fifo\n");
788         else if (S_ISLNK(st.st_ex_mode)) printf("  Symbolic Link\n");
789         else if (S_ISSOCK(st.st_ex_mode)) printf("  Socket\n");
790         printf("  Size: %10u", (unsigned int)st.st_ex_size);
791 #ifdef HAVE_STAT_ST_BLOCKS
792         printf(" Blocks: %9u", (unsigned int)st.st_ex_blocks);
793 #endif
794 #ifdef HAVE_STAT_ST_BLKSIZE
795         printf(" IO Block: %u\n", (unsigned int)st.st_ex_blksize);
796 #endif
797         printf("  Device: 0x%10x", (unsigned int)st.st_ex_dev);
798         printf(" Inode: %10u", (unsigned int)st.st_ex_ino);
799         printf(" Links: %10u\n", (unsigned int)st.st_ex_nlink);
800         printf("  Access: %05o", (int)((st.st_ex_mode) & 007777));
801         printf(" Uid: %5lu/%.16s Gid: %5lu/%.16s\n", (unsigned long)st.st_ex_uid, user,
802                (unsigned long)st.st_ex_gid, group);
803         tmp_time = convert_timespec_to_time_t(st.st_ex_atime);
804         printf("  Access: %s", ctime(&tmp_time));
805         tmp_time = convert_timespec_to_time_t(st.st_ex_mtime);
806         printf("  Modify: %s", ctime(&tmp_time));
807         tmp_time = convert_timespec_to_time_t(st.st_ex_ctime);
808         printf("  Change: %s", ctime(&tmp_time));
809
810         return NT_STATUS_OK;
811 }
812
813
814 static NTSTATUS cmd_chmod(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
815 {
816         mode_t mode;
817         if (argc != 3) {
818                 printf("Usage: chmod <path> <mode>\n");
819                 return NT_STATUS_OK;
820         }
821
822         mode = atoi(argv[2]);
823         if (SMB_VFS_CHMOD(vfs->conn, argv[1], mode) == -1) {
824                 printf("chmod: error=%d (%s)\n", errno, strerror(errno));
825                 return NT_STATUS_UNSUCCESSFUL;
826         }
827
828         printf("chmod: ok\n");
829         return NT_STATUS_OK;
830 }
831
832
833 static NTSTATUS cmd_fchmod(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
834 {
835         int fd;
836         mode_t mode;
837         if (argc != 3) {
838                 printf("Usage: fchmod <fd> <mode>\n");
839                 return NT_STATUS_OK;
840         }
841
842         fd = atoi(argv[1]);
843         mode = atoi(argv[2]);
844         if (fd < 0 || fd >= 1024) {
845                 printf("fchmod: error=%d (file descriptor out of range)\n", EBADF);
846                 return NT_STATUS_OK;
847         }
848         if (vfs->files[fd] == NULL) {
849                 printf("fchmod: error=%d (invalid file descriptor)\n", EBADF);
850                 return NT_STATUS_OK;
851         }
852
853         if (SMB_VFS_FCHMOD(vfs->files[fd], mode) == -1) {
854                 printf("fchmod: error=%d (%s)\n", errno, strerror(errno));
855                 return NT_STATUS_UNSUCCESSFUL;
856         }
857
858         printf("fchmod: ok\n");
859         return NT_STATUS_OK;
860 }
861
862
863 static NTSTATUS cmd_chmod_acl(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
864 {
865         mode_t mode;
866         if (argc != 3) {
867                 printf("Usage: chmod_acl <path> <mode>\n");
868                 return NT_STATUS_OK;
869         }
870
871         mode = atoi(argv[2]);
872         if (SMB_VFS_CHMOD_ACL(vfs->conn, argv[1], mode) == -1) {
873                 printf("chmod_acl: error=%d (%s)\n", errno, strerror(errno));
874                 return NT_STATUS_UNSUCCESSFUL;
875         }
876
877         printf("chmod_acl: ok\n");
878         return NT_STATUS_OK;
879 }
880
881
882 static NTSTATUS cmd_fchmod_acl(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
883 {
884         int fd;
885         mode_t mode;
886         if (argc != 3) {
887                 printf("Usage: fchmod_acl <fd> <mode>\n");
888                 return NT_STATUS_OK;
889         }
890
891         fd = atoi(argv[1]);
892         mode = atoi(argv[2]);
893         if (fd < 0 || fd >= 1024) {
894                 printf("fchmod_acl: error=%d (file descriptor out of range)\n", EBADF);
895                 return NT_STATUS_OK;
896         }
897         if (vfs->files[fd] == NULL) {
898                 printf("fchmod_acl: error=%d (invalid file descriptor)\n", EBADF);
899                 return NT_STATUS_OK;
900         }
901
902         if (SMB_VFS_FCHMOD_ACL(vfs->files[fd], mode) == -1) {
903                 printf("fchmod_acl: error=%d (%s)\n", errno, strerror(errno));
904                 return NT_STATUS_UNSUCCESSFUL;
905         }
906
907         printf("fchmod_acl: ok\n");
908         return NT_STATUS_OK;
909 }
910
911
912 static NTSTATUS cmd_chown(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
913 {
914         uid_t uid;
915         gid_t gid;
916         if (argc != 4) {
917                 printf("Usage: chown <path> <uid> <gid>\n");
918                 return NT_STATUS_OK;
919         }
920
921         uid = atoi(argv[2]);
922         gid = atoi(argv[3]);
923         if (SMB_VFS_CHOWN(vfs->conn, argv[1], uid, gid) == -1) {
924                 printf("chown: error=%d (%s)\n", errno, strerror(errno));
925                 return NT_STATUS_UNSUCCESSFUL;
926         }
927
928         printf("chown: ok\n");
929         return NT_STATUS_OK;
930 }
931
932
933 static NTSTATUS cmd_fchown(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
934 {
935         uid_t uid;
936         gid_t gid;
937         int fd;
938         if (argc != 4) {
939                 printf("Usage: fchown <fd> <uid> <gid>\n");
940                 return NT_STATUS_OK;
941         }
942
943         uid = atoi(argv[2]);
944         gid = atoi(argv[3]);
945         fd = atoi(argv[1]);
946         if (fd < 0 || fd >= 1024) {
947                 printf("fchown: faliure=%d (file descriptor out of range)\n", EBADF);
948                 return NT_STATUS_OK;
949         }
950         if (vfs->files[fd] == NULL) {
951                 printf("fchown: error=%d (invalid file descriptor)\n", EBADF);
952                 return NT_STATUS_OK;
953         }
954         if (SMB_VFS_FCHOWN(vfs->files[fd], uid, gid) == -1) {
955                 printf("fchown error=%d (%s)\n", errno, strerror(errno));
956                 return NT_STATUS_UNSUCCESSFUL;
957         }
958
959         printf("fchown: ok\n");
960         return NT_STATUS_OK;
961 }
962
963
964 static NTSTATUS cmd_getwd(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
965 {
966         char *buf = SMB_VFS_GETWD(vfs->conn);
967         if (buf == NULL) {
968                 printf("getwd: error=%d (%s)\n", errno, strerror(errno));
969                 return NT_STATUS_UNSUCCESSFUL;
970         }
971
972         printf("getwd: %s\n", buf);
973         SAFE_FREE(buf);
974         return NT_STATUS_OK;
975 }
976
977 static NTSTATUS cmd_utime(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
978 {
979         struct smb_file_time ft;
980         struct smb_filename *smb_fname = NULL;
981         NTSTATUS status;
982
983         if (argc != 4) {
984                 printf("Usage: utime <path> <access> <modify>\n");
985                 return NT_STATUS_OK;
986         }
987
988         ZERO_STRUCT(ft);
989
990         ft.atime = convert_time_t_to_timespec(atoi(argv[2]));
991         ft.mtime = convert_time_t_to_timespec(atoi(argv[3]));
992
993         status = create_synthetic_smb_fname_split(mem_ctx, argv[1],
994                                                   NULL, &smb_fname);
995         if (!NT_STATUS_IS_OK(status)) {
996                 return status;
997         }
998
999         if (SMB_VFS_NTIMES(vfs->conn, smb_fname, &ft) != 0) {
1000                 printf("utime: error=%d (%s)\n", errno, strerror(errno));
1001                 TALLOC_FREE(smb_fname);
1002                 return NT_STATUS_UNSUCCESSFUL;
1003         }
1004
1005         TALLOC_FREE(smb_fname);
1006         printf("utime: ok\n");
1007         return NT_STATUS_OK;
1008 }
1009
1010 static NTSTATUS cmd_ftruncate(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
1011 {
1012         int fd;
1013         off_t off;
1014         if (argc != 3) {
1015                 printf("Usage: ftruncate <fd> <length>\n");
1016                 return NT_STATUS_OK;
1017         }
1018
1019         fd = atoi(argv[1]);
1020         off = atoi(argv[2]);
1021         if (fd < 0 || fd >= 1024) {
1022                 printf("ftruncate: error=%d (file descriptor out of range)\n", EBADF);
1023                 return NT_STATUS_OK;
1024         }
1025         if (vfs->files[fd] == NULL) {
1026                 printf("ftruncate: error=%d (invalid file descriptor)\n", EBADF);
1027                 return NT_STATUS_OK;
1028         }
1029
1030         if (SMB_VFS_FTRUNCATE(vfs->files[fd], off) == -1) {
1031                 printf("ftruncate: error=%d (%s)\n", errno, strerror(errno));
1032                 return NT_STATUS_UNSUCCESSFUL;
1033         }
1034
1035         printf("ftruncate: ok\n");
1036         return NT_STATUS_OK;
1037 }
1038
1039 static NTSTATUS cmd_lock(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
1040 {
1041         int fd;
1042         int op;
1043         long offset;
1044         long count;
1045         int type;
1046         const char *typestr;
1047
1048         if (argc != 6) {
1049                 printf("Usage: lock <fd> <op> <offset> <count> <type>\n");
1050                 printf("  ops: G = F_GETLK\n");
1051                 printf("       S = F_SETLK\n");
1052                 printf("       W = F_SETLKW\n");
1053                 printf("  type: R = F_RDLCK\n");
1054                 printf("        W = F_WRLCK\n");
1055                 printf("        U = F_UNLCK\n");
1056                 return NT_STATUS_OK;
1057         }
1058
1059         if (sscanf(argv[1], "%d", &fd) == 0) {
1060                 printf("lock: error=-1 (error parsing fd)\n");
1061                 return NT_STATUS_UNSUCCESSFUL;
1062         }
1063
1064         op = 0;
1065         switch (*argv[2]) {
1066         case 'G':
1067                 op = F_GETLK;
1068                 break;
1069         case 'S':
1070                 op = F_SETLK;
1071                 break;
1072         case 'W':
1073                 op = F_SETLKW;
1074                 break;
1075         default:
1076                 printf("lock: error=-1 (invalid op flag!)\n");
1077                 return NT_STATUS_UNSUCCESSFUL;
1078         }
1079
1080         if (sscanf(argv[3], "%ld", &offset) == 0) {
1081                 printf("lock: error=-1 (error parsing fd)\n");
1082                 return NT_STATUS_UNSUCCESSFUL;
1083         }
1084
1085         if (sscanf(argv[4], "%ld", &count) == 0) {
1086                 printf("lock: error=-1 (error parsing fd)\n");
1087                 return NT_STATUS_UNSUCCESSFUL;
1088         }
1089
1090         type = 0;
1091         typestr = argv[5];
1092         while(*typestr) {
1093                 switch (*typestr) {
1094                 case 'R':
1095                         type |= F_RDLCK;
1096                         break;
1097                 case 'W':
1098                         type |= F_WRLCK;
1099                         break;
1100                 case 'U':
1101                         type |= F_UNLCK;
1102                         break;
1103                 default:
1104                         printf("lock: error=-1 (invalid type flag!)\n");
1105                         return NT_STATUS_UNSUCCESSFUL;
1106                 }
1107                 typestr++;
1108         }
1109
1110         printf("lock: debug lock(fd=%d, op=%d, offset=%ld, count=%ld, type=%d))\n", fd, op, offset, count, type);
1111
1112         if (SMB_VFS_LOCK(vfs->files[fd], op, offset, count, type) == False) {
1113                 printf("lock: error=%d (%s)\n", errno, strerror(errno));
1114                 return NT_STATUS_UNSUCCESSFUL;
1115         }
1116
1117         printf("lock: ok\n");
1118         return NT_STATUS_OK;
1119 }
1120
1121 static NTSTATUS cmd_symlink(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
1122 {
1123         if (argc != 3) {
1124                 printf("Usage: symlink <path> <link>\n");
1125                 return NT_STATUS_OK;
1126         }
1127
1128         if (SMB_VFS_SYMLINK(vfs->conn, argv[1], argv[2]) == -1) {
1129                 printf("symlink: error=%d (%s)\n", errno, strerror(errno));
1130                 return NT_STATUS_UNSUCCESSFUL;
1131         }
1132
1133         printf("symlink: ok\n");
1134         return NT_STATUS_OK;
1135 }
1136
1137
1138 static NTSTATUS cmd_readlink(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
1139 {
1140         char buffer[PATH_MAX];
1141         int size;
1142
1143         if (argc != 2) {
1144                 printf("Usage: readlink <path>\n");
1145                 return NT_STATUS_OK;
1146         }
1147
1148         if ((size = SMB_VFS_READLINK(vfs->conn, argv[1], buffer, PATH_MAX)) == -1) {
1149                 printf("readlink: error=%d (%s)\n", errno, strerror(errno));
1150                 return NT_STATUS_UNSUCCESSFUL;
1151         }
1152
1153         buffer[size] = '\0';
1154         printf("readlink: %s\n", buffer);
1155         return NT_STATUS_OK;
1156 }
1157
1158
1159 static NTSTATUS cmd_link(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
1160 {
1161         if (argc != 3) {
1162                 printf("Usage: link <path> <link>\n");
1163                 return NT_STATUS_OK;
1164         }
1165
1166         if (SMB_VFS_LINK(vfs->conn, argv[1], argv[2]) == -1) {
1167                 printf("link: error=%d (%s)\n", errno, strerror(errno));
1168                 return NT_STATUS_UNSUCCESSFUL;
1169         }
1170
1171         printf("link: ok\n");
1172         return NT_STATUS_OK;
1173 }
1174
1175 static NTSTATUS cmd_mknod(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
1176 {
1177         mode_t mode;
1178         unsigned int dev_val;
1179         SMB_DEV_T dev;
1180
1181         if (argc != 4) {
1182                 printf("Usage: mknod <path> <mode> <dev>\n");
1183                 printf("  mode is octal\n");
1184                 printf("  dev is hex\n");
1185                 return NT_STATUS_OK;
1186         }
1187
1188         if (sscanf(argv[2], "%ho", (unsigned short *)&mode) == 0) {
1189                 printf("open: error=-1 (invalid mode!)\n");
1190                 return NT_STATUS_UNSUCCESSFUL;
1191         }
1192
1193         if (sscanf(argv[3], "%x", &dev_val) == 0) {
1194                 printf("open: error=-1 (invalid dev!)\n");
1195                 return NT_STATUS_UNSUCCESSFUL;
1196         }
1197         dev = (SMB_DEV_T)dev_val;
1198
1199         if (SMB_VFS_MKNOD(vfs->conn, argv[1], mode, dev) == -1) {
1200                 printf("mknod: error=%d (%s)\n", errno, strerror(errno));
1201                 return NT_STATUS_UNSUCCESSFUL;
1202         }
1203
1204         printf("mknod: ok\n");
1205         return NT_STATUS_OK;
1206 }
1207
1208 static NTSTATUS cmd_realpath(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
1209 {
1210         if (argc != 2) {
1211                 printf("Usage: realpath <path>\n");
1212                 return NT_STATUS_OK;
1213         }
1214
1215         if (SMB_VFS_REALPATH(vfs->conn, argv[1]) == NULL) {
1216                 printf("realpath: error=%d (%s)\n", errno, strerror(errno));
1217                 return NT_STATUS_UNSUCCESSFUL;
1218         }
1219
1220         printf("realpath: ok\n");
1221         return NT_STATUS_OK;
1222 }
1223
1224 static NTSTATUS cmd_getxattr(struct vfs_state *vfs, TALLOC_CTX *mem_ctx,
1225                              int argc, const char **argv)
1226 {
1227         uint8_t *buf;
1228         ssize_t ret;
1229
1230         if (argc != 3) {
1231                 printf("Usage: getxattr <path> <xattr>\n");
1232                 return NT_STATUS_OK;
1233         }
1234
1235         buf = NULL;
1236
1237         ret = SMB_VFS_GETXATTR(vfs->conn, argv[1], argv[2], buf,
1238                                talloc_get_size(buf));
1239         if (ret == -1) {
1240                 int err = errno;
1241                 printf("getxattr returned (%s)\n", strerror(err));
1242                 return map_nt_error_from_unix(err);
1243         }
1244         buf = talloc_array(mem_ctx, uint8_t, ret);
1245         if (buf == NULL) {
1246                 return NT_STATUS_NO_MEMORY;
1247         }
1248         ret = SMB_VFS_GETXATTR(vfs->conn, argv[1], argv[2], buf,
1249                                talloc_get_size(buf));
1250         if (ret == -1) {
1251                 int err = errno;
1252                 printf("getxattr returned (%s)\n", strerror(err));
1253                 return map_nt_error_from_unix(err);
1254         }
1255         dump_data_file(buf, talloc_get_size(buf), false, stdout);
1256         return NT_STATUS_OK;
1257 }
1258
1259 static NTSTATUS cmd_listxattr(struct vfs_state *vfs, TALLOC_CTX *mem_ctx,
1260                               int argc, const char **argv)
1261 {
1262         char *buf, *p;
1263         ssize_t ret;
1264
1265         if (argc != 2) {
1266                 printf("Usage: listxattr <path>\n");
1267                 return NT_STATUS_OK;
1268         }
1269
1270         buf = NULL;
1271
1272         ret = SMB_VFS_LISTXATTR(vfs->conn, argv[1], buf, talloc_get_size(buf));
1273         if (ret == -1) {
1274                 int err = errno;
1275                 printf("listxattr returned (%s)\n", strerror(err));
1276                 return map_nt_error_from_unix(err);
1277         }
1278         buf = talloc_array(mem_ctx, char, ret);
1279         if (buf == NULL) {
1280                 return NT_STATUS_NO_MEMORY;
1281         }
1282         ret = SMB_VFS_LISTXATTR(vfs->conn, argv[1], buf, talloc_get_size(buf));
1283         if (ret == -1) {
1284                 int err = errno;
1285                 printf("listxattr returned (%s)\n", strerror(err));
1286                 return map_nt_error_from_unix(err);
1287         }
1288         if (ret == 0) {
1289                 return NT_STATUS_OK;
1290         }
1291         if (buf[ret-1] != '\0') {
1292                 printf("listxattr returned non 0-terminated strings\n");
1293                 return NT_STATUS_INTERNAL_ERROR;
1294         }
1295
1296         p = buf;
1297         while (p < buf+ret) {
1298                 printf("%s\n", p);
1299                 p = strchr(p, 0);
1300                 p += 1;
1301         }
1302         return NT_STATUS_OK;
1303 }
1304
1305 static NTSTATUS cmd_setxattr(struct vfs_state *vfs, TALLOC_CTX *mem_ctx,
1306                              int argc, const char **argv)
1307 {
1308         ssize_t ret;
1309         int flags = 0;
1310
1311         if ((argc < 4) || (argc > 5)) {
1312                 printf("Usage: setxattr <path> <xattr> <value> [flags]\n");
1313                 return NT_STATUS_OK;
1314         }
1315
1316         if (argc == 5) {
1317                 flags = atoi(argv[4]);
1318         }
1319
1320         ret = SMB_VFS_SETXATTR(vfs->conn, argv[1], argv[2],
1321                                argv[3], strlen(argv[3]), flags);
1322         if (ret == -1) {
1323                 int err = errno;
1324                 printf("setxattr returned (%s)\n", strerror(err));
1325                 return map_nt_error_from_unix(err);
1326         }
1327         return NT_STATUS_OK;
1328 }
1329
1330 static NTSTATUS cmd_removexattr(struct vfs_state *vfs, TALLOC_CTX *mem_ctx,
1331                                 int argc, const char **argv)
1332 {
1333         ssize_t ret;
1334
1335         if (argc != 3) {
1336                 printf("Usage: removexattr <path> <xattr>\n");
1337                 return NT_STATUS_OK;
1338         }
1339
1340         ret = SMB_VFS_REMOVEXATTR(vfs->conn, argv[1], argv[2]);
1341         if (ret == -1) {
1342                 int err = errno;
1343                 printf("removexattr returned (%s)\n", strerror(err));
1344                 return map_nt_error_from_unix(err);
1345         }
1346         return NT_STATUS_OK;
1347 }
1348
1349 static NTSTATUS cmd_fget_nt_acl(struct vfs_state *vfs, TALLOC_CTX *mem_ctx,
1350                                 int argc, const char **argv)
1351 {
1352         int fd;
1353         NTSTATUS status;
1354         struct security_descriptor *sd;
1355
1356         if (argc != 2) {
1357                 printf("Usage: fget_nt_acl <fd>\n");
1358                 return NT_STATUS_OK;
1359         }
1360
1361         fd = atoi(argv[1]);
1362         if (fd < 0 || fd >= 1024) {
1363                 printf("fget_nt_acl: error=%d (file descriptor out of range)\n", EBADF);
1364                 return NT_STATUS_OK;
1365         }
1366         if (vfs->files[fd] == NULL) {
1367                 printf("fget_nt_acl: error=%d (invalid file descriptor)\n", EBADF);
1368                 return NT_STATUS_OK;
1369         }
1370
1371         status = SMB_VFS_FGET_NT_ACL(vfs->files[fd],
1372                                      SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL,
1373                                      talloc_tos(), &sd);
1374         if (!NT_STATUS_IS_OK(status)) {
1375                 printf("fget_nt_acl returned (%s)\n", nt_errstr(status));
1376                 return status;
1377         }
1378         printf("%s\n", sddl_encode(talloc_tos(), sd, get_global_sam_sid()));
1379         TALLOC_FREE(sd);
1380         return NT_STATUS_OK;
1381 }
1382
1383 static NTSTATUS cmd_get_nt_acl(struct vfs_state *vfs, TALLOC_CTX *mem_ctx,
1384                                int argc, const char **argv)
1385 {
1386         NTSTATUS status;
1387         struct security_descriptor *sd;
1388
1389         if (argc != 2) {
1390                 printf("Usage: get_nt_acl <path>\n");
1391                 return NT_STATUS_OK;
1392         }
1393
1394         status = SMB_VFS_GET_NT_ACL(vfs->conn, argv[1],
1395                                     SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL,
1396                                     talloc_tos(), &sd);
1397         if (!NT_STATUS_IS_OK(status)) {
1398                 printf("get_nt_acl returned (%s)\n", nt_errstr(status));
1399                 return status;
1400         }
1401         printf("%s\n", sddl_encode(talloc_tos(), sd, get_global_sam_sid()));
1402         TALLOC_FREE(sd);
1403         return NT_STATUS_OK;
1404 }
1405
1406 static NTSTATUS cmd_fset_nt_acl(struct vfs_state *vfs, TALLOC_CTX *mem_ctx,
1407                                 int argc, const char **argv)
1408 {
1409         int fd;
1410         NTSTATUS status;
1411         struct security_descriptor *sd;
1412
1413         if (argc != 3) {
1414                 printf("Usage: fset_nt_acl <fd> <sddl>\n");
1415                 return NT_STATUS_OK;
1416         }
1417
1418         fd = atoi(argv[1]);
1419         if (fd < 0 || fd >= 1024) {
1420                 printf("fset_nt_acl: error=%d (file descriptor out of range)\n", EBADF);
1421                 return NT_STATUS_OK;
1422         }
1423         if (vfs->files[fd] == NULL) {
1424                 printf("fset_nt_acl: error=%d (invalid file descriptor)\n", EBADF);
1425                 return NT_STATUS_OK;
1426         }
1427
1428         sd = sddl_decode(talloc_tos(), argv[2], get_global_sam_sid());
1429         if (!sd) {
1430                 printf("sddl_decode failed to parse %s as SDDL\n", argv[2]);
1431                 return NT_STATUS_INVALID_PARAMETER;
1432         }
1433
1434         status = SMB_VFS_FSET_NT_ACL(vfs->files[fd], SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL, sd);
1435         if (!NT_STATUS_IS_OK(status)) {
1436                 printf("fset_nt_acl returned (%s)\n", nt_errstr(status));
1437                 return status;
1438         }
1439         TALLOC_FREE(sd);
1440         return NT_STATUS_OK;
1441 }
1442
1443 static NTSTATUS cmd_set_nt_acl(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
1444 {
1445         int flags;
1446         int ret;
1447         mode_t mode;
1448         files_struct *fsp;
1449         struct smb_filename *smb_fname = NULL;
1450         NTSTATUS status;
1451         struct security_descriptor *sd = NULL;
1452
1453         if (argc != 3) {
1454                 printf("Usage: set_nt_acl <file> <sddl>\n");
1455                 return NT_STATUS_OK;
1456         }
1457
1458         mode = 00400;
1459
1460         fsp = talloc_zero(vfs, struct files_struct);
1461         if (fsp == NULL) {
1462                 return NT_STATUS_NO_MEMORY;
1463         }
1464         fsp->fh = talloc_zero(fsp, struct fd_handle);
1465         if (fsp->fh == NULL) {
1466                 TALLOC_FREE(fsp);
1467                 return NT_STATUS_NO_MEMORY;
1468         }
1469         fsp->conn = vfs->conn;
1470
1471         status = create_synthetic_smb_fname_split(NULL, argv[1], NULL,
1472                                                   &smb_fname);
1473         if (!NT_STATUS_IS_OK(status)) {
1474                 TALLOC_FREE(fsp);
1475                 return status;
1476         }
1477
1478         fsp->fsp_name = smb_fname;
1479
1480 #ifdef O_DIRECTORY
1481         flags = O_RDONLY|O_DIRECTORY;
1482 #else
1483         /* POSIX allows us to open a directory with O_RDONLY. */
1484         flags = O_RDONLY;
1485 #endif
1486
1487         fsp->fh->fd = SMB_VFS_OPEN(vfs->conn, smb_fname, fsp, O_RDWR, mode);
1488         if (fsp->fh->fd == -1 && errno == EISDIR) {
1489                 fsp->fh->fd = SMB_VFS_OPEN(vfs->conn, smb_fname, fsp, flags, mode);
1490         }
1491         if (fsp->fh->fd == -1) {
1492                 printf("open: error=%d (%s)\n", errno, strerror(errno));
1493                 TALLOC_FREE(fsp);
1494                 TALLOC_FREE(smb_fname);
1495                 return NT_STATUS_UNSUCCESSFUL;
1496         }
1497
1498         ret = SMB_VFS_FSTAT(fsp, &smb_fname->st);
1499         if (ret == -1) {
1500                 /* If we have an fd, this stat should succeed. */
1501                 DEBUG(0,("Error doing fstat on open file %s "
1502                          "(%s)\n",
1503                          smb_fname_str_dbg(smb_fname),
1504                          strerror(errno) ));
1505                 status = map_nt_error_from_unix(errno);
1506         }
1507         
1508         if (!NT_STATUS_IS_OK(status)) {
1509                 goto out;
1510         }
1511
1512         fsp->file_id = vfs_file_id_from_sbuf(vfs->conn, &smb_fname->st);
1513         fsp->vuid = UID_FIELD_INVALID;
1514         fsp->file_pid = 0;
1515         fsp->can_lock = True;
1516         fsp->can_read = True;
1517         fsp->can_write = True;
1518         fsp->print_file = NULL;
1519         fsp->modified = False;
1520         fsp->sent_oplock_break = NO_BREAK_SENT;
1521         fsp->is_directory = S_ISDIR(smb_fname->st.st_ex_mode);
1522
1523
1524         sd = sddl_decode(talloc_tos(), argv[2], get_global_sam_sid());
1525         if (!sd) {
1526                 printf("sddl_decode failed to parse %s as SDDL\n", argv[2]);
1527                 status = NT_STATUS_INVALID_PARAMETER;
1528                 goto out;
1529         }
1530
1531         status = SMB_VFS_FSET_NT_ACL(fsp, SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL, sd);
1532         if (!NT_STATUS_IS_OK(status)) {
1533                 printf("fset_nt_acl returned (%s)\n", nt_errstr(status));
1534                 goto out;
1535         }
1536 out:
1537         TALLOC_FREE(sd);
1538
1539         ret = SMB_VFS_CLOSE(fsp);
1540         if (ret == -1 )
1541                 printf("close: error=%d (%s)\n", errno, strerror(errno));
1542
1543         TALLOC_FREE(fsp);
1544
1545         return status;
1546 }
1547
1548
1549
1550 static NTSTATUS cmd_sys_acl_get_fd(struct vfs_state *vfs, TALLOC_CTX *mem_ctx,
1551                                    int argc, const char **argv)
1552 {
1553         int fd;
1554         NTSTATUS status;
1555         SMB_ACL_T acl;
1556         char *acl_text;
1557
1558         if (argc != 2) {
1559                 printf("Usage: sys_acl_get_fd <fd>\n");
1560                 return NT_STATUS_OK;
1561         }
1562
1563         fd = atoi(argv[1]);
1564         if (fd < 0 || fd >= 1024) {
1565                 printf("sys_acl_get_fd: error=%d (file descriptor out of range)\n", EBADF);
1566                 return NT_STATUS_OK;
1567         }
1568         if (vfs->files[fd] == NULL) {
1569                 printf("sys_acl_get_fd: error=%d (invalid file descriptor)\n", EBADF);
1570                 return NT_STATUS_OK;
1571         }
1572
1573         acl = SMB_VFS_SYS_ACL_GET_FD(vfs->files[fd], talloc_tos());
1574         if (!acl) {
1575                 printf("sys_acl_get_fd failed (%s)\n", strerror(errno));
1576                 return status;
1577         }
1578         acl_text = sys_acl_to_text(acl, NULL);
1579         printf("%s", acl_text);
1580         TALLOC_FREE(acl);
1581         SAFE_FREE(acl_text);
1582         return NT_STATUS_OK;
1583 }
1584
1585 static NTSTATUS cmd_sys_acl_get_file(struct vfs_state *vfs, TALLOC_CTX *mem_ctx,
1586                                      int argc, const char **argv)
1587 {
1588         NTSTATUS status;
1589         SMB_ACL_T acl;
1590         char *acl_text;
1591         int type;
1592         if (argc != 3) {
1593                 printf("Usage: sys_acl_get_file <path> <type>\n");
1594                 return NT_STATUS_OK;
1595         }
1596
1597         type = atoi(argv[2]);
1598         acl = SMB_VFS_SYS_ACL_GET_FILE(vfs->conn, argv[1], type, talloc_tos());
1599         if (!acl) {
1600                 printf("sys_acl_get_file failed (%s)\n", strerror(errno));
1601                 return status;
1602         }
1603         acl_text = sys_acl_to_text(acl, NULL);
1604         printf("%s", acl_text);
1605         TALLOC_FREE(acl);
1606         SAFE_FREE(acl_text);
1607         return NT_STATUS_OK;
1608 }
1609
1610 static NTSTATUS cmd_sys_acl_blob_get_file(struct vfs_state *vfs,
1611                                           TALLOC_CTX *mem_ctx,
1612                                           int argc, const char **argv)
1613 {
1614         char *description;
1615         DATA_BLOB blob;
1616         int ret;
1617         size_t i;
1618
1619         if (argc != 2) {
1620                 printf("Usage: sys_acl_get_file <path>\n");
1621                 return NT_STATUS_OK;
1622         }
1623
1624         ret = SMB_VFS_SYS_ACL_BLOB_GET_FILE(vfs->conn, argv[1], talloc_tos(),
1625                                             &description, &blob);
1626         if (ret != 0) {
1627                 printf("sys_acl_blob_get_file failed (%s)\n", strerror(errno));
1628                 return map_nt_error_from_unix(errno);
1629         }
1630         printf("Description: %s\n", description);
1631         for (i = 0; i < blob.length; i++) {
1632                 printf("%.2x ", blob.data[i]);
1633         }
1634         printf("\n");
1635
1636         return NT_STATUS_OK;
1637 }
1638
1639 static NTSTATUS cmd_sys_acl_blob_get_fd(struct vfs_state *vfs,
1640                                         TALLOC_CTX *mem_ctx,
1641                                         int argc, const char **argv)
1642 {
1643         int fd;
1644         char *description;
1645         DATA_BLOB blob;
1646         int ret;
1647         size_t i;
1648
1649         if (argc != 2) {
1650                 printf("Usage: sys_acl_blob_get_fd <fd>\n");
1651                 return NT_STATUS_OK;
1652         }
1653
1654         fd = atoi(argv[1]);
1655         if (fd < 0 || fd >= 1024) {
1656                 printf("sys_acl_blob_get_fd: error=%d "
1657                        "(file descriptor out of range)\n", EBADF);
1658                 return NT_STATUS_OK;
1659         }
1660         if (vfs->files[fd] == NULL) {
1661                 printf("sys_acl_blob_get_fd: error=%d "
1662                        "(invalid file descriptor)\n", EBADF);
1663                 return NT_STATUS_OK;
1664         }
1665
1666         ret = SMB_VFS_SYS_ACL_BLOB_GET_FD(vfs->files[fd], talloc_tos(),
1667                                           &description, &blob);
1668         if (ret != 0) {
1669                 printf("sys_acl_blob_get_fd failed (%s)\n", strerror(errno));
1670                 return map_nt_error_from_unix(errno);
1671         }
1672         printf("Description: %s\n", description);
1673         for (i = 0; i < blob.length; i++) {
1674                 printf("%.2x ", blob.data[i]);
1675         }
1676         printf("\n");
1677
1678         return NT_STATUS_OK;
1679 }
1680
1681
1682
1683 static NTSTATUS cmd_sys_acl_delete_def_file(struct vfs_state *vfs, TALLOC_CTX *mem_ctx,
1684                                             int argc, const char **argv)
1685 {
1686         int ret;
1687
1688         if (argc != 2) {
1689                 printf("Usage: sys_acl_delete_def_file <path>\n");
1690                 return NT_STATUS_OK;
1691         }
1692
1693         ret = SMB_VFS_SYS_ACL_DELETE_DEF_FILE(vfs->conn, argv[1]);
1694         if (ret == -1) {
1695                 printf("sys_acl_delete_def_file failed (%s)\n", strerror(errno));
1696                 return NT_STATUS_UNSUCCESSFUL;
1697         }
1698         return NT_STATUS_OK;
1699 }
1700
1701 /* Afaik translate name was first introduced with vfs_catia, to be able
1702    to translate unix file/dir-names, containing invalid windows characters,
1703    to valid windows names.
1704    The used translation direction is always unix --> windows
1705 */
1706 static NTSTATUS cmd_translate_name(struct vfs_state *vfs, TALLOC_CTX *mem_ctx,
1707                                             int argc, const char **argv)
1708 {
1709         int ret;
1710         struct dirent *dent = NULL;
1711         SMB_STRUCT_STAT st;
1712         bool found = false;
1713         char *translated = NULL;
1714         NTSTATUS status;
1715
1716         if (argc != 2) {
1717                 DEBUG(0, ("Usage: translate_name unix_filename\n"));
1718                 return NT_STATUS_UNSUCCESSFUL;
1719         }
1720
1721         vfs->currentdir = SMB_VFS_OPENDIR(vfs->conn, ".", NULL, 0);
1722         if (vfs->currentdir == NULL) {
1723                 DEBUG(0, ("cmd_translate_name: opendir error=%d (%s)\n",
1724                           errno, strerror(errno)));
1725                 return NT_STATUS_UNSUCCESSFUL;
1726         }
1727
1728         while (true) {
1729                 dent = SMB_VFS_READDIR(vfs->conn, vfs->currentdir, &st);
1730                 if (dent == NULL) {
1731                         break;
1732                 }
1733                 if (strcmp (dent->d_name, argv[1]) == 0) {
1734                         found = true;
1735                         break;
1736                 }
1737         };
1738
1739         if (!found) {
1740                 DEBUG(0, ("cmd_translate_name: file '%s' not found.\n", 
1741                           argv[1]));
1742                 status = NT_STATUS_UNSUCCESSFUL;
1743                 goto cleanup;
1744         }
1745         status = SMB_VFS_TRANSLATE_NAME(vfs->conn, dent->d_name,
1746                                         vfs_translate_to_windows,
1747                                         talloc_tos(), &translated);
1748         if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
1749                 DEBUG(0, ("cmd_translate_name: file '%s' cannot be "
1750                           "translated\n", argv[1]));
1751                 TALLOC_FREE(translated);
1752                 goto cleanup;
1753         }
1754         /* translation success. But that could also mean
1755            that translating "aaa" to "aaa" was successful :-(
1756         */ 
1757         DEBUG(0, ("cmd_translate_name: file '%s' --> '%s'\n", 
1758                   argv[1], translated));
1759
1760         TALLOC_FREE(translated);
1761
1762 cleanup:
1763         ret = SMB_VFS_CLOSEDIR(vfs->conn, vfs->currentdir);
1764         if (ret == -1) {
1765                 DEBUG(0, ("cmd_translate_name: closedir failure: %s\n",
1766                           strerror(errno)));
1767                 return NT_STATUS_UNSUCCESSFUL;
1768         }
1769
1770         vfs->currentdir = NULL;
1771         return status;;
1772 }
1773
1774
1775 struct cmd_set vfs_commands[] = {
1776
1777         { "VFS Commands" },
1778
1779         { "load", cmd_load_module, "Load a module", "load <module.so>" },
1780         { "populate", cmd_populate, "Populate a data buffer", "populate <char> <size>" },
1781         { "showdata", cmd_show_data, "Show data currently in data buffer", "show_data [<offset> <len>]"},
1782         { "connect",   cmd_connect,   "VFS connect()",    "connect" },
1783         { "disconnect",   cmd_disconnect,   "VFS disconnect()",    "disconnect" },
1784         { "disk_free",   cmd_disk_free,   "VFS disk_free()",    "disk_free <path>" },
1785         { "opendir",   cmd_opendir,   "VFS opendir()",    "opendir <fname>" },
1786         { "readdir",   cmd_readdir,   "VFS readdir()",    "readdir" },
1787         { "mkdir",   cmd_mkdir,   "VFS mkdir()",    "mkdir <path>" },
1788         { "rmdir",   cmd_pathfunc,   "VFS rmdir()",    "rmdir <path>" },
1789         { "closedir",   cmd_closedir,   "VFS closedir()",    "closedir" },
1790         { "open",   cmd_open,   "VFS open()",    "open <fname>" },
1791         { "close",   cmd_close,   "VFS close()",    "close <fd>" },
1792         { "read",   cmd_read,   "VFS read()",    "read <fd> <size>" },
1793         { "write",   cmd_write,   "VFS write()",    "write <fd> <size>" },
1794         { "lseek",   cmd_lseek,   "VFS lseek()",    "lseek <fd> <offset> <whence>" },
1795         { "rename",   cmd_rename,   "VFS rename()",    "rename <old> <new>" },
1796         { "fsync",   cmd_fsync,   "VFS fsync()",    "fsync <fd>" },
1797         { "stat",   cmd_stat,   "VFS stat()",    "stat <fname>" },
1798         { "fstat",   cmd_fstat,   "VFS fstat()",    "fstat <fd>" },
1799         { "lstat",   cmd_lstat,   "VFS lstat()",    "lstat <fname>" },
1800         { "unlink",   cmd_pathfunc,   "VFS unlink()",    "unlink <fname>" },
1801         { "chmod",   cmd_chmod,   "VFS chmod()",    "chmod <path> <mode>" },
1802         { "fchmod",   cmd_fchmod,   "VFS fchmod()",    "fchmod <fd> <mode>" },
1803         { "chown",   cmd_chown,   "VFS chown()",    "chown <path> <uid> <gid>" },
1804         { "fchown",   cmd_fchown,   "VFS fchown()",    "fchown <fd> <uid> <gid>" },
1805         { "chdir",   cmd_pathfunc,   "VFS chdir()",    "chdir <path>" },
1806         { "getwd",   cmd_getwd,   "VFS getwd()",    "getwd" },
1807         { "utime",   cmd_utime,   "VFS utime()",    "utime <path> <access> <modify>" },
1808         { "ftruncate",   cmd_ftruncate,   "VFS ftruncate()",    "ftruncate <fd> <length>" },
1809         { "lock",   cmd_lock,   "VFS lock()",    "lock <f> <op> <offset> <count> <type>" },
1810         { "symlink",   cmd_symlink,   "VFS symlink()",    "symlink <old> <new>" },
1811         { "readlink",   cmd_readlink,   "VFS readlink()",    "readlink <path>" },
1812         { "link",   cmd_link,   "VFS link()",    "link <oldpath> <newpath>" },
1813         { "mknod",   cmd_mknod,   "VFS mknod()",    "mknod <path> <mode> <dev>" },
1814         { "realpath",   cmd_realpath,   "VFS realpath()",    "realpath <path>" },
1815         { "getxattr", cmd_getxattr, "VFS getxattr()",
1816           "getxattr <path> <name>" },
1817         { "listxattr", cmd_listxattr, "VFS listxattr()",
1818           "listxattr <path>" },
1819         { "setxattr", cmd_setxattr, "VFS setxattr()",
1820           "setxattr <path> <name> <value> [<flags>]" },
1821         { "removexattr", cmd_removexattr, "VFS removexattr()",
1822           "removexattr <path> <name>\n" },
1823         { "fget_nt_acl", cmd_fget_nt_acl, "VFS fget_nt_acl()", 
1824           "fget_nt_acl <fd>\n" },
1825         { "get_nt_acl", cmd_get_nt_acl, "VFS get_nt_acl()", 
1826           "get_nt_acl <path>\n" },
1827         { "fset_nt_acl", cmd_fset_nt_acl, "VFS fset_nt_acl()", 
1828           "fset_nt_acl <fd>\n" },
1829         { "set_nt_acl", cmd_set_nt_acl, "VFS open() and fset_nt_acl()", 
1830           "set_nt_acl <file>\n" },
1831         { "fchmod_acl",   cmd_fchmod_acl,   "VFS fchmod_acl()",    "fchmod_acl <fd> <mode>" },
1832         { "chmod_acl",   cmd_chmod_acl,   "VFS chmod_acl()",    "chmod_acl <path> <mode>" },
1833         { "sys_acl_get_file", cmd_sys_acl_get_file, "VFS sys_acl_get_file()", "sys_acl_get_file <path>" },
1834         { "sys_acl_get_fd", cmd_sys_acl_get_fd, "VFS sys_acl_get_fd()", "sys_acl_get_fd <fd>" },
1835         { "sys_acl_blob_get_file", cmd_sys_acl_blob_get_file,
1836           "VFS sys_acl_blob_get_file()", "sys_acl_blob_get_file <path>" },
1837         { "sys_acl_blob_get_fd", cmd_sys_acl_blob_get_fd,
1838           "VFS sys_acl_blob_get_fd()", "sys_acl_blob_get_fd <path>" },
1839         { "sys_acl_delete_def_file", cmd_sys_acl_delete_def_file, "VFS sys_acl_delete_def_file()", "sys_acl_delete_def_file <path>" },
1840
1841
1842         { "test_chain", cmd_test_chain, "test chain code",
1843           "test_chain" },
1844         { "translate_name", cmd_translate_name, "VFS translate_name()", "translate_name unix_filename" },
1845         { NULL }
1846 };