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