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