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