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