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