torture: Disable vfs chain test dependant on SMB1
[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 uint32_t ssf_flags(void)
34 {
35         return lp_posix_pathnames() ? SMB_FILENAME_POSIX_PATH : 0;
36 }
37
38 static NTSTATUS cmd_load_module(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
39 {
40         int i;
41
42         if (argc < 2) {
43                 printf("Usage: load <modules>\n");
44                 return NT_STATUS_OK;
45         }
46
47         for (i=argc-1;i>0;i--) {
48                 if (!vfs_init_custom(vfs->conn, argv[i])) {
49                         DEBUG(0, ("load: (vfs_init_custom failed for %s)\n", argv[i]));
50                         return NT_STATUS_UNSUCCESSFUL;
51                 }
52         }
53         printf("load: ok\n");
54         return NT_STATUS_OK;
55 }
56
57 static NTSTATUS cmd_populate(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
58 {
59         char c;
60         size_t size;
61         if (argc != 3) {
62                 printf("Usage: populate <char> <size>\n");
63                 return NT_STATUS_OK;
64         }
65         c = argv[1][0];
66         size = atoi(argv[2]);
67         vfs->data = talloc_array(mem_ctx, char, size);
68         if (vfs->data == NULL) {
69                 printf("populate: error=-1 (not enough memory)");
70                 return NT_STATUS_UNSUCCESSFUL;
71         }
72         memset(vfs->data, c, size);
73         vfs->data_size = size;
74         return NT_STATUS_OK;
75 }
76
77 static NTSTATUS cmd_show_data(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
78 {
79         size_t offset;
80         size_t len;
81         if (argc != 1 && argc != 3) {
82                 printf("Usage: showdata [<offset> <len>]\n");
83                 return NT_STATUS_OK;
84         }
85         if (vfs->data == NULL || vfs->data_size == 0) {
86                 printf("show_data: error=-1 (buffer empty)\n");
87                 return NT_STATUS_UNSUCCESSFUL;
88         }
89
90         if (argc == 3) {
91                 offset = atoi(argv[1]);
92                 len = atoi(argv[2]);
93         } else {
94                 offset = 0;
95                 len = vfs->data_size;
96         }
97         if ((offset + len) > vfs->data_size) {
98                 printf("show_data: error=-1 (not enough data in buffer)\n");
99                 return NT_STATUS_UNSUCCESSFUL;
100         }
101         dump_data(0, (uint8_t *)(vfs->data) + offset, len);
102         return NT_STATUS_OK;
103 }
104
105 static NTSTATUS cmd_connect(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
106 {
107         const struct loadparm_substitution *lp_sub =
108                 loadparm_s3_global_substitution();
109
110         SMB_VFS_CONNECT(vfs->conn, lp_servicename(talloc_tos(), lp_sub, SNUM(vfs->conn)), "vfstest");
111         return NT_STATUS_OK;
112 }
113
114 static NTSTATUS cmd_disconnect(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
115 {
116         SMB_VFS_DISCONNECT(vfs->conn);
117         return NT_STATUS_OK;
118 }
119
120 static NTSTATUS cmd_disk_free(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
121 {
122         struct smb_filename *smb_fname = NULL;
123         uint64_t diskfree, bsize, dfree, dsize;
124         if (argc != 2) {
125                 printf("Usage: disk_free <path>\n");
126                 return NT_STATUS_OK;
127         }
128
129         smb_fname = synthetic_smb_fname(talloc_tos(),
130                                         argv[1],
131                                         NULL,
132                                         NULL,
133                                         0,
134                                         ssf_flags());
135         if (smb_fname == NULL) {
136                 return NT_STATUS_NO_MEMORY;
137         }
138         diskfree = SMB_VFS_DISK_FREE(vfs->conn, smb_fname,
139                                 &bsize, &dfree, &dsize);
140         printf("disk_free: %lu, bsize = %lu, dfree = %lu, dsize = %lu\n",
141                         (unsigned long)diskfree,
142                         (unsigned long)bsize,
143                         (unsigned long)dfree,
144                         (unsigned long)dsize);
145         return NT_STATUS_OK;
146 }
147
148
149 static NTSTATUS cmd_opendir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
150 {
151         struct smb_filename *smb_fname = NULL;
152         NTSTATUS status;
153
154         if (argc != 2) {
155                 printf("Usage: opendir <fname>\n");
156                 return NT_STATUS_OK;
157         }
158
159         smb_fname = synthetic_smb_fname(talloc_tos(),
160                                         argv[1],
161                                         NULL,
162                                         NULL,
163                                         0,
164                                         ssf_flags());
165         if (smb_fname == NULL) {
166                 return NT_STATUS_NO_MEMORY;
167         }
168
169         status = OpenDir(vfs->conn,
170                          vfs->conn,
171                          smb_fname,
172                          NULL,
173                          0,
174                          &vfs->currentdir);
175         if (!NT_STATUS_IS_OK(status)) {
176                 int err = map_errno_from_nt_status(status);
177                 printf("opendir error=%d (%s)\n", err, strerror(err));
178                 TALLOC_FREE(smb_fname);
179                 errno = err;
180                 return NT_STATUS_UNSUCCESSFUL;
181         }
182
183         vfs->currentdir_offset = 0;
184
185         TALLOC_FREE(smb_fname);
186         printf("opendir: ok\n");
187         return NT_STATUS_OK;
188 }
189
190
191 static NTSTATUS cmd_readdir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
192 {
193         SMB_STRUCT_STAT st;
194         const char *dname = NULL;
195         char *talloced = NULL;
196
197         if (vfs->currentdir == NULL) {
198                 printf("readdir: error=-1 (no open directory)\n");
199                 return NT_STATUS_UNSUCCESSFUL;
200         }
201
202         dname = ReadDirName(vfs->currentdir,
203                             &vfs->currentdir_offset,
204                             &st,
205                             &talloced);
206         if (dname == NULL) {
207                 printf("readdir: NULL\n");
208                 return NT_STATUS_OK;
209         }
210
211         printf("readdir: %s\n", dname);
212         if (VALID_STAT(st)) {
213                 time_t tmp_time;
214                 printf("  stat available");
215                 if (S_ISREG(st.st_ex_mode)) printf("  Regular File\n");
216                 else if (S_ISDIR(st.st_ex_mode)) printf("  Directory\n");
217                 else if (S_ISCHR(st.st_ex_mode)) printf("  Character Device\n");
218                 else if (S_ISBLK(st.st_ex_mode)) printf("  Block Device\n");
219                 else if (S_ISFIFO(st.st_ex_mode)) printf("  Fifo\n");
220                 else if (S_ISLNK(st.st_ex_mode)) printf("  Symbolic Link\n");
221                 else if (S_ISSOCK(st.st_ex_mode)) printf("  Socket\n");
222                 printf("  Size: %10u", (unsigned int)st.st_ex_size);
223 #ifdef HAVE_STAT_ST_BLOCKS
224                 printf(" Blocks: %9u", (unsigned int)st.st_ex_blocks);
225 #endif
226 #ifdef HAVE_STAT_ST_BLKSIZE
227                 printf(" IO Block: %u\n", (unsigned int)st.st_ex_blksize);
228 #endif
229                 printf("  Device: 0x%10x", (unsigned int)st.st_ex_dev);
230                 printf(" Inode: %10u", (unsigned int)st.st_ex_ino);
231                 printf(" Links: %10u\n", (unsigned int)st.st_ex_nlink);
232                 printf("  Access: %05o", (int)((st.st_ex_mode) & 007777));
233                 printf(" Uid: %5lu Gid: %5lu\n",
234                        (unsigned long)st.st_ex_uid,
235                        (unsigned long)st.st_ex_gid);
236                 tmp_time = convert_timespec_to_time_t(st.st_ex_atime);
237                 printf("  Access: %s", ctime(&tmp_time));
238                 tmp_time = convert_timespec_to_time_t(st.st_ex_mtime);
239                 printf("  Modify: %s", ctime(&tmp_time));
240                 tmp_time = convert_timespec_to_time_t(st.st_ex_ctime);
241                 printf("  Change: %s", ctime(&tmp_time));
242         }
243
244         TALLOC_FREE(talloced);
245         return NT_STATUS_OK;
246 }
247
248
249 static NTSTATUS cmd_mkdir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
250 {
251         struct smb_filename *smb_fname = NULL;
252         int ret;
253
254         if (argc != 2) {
255                 printf("Usage: mkdir <path>\n");
256                 return NT_STATUS_OK;
257         }
258
259         smb_fname = synthetic_smb_fname(talloc_tos(),
260                                         argv[1],
261                                         NULL,
262                                         NULL,
263                                         0,
264                                         ssf_flags());
265
266         if (smb_fname == NULL) {
267                 return NT_STATUS_NO_MEMORY;
268         }
269
270         ret = SMB_VFS_MKDIRAT(vfs->conn,
271                                 vfs->conn->cwd_fsp,
272                                 smb_fname,
273                                 00755);
274         if (ret == -1) {
275                 printf("mkdir error=%d (%s)\n", errno, strerror(errno));
276                 return NT_STATUS_UNSUCCESSFUL;
277         }
278
279         printf("mkdir: ok\n");
280         return NT_STATUS_OK;
281 }
282
283
284 static NTSTATUS cmd_closedir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
285 {
286         if (vfs->currentdir == NULL) {
287                 printf("closedir: failure (no directory open)\n");
288                 return NT_STATUS_UNSUCCESSFUL;
289         }
290
291         TALLOC_FREE(vfs->currentdir);
292         vfs->currentdir_offset = 0;
293
294         printf("closedir: ok\n");
295         return NT_STATUS_OK;
296 }
297
298
299 static NTSTATUS cmd_open(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
300 {
301         int flags;
302         mode_t mode;
303         const char *flagstr;
304         files_struct *fsp;
305         struct files_struct *fspcwd = NULL;
306         struct smb_filename *smb_fname = NULL;
307         NTSTATUS status;
308         int fd;
309
310         mode = 00400;
311
312         if (argc < 3 || argc > 5) {
313                 printf("Usage: open <filename> <flags> <mode>\n");
314                 printf("  flags: O = O_RDONLY\n");
315                 printf("         R = O_RDWR\n");
316                 printf("         W = O_WRONLY\n");
317                 printf("         C = O_CREAT\n");
318                 printf("         E = O_EXCL\n");
319                 printf("         T = O_TRUNC\n");
320                 printf("         A = O_APPEND\n");
321                 printf("         N = O_NONBLOCK/O_NDELAY\n");
322 #ifdef O_SYNC
323                 printf("         S = O_SYNC\n");
324 #endif
325 #ifdef O_NOFOLLOW
326                 printf("         F = O_NOFOLLOW\n");
327 #endif
328                 printf("  mode: see open.2\n");
329                 printf("        mode is ignored if C flag not present\n");
330                 printf("        mode defaults to 00400\n");
331                 return NT_STATUS_OK;
332         }
333         flags = 0;
334         flagstr = argv[2];
335         while (*flagstr) {
336                 switch (*flagstr) {
337                 case 'O':
338                         flags |= O_RDONLY;
339                         break;
340                 case 'R':
341                         flags |= O_RDWR;
342                         break;
343                 case 'W':
344                         flags |= O_WRONLY;
345                         break;
346                 case 'C':
347                         flags |= O_CREAT;
348                         break;
349                 case 'E':
350                         flags |= O_EXCL;
351                         break;
352                 case 'T':
353                         flags |= O_TRUNC;
354                         break;
355                 case 'A':
356                         flags |= O_APPEND;
357                         break;
358                 case 'N':
359                         flags |= O_NONBLOCK;
360                         break;
361 #ifdef O_SYNC
362                 case 'S':
363                         flags |= O_SYNC;
364                         break;
365 #endif
366 #ifdef O_NOFOLLOW
367                 case 'F':
368                         flags |= O_NOFOLLOW;
369                         break;
370 #endif
371                 default:
372                         printf("open: error=-1 (invalid flag!)\n");
373                         return NT_STATUS_UNSUCCESSFUL;
374                 }
375                 flagstr++;
376         }
377         if ((flags & O_CREAT) && argc == 4) {
378                 if (sscanf(argv[3], "%ho", (unsigned short *)&mode) == 0) {
379                         printf("open: error=-1 (invalid mode!)\n");
380                         return NT_STATUS_UNSUCCESSFUL;
381                 }
382         }
383
384         fsp = talloc_zero(vfs, struct files_struct);
385         if (fsp == NULL) {
386                 goto nomem;
387         }
388         fsp->fh = fd_handle_create(fsp);
389         if (fsp->fh == NULL) {
390                 goto nomem;
391         }
392         fsp->conn = vfs->conn;
393
394         smb_fname = synthetic_smb_fname_split(NULL,
395                                         argv[1],
396                                         lp_posix_pathnames());
397         if (smb_fname == NULL) {
398                 goto nomem;
399         }
400
401         fsp->fsp_name = smb_fname;
402
403         status = vfs_at_fspcwd(fsp, vfs->conn, &fspcwd);
404         if (!NT_STATUS_IS_OK(status)) {
405                 goto fail;
406         }
407
408         if (is_named_stream(smb_fname)) {
409                 struct smb_filename *base_name = NULL;
410
411                 base_name = cp_smb_filename_nostream(NULL, smb_fname);
412                 if (base_name == NULL) {
413                         goto nomem;
414                 }
415
416                 status = openat_pathref_fsp(fspcwd, base_name);
417                 if (!NT_STATUS_IS_OK(status)) {
418                         goto fail;
419                 }
420
421                 fsp->base_fsp = base_name->fsp;
422         }
423
424         fd = SMB_VFS_OPENAT(vfs->conn,
425                             fspcwd,
426                             smb_fname,
427                             fsp,
428                             flags,
429                             mode);
430         if (fd == -1) {
431                 printf("open: error=%d (%s)\n", errno, strerror(errno));
432                 status = map_nt_error_from_unix(errno);
433                 goto fail;
434         }
435         fsp_set_fd(fsp, fd);
436
437         status = vfs_stat_fsp(fsp);
438         if (!NT_STATUS_IS_OK(status)) {
439                 /* If we have an fd, this stat should succeed. */
440                 DEBUG(0,("Error doing fstat on open file %s "
441                          "(%s)\n",
442                          smb_fname_str_dbg(smb_fname),
443                          nt_errstr(status) ));
444         } else if (S_ISDIR(smb_fname->st.st_ex_mode)) {
445                 errno = EISDIR;
446                 status = NT_STATUS_FILE_IS_A_DIRECTORY;
447         }
448
449         if (!NT_STATUS_IS_OK(status)) {
450                 fd_close(fsp);
451                 goto fail;
452         }
453
454         fsp->file_id = vfs_file_id_from_sbuf(vfs->conn, &smb_fname->st);
455         fsp->vuid = UID_FIELD_INVALID;
456         fsp->file_pid = 0;
457         fsp->fsp_flags.can_lock = true;
458         fsp->fsp_flags.can_read = true;
459         fsp->fsp_flags.can_write = CAN_WRITE(vfs->conn);
460         fsp->print_file = NULL;
461         fsp->fsp_flags.modified = false;
462         fsp->sent_oplock_break = NO_BREAK_SENT;
463         fsp->fsp_flags.is_directory = false;
464
465         vfs->files[fsp_get_pathref_fd(fsp)] = fsp;
466         printf("open: fd=%d\n", fsp_get_pathref_fd(fsp));
467         return NT_STATUS_OK;
468
469 nomem:
470         status = NT_STATUS_NO_MEMORY;
471 fail:
472         TALLOC_FREE(smb_fname);
473         TALLOC_FREE(fsp);
474         return status;
475 }
476
477
478 static NTSTATUS cmd_pathfunc(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
479 {
480         struct smb_filename *smb_fname = NULL;
481         int ret = -1;
482
483         if (argc != 2) {
484                 printf("Usage: %s <path>\n", argv[0]);
485                 return NT_STATUS_OK;
486         }
487
488         smb_fname = synthetic_smb_fname(talloc_tos(),
489                                         argv[1],
490                                         NULL,
491                                         NULL,
492                                         0,
493                                         ssf_flags());
494
495         if (smb_fname == NULL) {
496                 return NT_STATUS_NO_MEMORY;
497         }
498
499         if (strcmp("rmdir", argv[0]) == 0 ) {
500                 ret = SMB_VFS_UNLINKAT(vfs->conn,
501                                 vfs->conn->cwd_fsp,
502                                 smb_fname,
503                                 AT_REMOVEDIR);
504                 TALLOC_FREE(smb_fname);
505         } else if (strcmp("unlink", argv[0]) == 0 ) {
506                 TALLOC_FREE(smb_fname);
507                 /* unlink can be a stream:name */
508                 smb_fname = synthetic_smb_fname_split(talloc_tos(),
509                                         argv[1],
510                                         lp_posix_pathnames());
511                 if (smb_fname == NULL) {
512                         return NT_STATUS_NO_MEMORY;
513                 }
514                 ret = SMB_VFS_UNLINKAT(vfs->conn,
515                                 vfs->conn->cwd_fsp,
516                                 smb_fname,
517                                 0);
518                 TALLOC_FREE(smb_fname);
519         } else if (strcmp("chdir", argv[0]) == 0 ) {
520                 ret = SMB_VFS_CHDIR(vfs->conn, smb_fname);
521                 TALLOC_FREE(smb_fname);
522         } else {
523                 printf("%s: error=%d (invalid function name!)\n", argv[0], errno);
524                 return NT_STATUS_UNSUCCESSFUL;
525         }
526
527         if (ret == -1) {
528                 printf("%s: error=%d (%s)\n", argv[0], errno, strerror(errno));
529                 return NT_STATUS_UNSUCCESSFUL;
530         }
531
532         printf("%s: ok\n", argv[0]);
533         return NT_STATUS_OK;
534 }
535
536
537 static NTSTATUS cmd_close(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
538 {
539         int fd;
540         NTSTATUS status;
541
542         if (argc != 2) {
543                 printf("Usage: close <fd>\n");
544                 return NT_STATUS_OK;
545         }
546
547         fd = atoi(argv[1]);
548         if (vfs->files[fd] == NULL) {
549                 printf("close: error=-1 (invalid file descriptor)\n");
550                 return NT_STATUS_OK;
551         }
552
553         status = fd_close(vfs->files[fd]);
554         if (!NT_STATUS_IS_OK(status))
555                 printf("close: error=%s\n", nt_errstr(status));
556         else
557                 printf("close: ok\n");
558
559         TALLOC_FREE(vfs->files[fd]);
560         vfs->files[fd] = NULL;
561         return status;
562 }
563
564
565 static NTSTATUS cmd_read(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
566 {
567         int fd;
568         size_t size;
569         ssize_t rsize;
570
571         if (argc != 3) {
572                 printf("Usage: read <fd> <size>\n");
573                 return NT_STATUS_OK;
574         }
575
576         /* do some error checking on these */
577         fd = atoi(argv[1]);
578         size = atoi(argv[2]);
579         vfs->data = talloc_array(mem_ctx, char, size);
580         if (vfs->data == NULL) {
581                 printf("read: error=-1 (not enough memory)");
582                 return NT_STATUS_UNSUCCESSFUL;
583         }
584         vfs->data_size = size;
585
586         rsize = read_file(vfs->files[fd], vfs->data, 0, size);
587         if (rsize == -1) {
588                 printf("read: error=%d (%s)\n", errno, strerror(errno));
589                 return NT_STATUS_UNSUCCESSFUL;
590         }
591
592         printf("read: ok\n");
593         return NT_STATUS_OK;
594 }
595
596
597 static NTSTATUS cmd_write(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
598 {
599         int fd, wsize;
600         size_t size;
601
602         if (argc != 3) {
603                 printf("Usage: write <fd> <size>\n");
604                 return NT_STATUS_OK;
605         }
606
607         /* some error checking should go here */
608         fd = atoi(argv[1]);
609         size = atoi(argv[2]);
610         if (vfs->data == NULL) {
611                 printf("write: error=-1 (buffer empty, please populate it before writing)");
612                 return NT_STATUS_UNSUCCESSFUL;
613         }
614
615         if (vfs->data_size < size) {
616                 printf("write: error=-1 (buffer too small, please put some more data in)");
617                 return NT_STATUS_UNSUCCESSFUL;
618         }
619
620         wsize = write_file(NULL, vfs->files[fd], vfs->data, 0, size);
621
622         if (wsize == -1) {
623                 printf("write: error=%d (%s)\n", errno, strerror(errno));
624                 return NT_STATUS_UNSUCCESSFUL;
625         }
626
627         printf("write: ok\n");
628         return NT_STATUS_OK;
629 }
630
631
632 static NTSTATUS cmd_lseek(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
633 {
634         int fd, offset, whence;
635         off_t pos;
636
637         if (argc != 4) {
638                 printf("Usage: lseek <fd> <offset> <whence>\n...where whence is 1 => SEEK_SET, 2 => SEEK_CUR, 3 => SEEK_END\n");
639                 return NT_STATUS_OK;
640         }
641
642         fd = atoi(argv[1]);
643         offset = atoi(argv[2]);
644         whence = atoi(argv[3]);
645         switch (whence) {
646                 case 1:         whence = SEEK_SET; break;
647                 case 2:         whence = SEEK_CUR; break;
648                 default:        whence = SEEK_END;
649         }
650
651         pos = SMB_VFS_LSEEK(vfs->files[fd], offset, whence);
652         if (pos == (off_t)-1) {
653                 printf("lseek: error=%d (%s)\n", errno, strerror(errno));
654                 return NT_STATUS_UNSUCCESSFUL;
655         }
656
657         printf("lseek: ok\n");
658         return NT_STATUS_OK;
659 }
660
661
662 static NTSTATUS cmd_rename(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
663 {
664         int ret;
665         struct smb_filename *smb_fname_src = NULL;
666         struct smb_filename *smb_fname_dst = NULL;
667
668         if (argc != 3) {
669                 printf("Usage: rename <old> <new>\n");
670                 return NT_STATUS_OK;
671         }
672
673         smb_fname_src = synthetic_smb_fname_split(mem_ctx,
674                                         argv[1],
675                                         lp_posix_pathnames());
676         if (smb_fname_src == NULL) {
677                 return NT_STATUS_NO_MEMORY;
678         }
679
680         smb_fname_dst = synthetic_smb_fname_split(mem_ctx,
681                                         argv[2],
682                                         lp_posix_pathnames());
683         if (smb_fname_dst == NULL) {
684                 TALLOC_FREE(smb_fname_src);
685                 return NT_STATUS_NO_MEMORY;
686         }
687
688         ret = SMB_VFS_RENAMEAT(vfs->conn,
689                         vfs->conn->cwd_fsp,
690                         smb_fname_src,
691                         vfs->conn->cwd_fsp,
692                         smb_fname_dst);
693
694         TALLOC_FREE(smb_fname_src);
695         TALLOC_FREE(smb_fname_dst);
696         if (ret == -1) {
697                 printf("rename: error=%d (%s)\n", errno, strerror(errno));
698                 return NT_STATUS_UNSUCCESSFUL;
699         }
700
701         printf("rename: ok\n");
702         return NT_STATUS_OK;
703 }
704
705 static NTSTATUS cmd_fsync(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
706 {
707         int ret, fd;
708         if (argc != 2) {
709                 printf("Usage: fsync <fd>\n");
710                 return NT_STATUS_OK;
711         }
712
713         fd = atoi(argv[1]);
714         ret = smb_vfs_fsync_sync(vfs->files[fd]);
715         if (ret == -1) {
716                 printf("fsync: error=%d (%s)\n", errno, strerror(errno));
717                 return NT_STATUS_UNSUCCESSFUL;
718         }
719
720         printf("fsync: ok\n");
721         return NT_STATUS_OK;
722 }
723
724
725 static NTSTATUS cmd_stat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
726 {
727         int ret;
728         const char *user;
729         const char *group;
730         struct passwd *pwd = NULL;
731         struct group *grp = NULL;
732         struct smb_filename *smb_fname = NULL;
733         SMB_STRUCT_STAT st;
734         time_t tmp_time;
735
736         if (argc != 2) {
737                 printf("Usage: stat <fname>\n");
738                 return NT_STATUS_OK;
739         }
740
741         smb_fname = synthetic_smb_fname_split(mem_ctx,
742                                         argv[1],
743                                         lp_posix_pathnames());
744         if (smb_fname == NULL) {
745                 return NT_STATUS_NO_MEMORY;
746         }
747
748         ret = SMB_VFS_STAT(vfs->conn, smb_fname);
749         if (ret == -1) {
750                 printf("stat: error=%d (%s)\n", errno, strerror(errno));
751                 TALLOC_FREE(smb_fname);
752                 return NT_STATUS_UNSUCCESSFUL;
753         }
754         st = smb_fname->st;
755         TALLOC_FREE(smb_fname);
756
757         pwd = getpwuid(st.st_ex_uid);
758         if (pwd != NULL) user = pwd->pw_name;
759         else user = null_string;
760         grp = getgrgid(st.st_ex_gid);
761         if (grp != NULL) group = grp->gr_name;
762         else group = null_string;
763
764         printf("stat: ok\n");
765         printf("  File: %s", argv[1]);
766         if (S_ISREG(st.st_ex_mode)) printf("  Regular File\n");
767         else if (S_ISDIR(st.st_ex_mode)) printf("  Directory\n");
768         else if (S_ISCHR(st.st_ex_mode)) printf("  Character Device\n");
769         else if (S_ISBLK(st.st_ex_mode)) printf("  Block Device\n");
770         else if (S_ISFIFO(st.st_ex_mode)) printf("  Fifo\n");
771         else if (S_ISLNK(st.st_ex_mode)) printf("  Symbolic Link\n");
772         else if (S_ISSOCK(st.st_ex_mode)) printf("  Socket\n");
773         printf("  Size: %10u", (unsigned int)st.st_ex_size);
774 #ifdef HAVE_STAT_ST_BLOCKS
775         printf(" Blocks: %9u", (unsigned int)st.st_ex_blocks);
776 #endif
777 #ifdef HAVE_STAT_ST_BLKSIZE
778         printf(" IO Block: %u\n", (unsigned int)st.st_ex_blksize);
779 #endif
780         printf("  Device: 0x%10x", (unsigned int)st.st_ex_dev);
781         printf(" Inode: %10u", (unsigned int)st.st_ex_ino);
782         printf(" Links: %10u\n", (unsigned int)st.st_ex_nlink);
783         printf("  Access: %05o", (int)((st.st_ex_mode) & 007777));
784         printf(" Uid: %5lu/%.16s Gid: %5lu/%.16s\n", (unsigned long)st.st_ex_uid, user,
785                (unsigned long)st.st_ex_gid, group);
786         tmp_time = convert_timespec_to_time_t(st.st_ex_atime);
787         printf("  Access: %s", ctime(&tmp_time));
788         tmp_time = convert_timespec_to_time_t(st.st_ex_mtime);
789         printf("  Modify: %s", ctime(&tmp_time));
790         tmp_time = convert_timespec_to_time_t(st.st_ex_ctime);
791         printf("  Change: %s", ctime(&tmp_time));
792
793         return NT_STATUS_OK;
794 }
795
796
797 static NTSTATUS cmd_fstat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
798 {
799         int fd;
800         const char *user;
801         const char *group;
802         struct passwd *pwd = NULL;
803         struct group *grp = NULL;
804         SMB_STRUCT_STAT st;
805         time_t tmp_time;
806
807         if (argc != 2) {
808                 printf("Usage: fstat <fd>\n");
809                 return NT_STATUS_OK;
810         }
811
812         fd = atoi(argv[1]);
813         if (fd < 0 || fd >= 1024) {
814                 printf("fstat: error=%d (file descriptor out of range)\n", EBADF);
815                 return NT_STATUS_OK;
816         }
817
818         if (vfs->files[fd] == NULL) {
819                 printf("fstat: error=%d (invalid file descriptor)\n", EBADF);
820                 return NT_STATUS_OK;
821         }
822
823         if (SMB_VFS_FSTAT(vfs->files[fd], &st) == -1) {
824                 printf("fstat: error=%d (%s)\n", errno, strerror(errno));
825                 return NT_STATUS_UNSUCCESSFUL;
826         }
827
828         pwd = getpwuid(st.st_ex_uid);
829         if (pwd != NULL) user = pwd->pw_name;
830         else user = null_string;
831         grp = getgrgid(st.st_ex_gid);
832         if (grp != NULL) group = grp->gr_name;
833         else group = null_string;
834
835         printf("fstat: ok\n");
836         if (S_ISREG(st.st_ex_mode)) printf("  Regular File\n");
837         else if (S_ISDIR(st.st_ex_mode)) printf("  Directory\n");
838         else if (S_ISCHR(st.st_ex_mode)) printf("  Character Device\n");
839         else if (S_ISBLK(st.st_ex_mode)) printf("  Block Device\n");
840         else if (S_ISFIFO(st.st_ex_mode)) printf("  Fifo\n");
841         else if (S_ISLNK(st.st_ex_mode)) printf("  Symbolic Link\n");
842         else if (S_ISSOCK(st.st_ex_mode)) printf("  Socket\n");
843         printf("  Size: %10u", (unsigned int)st.st_ex_size);
844 #ifdef HAVE_STAT_ST_BLOCKS
845         printf(" Blocks: %9u", (unsigned int)st.st_ex_blocks);
846 #endif
847 #ifdef HAVE_STAT_ST_BLKSIZE
848         printf(" IO Block: %u\n", (unsigned int)st.st_ex_blksize);
849 #endif
850         printf("  Device: 0x%10x", (unsigned int)st.st_ex_dev);
851         printf(" Inode: %10u", (unsigned int)st.st_ex_ino);
852         printf(" Links: %10u\n", (unsigned int)st.st_ex_nlink);
853         printf("  Access: %05o", (int)((st.st_ex_mode) & 007777));
854         printf(" Uid: %5lu/%.16s Gid: %5lu/%.16s\n", (unsigned long)st.st_ex_uid, user,
855                (unsigned long)st.st_ex_gid, group);
856         tmp_time = convert_timespec_to_time_t(st.st_ex_atime);
857         printf("  Access: %s", ctime(&tmp_time));
858         tmp_time = convert_timespec_to_time_t(st.st_ex_mtime);
859         printf("  Modify: %s", ctime(&tmp_time));
860         tmp_time = convert_timespec_to_time_t(st.st_ex_ctime);
861         printf("  Change: %s", ctime(&tmp_time));
862
863         return NT_STATUS_OK;
864 }
865
866
867 static NTSTATUS cmd_lstat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
868 {
869         const char *user;
870         const char *group;
871         struct passwd *pwd = NULL;
872         struct group *grp = NULL;
873         struct smb_filename *smb_fname = NULL;
874         SMB_STRUCT_STAT st;
875         time_t tmp_time;
876
877         if (argc != 2) {
878                 printf("Usage: lstat <path>\n");
879                 return NT_STATUS_OK;
880         }
881
882         smb_fname = synthetic_smb_fname_split(mem_ctx,
883                                         argv[1],
884                                         lp_posix_pathnames());
885         if (smb_fname == NULL) {
886                 return NT_STATUS_NO_MEMORY;
887         }
888
889         if (SMB_VFS_LSTAT(vfs->conn, smb_fname) == -1) {
890                 printf("lstat: error=%d (%s)\n", errno, strerror(errno));
891                 TALLOC_FREE(smb_fname);
892                 return NT_STATUS_UNSUCCESSFUL;
893         }
894         st = smb_fname->st;
895         TALLOC_FREE(smb_fname);
896
897         pwd = getpwuid(st.st_ex_uid);
898         if (pwd != NULL) user = pwd->pw_name;
899         else user = null_string;
900         grp = getgrgid(st.st_ex_gid);
901         if (grp != NULL) group = grp->gr_name;
902         else group = null_string;
903
904         printf("lstat: ok\n");
905         if (S_ISREG(st.st_ex_mode)) printf("  Regular File\n");
906         else if (S_ISDIR(st.st_ex_mode)) printf("  Directory\n");
907         else if (S_ISCHR(st.st_ex_mode)) printf("  Character Device\n");
908         else if (S_ISBLK(st.st_ex_mode)) printf("  Block Device\n");
909         else if (S_ISFIFO(st.st_ex_mode)) printf("  Fifo\n");
910         else if (S_ISLNK(st.st_ex_mode)) printf("  Symbolic Link\n");
911         else if (S_ISSOCK(st.st_ex_mode)) printf("  Socket\n");
912         printf("  Size: %10u", (unsigned int)st.st_ex_size);
913 #ifdef HAVE_STAT_ST_BLOCKS
914         printf(" Blocks: %9u", (unsigned int)st.st_ex_blocks);
915 #endif
916 #ifdef HAVE_STAT_ST_BLKSIZE
917         printf(" IO Block: %u\n", (unsigned int)st.st_ex_blksize);
918 #endif
919         printf("  Device: 0x%10x", (unsigned int)st.st_ex_dev);
920         printf(" Inode: %10u", (unsigned int)st.st_ex_ino);
921         printf(" Links: %10u\n", (unsigned int)st.st_ex_nlink);
922         printf("  Access: %05o", (int)((st.st_ex_mode) & 007777));
923         printf(" Uid: %5lu/%.16s Gid: %5lu/%.16s\n", (unsigned long)st.st_ex_uid, user,
924                (unsigned long)st.st_ex_gid, group);
925         tmp_time = convert_timespec_to_time_t(st.st_ex_atime);
926         printf("  Access: %s", ctime(&tmp_time));
927         tmp_time = convert_timespec_to_time_t(st.st_ex_mtime);
928         printf("  Modify: %s", ctime(&tmp_time));
929         tmp_time = convert_timespec_to_time_t(st.st_ex_ctime);
930         printf("  Change: %s", ctime(&tmp_time));
931
932         return NT_STATUS_OK;
933 }
934
935
936 static NTSTATUS cmd_chmod(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
937 {
938         struct smb_filename *smb_fname = NULL;
939         mode_t mode;
940         struct smb_filename *pathref_fname = NULL;
941         NTSTATUS status;
942         if (argc != 3) {
943                 printf("Usage: chmod <path> <mode>\n");
944                 return NT_STATUS_OK;
945         }
946
947         mode = atoi(argv[2]);
948
949         smb_fname = synthetic_smb_fname_split(mem_ctx,
950                                         argv[1],
951                                         lp_posix_pathnames());
952         if (smb_fname == NULL) {
953                 return NT_STATUS_NO_MEMORY;
954         }
955
956         status = synthetic_pathref(mem_ctx,
957                                 vfs->conn->cwd_fsp,
958                                 smb_fname->base_name,
959                                 NULL,
960                                 NULL,
961                                 smb_fname->twrp,
962                                 smb_fname->flags,
963                                 &pathref_fname);
964         if (!NT_STATUS_IS_OK(status)) {
965                 return status;
966         }
967         if (SMB_VFS_FCHMOD(pathref_fname->fsp, mode) == -1) {
968                 printf("chmod: error=%d (%s)\n", errno, strerror(errno));
969                 return NT_STATUS_UNSUCCESSFUL;
970         }
971
972         printf("chmod: ok\n");
973         return NT_STATUS_OK;
974 }
975
976
977 static NTSTATUS cmd_fchmod(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
978 {
979         int fd;
980         mode_t mode;
981         if (argc != 3) {
982                 printf("Usage: fchmod <fd> <mode>\n");
983                 return NT_STATUS_OK;
984         }
985
986         fd = atoi(argv[1]);
987         mode = atoi(argv[2]);
988         if (fd < 0 || fd >= 1024) {
989                 printf("fchmod: error=%d (file descriptor out of range)\n", EBADF);
990                 return NT_STATUS_OK;
991         }
992         if (vfs->files[fd] == NULL) {
993                 printf("fchmod: error=%d (invalid file descriptor)\n", EBADF);
994                 return NT_STATUS_OK;
995         }
996
997         if (SMB_VFS_FCHMOD(vfs->files[fd], mode) == -1) {
998                 printf("fchmod: error=%d (%s)\n", errno, strerror(errno));
999                 return NT_STATUS_UNSUCCESSFUL;
1000         }
1001
1002         printf("fchmod: ok\n");
1003         return NT_STATUS_OK;
1004 }
1005
1006 static NTSTATUS cmd_fchown(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
1007 {
1008         uid_t uid;
1009         gid_t gid;
1010         int fd;
1011         if (argc != 4) {
1012                 printf("Usage: fchown <fd> <uid> <gid>\n");
1013                 return NT_STATUS_OK;
1014         }
1015
1016         uid = atoi(argv[2]);
1017         gid = atoi(argv[3]);
1018         fd = atoi(argv[1]);
1019         if (fd < 0 || fd >= 1024) {
1020                 printf("fchown: faliure=%d (file descriptor out of range)\n", EBADF);
1021                 return NT_STATUS_OK;
1022         }
1023         if (vfs->files[fd] == NULL) {
1024                 printf("fchown: error=%d (invalid file descriptor)\n", EBADF);
1025                 return NT_STATUS_OK;
1026         }
1027         if (SMB_VFS_FCHOWN(vfs->files[fd], uid, gid) == -1) {
1028                 printf("fchown error=%d (%s)\n", errno, strerror(errno));
1029                 return NT_STATUS_UNSUCCESSFUL;
1030         }
1031
1032         printf("fchown: ok\n");
1033         return NT_STATUS_OK;
1034 }
1035
1036
1037 static NTSTATUS cmd_getwd(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
1038 {
1039         struct smb_filename *smb_fname = SMB_VFS_GETWD(vfs->conn, talloc_tos());
1040         if (smb_fname == NULL) {
1041                 printf("getwd: error=%d (%s)\n", errno, strerror(errno));
1042                 return NT_STATUS_UNSUCCESSFUL;
1043         }
1044
1045         printf("getwd: %s\n", smb_fname->base_name);
1046         TALLOC_FREE(smb_fname);
1047         return NT_STATUS_OK;
1048 }
1049
1050 static NTSTATUS cmd_utime(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
1051 {
1052         struct smb_file_time ft;
1053         struct smb_filename *smb_fname = NULL;
1054         NTSTATUS status;
1055
1056         if (argc != 4) {
1057                 printf("Usage: utime <path> <access> <modify>\n");
1058                 return NT_STATUS_OK;
1059         }
1060
1061         init_smb_file_time(&ft);
1062
1063         ft.atime = time_t_to_full_timespec(atoi(argv[2]));
1064         ft.mtime = time_t_to_full_timespec(atoi(argv[3]));
1065
1066         status = filename_convert(mem_ctx,
1067                                   vfs->conn,
1068                                   argv[1],
1069                                   0,
1070                                   0,
1071                                   &smb_fname);
1072         if (!NT_STATUS_IS_OK(status)) {
1073                 printf("utime: %s\n", nt_errstr(status));
1074                 return status;
1075         }
1076
1077         if (SMB_VFS_FNTIMES(smb_fname->fsp, &ft) != 0) {
1078                 printf("utime: error=%d (%s)\n", errno, strerror(errno));
1079                 TALLOC_FREE(smb_fname);
1080                 return NT_STATUS_UNSUCCESSFUL;
1081         }
1082
1083         TALLOC_FREE(smb_fname);
1084         printf("utime: ok\n");
1085         return NT_STATUS_OK;
1086 }
1087
1088 static NTSTATUS cmd_ftruncate(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
1089 {
1090         int fd;
1091         off_t off;
1092         if (argc != 3) {
1093                 printf("Usage: ftruncate <fd> <length>\n");
1094                 return NT_STATUS_OK;
1095         }
1096
1097         fd = atoi(argv[1]);
1098         off = atoi(argv[2]);
1099         if (fd < 0 || fd >= 1024) {
1100                 printf("ftruncate: error=%d (file descriptor out of range)\n", EBADF);
1101                 return NT_STATUS_OK;
1102         }
1103         if (vfs->files[fd] == NULL) {
1104                 printf("ftruncate: error=%d (invalid file descriptor)\n", EBADF);
1105                 return NT_STATUS_OK;
1106         }
1107
1108         if (SMB_VFS_FTRUNCATE(vfs->files[fd], off) == -1) {
1109                 printf("ftruncate: error=%d (%s)\n", errno, strerror(errno));
1110                 return NT_STATUS_UNSUCCESSFUL;
1111         }
1112
1113         printf("ftruncate: ok\n");
1114         return NT_STATUS_OK;
1115 }
1116
1117 static NTSTATUS cmd_lock(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
1118 {
1119         int fd;
1120         int op;
1121         long offset;
1122         long count;
1123         int type;
1124         const char *typestr;
1125
1126         if (argc != 6) {
1127                 printf("Usage: lock <fd> <op> <offset> <count> <type>\n");
1128                 printf("  ops: G = F_GETLK\n");
1129                 printf("       S = F_SETLK\n");
1130                 printf("       W = F_SETLKW\n");
1131                 printf("  type: R = F_RDLCK\n");
1132                 printf("        W = F_WRLCK\n");
1133                 printf("        U = F_UNLCK\n");
1134                 return NT_STATUS_OK;
1135         }
1136
1137         if (sscanf(argv[1], "%d", &fd) == 0) {
1138                 printf("lock: error=-1 (error parsing fd)\n");
1139                 return NT_STATUS_UNSUCCESSFUL;
1140         }
1141
1142         op = 0;
1143         switch (*argv[2]) {
1144         case 'G':
1145                 op = F_GETLK;
1146                 break;
1147         case 'S':
1148                 op = F_SETLK;
1149                 break;
1150         case 'W':
1151                 op = F_SETLKW;
1152                 break;
1153         default:
1154                 printf("lock: error=-1 (invalid op flag!)\n");
1155                 return NT_STATUS_UNSUCCESSFUL;
1156         }
1157
1158         if (sscanf(argv[3], "%ld", &offset) == 0) {
1159                 printf("lock: error=-1 (error parsing fd)\n");
1160                 return NT_STATUS_UNSUCCESSFUL;
1161         }
1162
1163         if (sscanf(argv[4], "%ld", &count) == 0) {
1164                 printf("lock: error=-1 (error parsing fd)\n");
1165                 return NT_STATUS_UNSUCCESSFUL;
1166         }
1167
1168         type = 0;
1169         typestr = argv[5];
1170         while(*typestr) {
1171                 switch (*typestr) {
1172                 case 'R':
1173                         type |= F_RDLCK;
1174                         break;
1175                 case 'W':
1176                         type |= F_WRLCK;
1177                         break;
1178                 case 'U':
1179                         type |= F_UNLCK;
1180                         break;
1181                 default:
1182                         printf("lock: error=-1 (invalid type flag!)\n");
1183                         return NT_STATUS_UNSUCCESSFUL;
1184                 }
1185                 typestr++;
1186         }
1187
1188         printf("lock: debug lock(fd=%d, op=%d, offset=%ld, count=%ld, type=%d))\n", fd, op, offset, count, type);
1189
1190         if (SMB_VFS_LOCK(vfs->files[fd], op, offset, count, type) == False) {
1191                 printf("lock: error=%d (%s)\n", errno, strerror(errno));
1192                 return NT_STATUS_UNSUCCESSFUL;
1193         }
1194
1195         printf("lock: ok\n");
1196         return NT_STATUS_OK;
1197 }
1198
1199 static NTSTATUS cmd_symlink(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
1200 {
1201         int ret;
1202         char *target = NULL;
1203         struct smb_filename target_fname;
1204         struct smb_filename *new_smb_fname = NULL;
1205         NTSTATUS status;
1206
1207         if (argc != 3) {
1208                 printf("Usage: symlink <path> <link>\n");
1209                 return NT_STATUS_OK;
1210         }
1211
1212         new_smb_fname = synthetic_smb_fname_split(mem_ctx,
1213                                         argv[2],
1214                                         lp_posix_pathnames());
1215         if (new_smb_fname == NULL) {
1216                 return NT_STATUS_NO_MEMORY;
1217         }
1218
1219         target = talloc_strdup(mem_ctx, argv[1]);
1220         if (target == NULL) {
1221                 return NT_STATUS_NO_MEMORY;
1222         }
1223
1224         target_fname = (struct smb_filename) {
1225                 .base_name = target,
1226         };
1227
1228         /* Removes @GMT tokens if any */
1229         status = canonicalize_snapshot_path(&target_fname, UCF_GMT_PATHNAME, 0);
1230         if (!NT_STATUS_IS_OK(status)) {
1231                 return status;
1232         }
1233
1234         ret = SMB_VFS_SYMLINKAT(vfs->conn,
1235                         &target_fname,
1236                         vfs->conn->cwd_fsp,
1237                         new_smb_fname);
1238         if (ret == -1) {
1239                 printf("symlink: error=%d (%s)\n", errno, strerror(errno));
1240                 return NT_STATUS_UNSUCCESSFUL;
1241         }
1242
1243         printf("symlink: ok\n");
1244         return NT_STATUS_OK;
1245 }
1246
1247
1248 static NTSTATUS cmd_readlink(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
1249 {
1250         char buffer[PATH_MAX];
1251         struct smb_filename *smb_fname = NULL;
1252         int size;
1253
1254         if (argc != 2) {
1255                 printf("Usage: readlink <path>\n");
1256                 return NT_STATUS_OK;
1257         }
1258
1259         smb_fname = synthetic_smb_fname_split(mem_ctx,
1260                                         argv[1],
1261                                         lp_posix_pathnames());
1262         if (smb_fname == NULL) {
1263                 return NT_STATUS_NO_MEMORY;
1264         }
1265         size = SMB_VFS_READLINKAT(vfs->conn,
1266                         vfs->conn->cwd_fsp,
1267                         smb_fname,
1268                         buffer,
1269                         PATH_MAX);
1270
1271         if (size == -1) {
1272                 printf("readlink: error=%d (%s)\n", errno, strerror(errno));
1273                 return NT_STATUS_UNSUCCESSFUL;
1274         }
1275
1276         buffer[size] = '\0';
1277         printf("readlink: %s\n", buffer);
1278         return NT_STATUS_OK;
1279 }
1280
1281
1282 static NTSTATUS cmd_link(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
1283 {
1284         struct smb_filename *old_smb_fname = NULL;
1285         struct smb_filename *new_smb_fname = NULL;
1286         int ret;
1287
1288         if (argc != 3) {
1289                 printf("Usage: link <path> <link>\n");
1290                 return NT_STATUS_OK;
1291         }
1292
1293         old_smb_fname = synthetic_smb_fname_split(mem_ctx,
1294                                         argv[1],
1295                                         lp_posix_pathnames());
1296         if (old_smb_fname == NULL) {
1297                 return NT_STATUS_NO_MEMORY;
1298         }
1299         new_smb_fname = synthetic_smb_fname_split(mem_ctx,
1300                                         argv[2],
1301                                         lp_posix_pathnames());
1302         if (new_smb_fname == NULL) {
1303                 return NT_STATUS_NO_MEMORY;
1304         }
1305
1306         ret = SMB_VFS_LINKAT(vfs->conn,
1307                         vfs->conn->cwd_fsp,
1308                         old_smb_fname,
1309                         vfs->conn->cwd_fsp,
1310                         new_smb_fname,
1311                         0);
1312         if (ret == -1) {
1313                 printf("link: error=%d (%s)\n", errno, strerror(errno));
1314                 return NT_STATUS_UNSUCCESSFUL;
1315         }
1316
1317         printf("link: ok\n");
1318         return NT_STATUS_OK;
1319 }
1320
1321 static NTSTATUS cmd_mknod(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
1322 {
1323         mode_t mode;
1324         unsigned int dev_val;
1325         SMB_DEV_T dev;
1326         struct smb_filename *smb_fname = NULL;
1327         int ret;
1328
1329         if (argc != 4) {
1330                 printf("Usage: mknod <path> <mode> <dev>\n");
1331                 printf("  mode is octal\n");
1332                 printf("  dev is hex\n");
1333                 return NT_STATUS_OK;
1334         }
1335
1336         if (sscanf(argv[2], "%ho", (unsigned short *)&mode) == 0) {
1337                 printf("open: error=-1 (invalid mode!)\n");
1338                 return NT_STATUS_UNSUCCESSFUL;
1339         }
1340
1341         if (sscanf(argv[3], "%x", &dev_val) == 0) {
1342                 printf("open: error=-1 (invalid dev!)\n");
1343                 return NT_STATUS_UNSUCCESSFUL;
1344         }
1345         dev = (SMB_DEV_T)dev_val;
1346
1347         smb_fname = synthetic_smb_fname_split(mem_ctx,
1348                                         argv[1],
1349                                         lp_posix_pathnames());
1350         if (smb_fname == NULL) {
1351                 return NT_STATUS_NO_MEMORY;
1352         }
1353
1354         ret = SMB_VFS_MKNODAT(vfs->conn,
1355                         vfs->conn->cwd_fsp,
1356                         smb_fname,
1357                         mode,
1358                         dev);
1359
1360         if (ret == -1) {
1361                 printf("mknod: error=%d (%s)\n", errno, strerror(errno));
1362                 return NT_STATUS_UNSUCCESSFUL;
1363         }
1364
1365         printf("mknod: ok\n");
1366         return NT_STATUS_OK;
1367 }
1368
1369 static NTSTATUS cmd_realpath(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
1370 {
1371         struct smb_filename *smb_fname = NULL;
1372
1373         if (argc != 2) {
1374                 printf("Usage: realpath <path>\n");
1375                 return NT_STATUS_OK;
1376         }
1377
1378         smb_fname = synthetic_smb_fname_split(mem_ctx,
1379                                         argv[1],
1380                                         lp_posix_pathnames());
1381         if (smb_fname == NULL) {
1382                 return NT_STATUS_NO_MEMORY;
1383         }
1384         if (SMB_VFS_REALPATH(vfs->conn, mem_ctx, smb_fname) == NULL) {
1385                 printf("realpath: error=%d (%s)\n", errno, strerror(errno));
1386                 return NT_STATUS_UNSUCCESSFUL;
1387         }
1388
1389         printf("realpath: ok\n");
1390         return NT_STATUS_OK;
1391 }
1392
1393 static NTSTATUS cmd_getxattr(struct vfs_state *vfs, TALLOC_CTX *mem_ctx,
1394                              int argc, const char **argv)
1395 {
1396         uint8_t *buf;
1397         ssize_t ret;
1398         struct smb_filename *smb_fname = NULL;
1399         struct smb_filename *pathref_fname = NULL;
1400         NTSTATUS status;
1401
1402         if (argc != 3) {
1403                 printf("Usage: getxattr <path> <xattr>\n");
1404                 return NT_STATUS_OK;
1405         }
1406
1407         buf = NULL;
1408
1409         smb_fname = synthetic_smb_fname_split(mem_ctx,
1410                                         argv[1],
1411                                         lp_posix_pathnames());
1412         if (smb_fname == NULL) {
1413                 return NT_STATUS_NO_MEMORY;
1414         }
1415         status = synthetic_pathref(mem_ctx,
1416                                 vfs->conn->cwd_fsp,
1417                                 smb_fname->base_name,
1418                                 NULL,
1419                                 NULL,
1420                                 smb_fname->twrp,
1421                                 smb_fname->flags,
1422                                 &pathref_fname);
1423         if (!NT_STATUS_IS_OK(status)) {
1424                 return status;
1425         }
1426         ret = SMB_VFS_FGETXATTR(pathref_fname->fsp,
1427                                 argv[2],
1428                                 buf,
1429                                 talloc_get_size(buf));
1430         if (ret == -1) {
1431                 int err = errno;
1432                 printf("getxattr returned (%s)\n", strerror(err));
1433                 return map_nt_error_from_unix(err);
1434         }
1435         buf = talloc_array(mem_ctx, uint8_t, ret);
1436         if (buf == NULL) {
1437                 return NT_STATUS_NO_MEMORY;
1438         }
1439         ret = SMB_VFS_FGETXATTR(pathref_fname->fsp,
1440                                 argv[2],
1441                                 buf,
1442                                 talloc_get_size(buf));
1443         if (ret == -1) {
1444                 int err = errno;
1445                 printf("getxattr returned (%s)\n", strerror(err));
1446                 return map_nt_error_from_unix(err);
1447         }
1448         dump_data_file(buf, talloc_get_size(buf), false, stdout);
1449         return NT_STATUS_OK;
1450 }
1451
1452 static NTSTATUS cmd_listxattr(struct vfs_state *vfs, TALLOC_CTX *mem_ctx,
1453                               int argc, const char **argv)
1454 {
1455         char *buf, *p;
1456         ssize_t ret;
1457         struct smb_filename *smb_fname = NULL;
1458         struct smb_filename *pathref_fname = NULL;
1459         NTSTATUS status;
1460         if (argc != 2) {
1461                 printf("Usage: listxattr <path>\n");
1462                 return NT_STATUS_OK;
1463         }
1464
1465         buf = NULL;
1466
1467         smb_fname = synthetic_smb_fname_split(mem_ctx,
1468                                         argv[1],
1469                                         lp_posix_pathnames());
1470         if (smb_fname == NULL) {
1471                 return NT_STATUS_NO_MEMORY;
1472         }
1473         status = synthetic_pathref(mem_ctx,
1474                                 vfs->conn->cwd_fsp,
1475                                 smb_fname->base_name,
1476                                 NULL,
1477                                 NULL,
1478                                 smb_fname->twrp,
1479                                 smb_fname->flags,
1480                                 &pathref_fname);
1481         if (!NT_STATUS_IS_OK(status)) {
1482                 return status;
1483         }
1484
1485         ret = SMB_VFS_FLISTXATTR(pathref_fname->fsp,
1486                                 buf, talloc_get_size(buf));
1487         if (ret == -1) {
1488                 int err = errno;
1489                 printf("listxattr returned (%s)\n", strerror(err));
1490                 return map_nt_error_from_unix(err);
1491         }
1492         buf = talloc_array(mem_ctx, char, ret);
1493         if (buf == NULL) {
1494                 return NT_STATUS_NO_MEMORY;
1495         }
1496         ret = SMB_VFS_FLISTXATTR(pathref_fname->fsp,
1497                                 buf, talloc_get_size(buf));
1498         if (ret == -1) {
1499                 int err = errno;
1500                 printf("listxattr returned (%s)\n", strerror(err));
1501                 return map_nt_error_from_unix(err);
1502         }
1503         if (ret == 0) {
1504                 return NT_STATUS_OK;
1505         }
1506         if (buf[ret-1] != '\0') {
1507                 printf("listxattr returned non 0-terminated strings\n");
1508                 return NT_STATUS_INTERNAL_ERROR;
1509         }
1510
1511         p = buf;
1512         while (p < buf+ret) {
1513                 printf("%s\n", p);
1514                 p = strchr(p, 0);
1515                 p += 1;
1516         }
1517         return NT_STATUS_OK;
1518 }
1519
1520 static NTSTATUS cmd_fsetxattr(struct vfs_state *vfs, TALLOC_CTX *mem_ctx,
1521                              int argc, const char **argv)
1522 {
1523         ssize_t ret;
1524         int flags = 0;
1525         struct smb_filename *smb_fname = NULL;
1526         struct smb_filename *pathref_fname = NULL;
1527         NTSTATUS status;
1528
1529         if ((argc < 4) || (argc > 5)) {
1530                 printf("Usage: setxattr <path> <xattr> <value> [flags]\n");
1531                 return NT_STATUS_OK;
1532         }
1533
1534         if (argc == 5) {
1535                 flags = atoi(argv[4]);
1536         }
1537
1538         smb_fname = synthetic_smb_fname_split(mem_ctx,
1539                                         argv[1],
1540                                         lp_posix_pathnames());
1541         if (smb_fname == NULL) {
1542                 return NT_STATUS_NO_MEMORY;
1543         }
1544
1545         status = synthetic_pathref(mem_ctx,
1546                                 vfs->conn->cwd_fsp,
1547                                 smb_fname->base_name,
1548                                 NULL,
1549                                 NULL,
1550                                 smb_fname->twrp,
1551                                 smb_fname->flags,
1552                                 &pathref_fname);
1553         if (!NT_STATUS_IS_OK(status)) {
1554                 return status;
1555         }
1556
1557         ret = SMB_VFS_FSETXATTR(pathref_fname->fsp, argv[2],
1558                                argv[3], strlen(argv[3]), flags);
1559         if (ret == -1) {
1560                 int err = errno;
1561                 printf("fsetxattr returned (%s)\n", strerror(err));
1562                 return map_nt_error_from_unix(err);
1563         }
1564         return NT_STATUS_OK;
1565 }
1566
1567 static NTSTATUS cmd_removexattr(struct vfs_state *vfs, TALLOC_CTX *mem_ctx,
1568                                 int argc, const char **argv)
1569 {
1570         ssize_t ret;
1571         struct smb_filename *smb_fname = NULL;
1572         struct smb_filename *pathref_fname = NULL;
1573         NTSTATUS status;
1574
1575         if (argc != 3) {
1576                 printf("Usage: removexattr <path> <xattr>\n");
1577                 return NT_STATUS_OK;
1578         }
1579
1580         smb_fname = synthetic_smb_fname_split(mem_ctx,
1581                                         argv[1],
1582                                         lp_posix_pathnames());
1583         if (smb_fname == NULL) {
1584                 return NT_STATUS_NO_MEMORY;
1585         }
1586         status = synthetic_pathref(mem_ctx,
1587                                 vfs->conn->cwd_fsp,
1588                                 smb_fname->base_name,
1589                                 NULL,
1590                                 NULL,
1591                                 smb_fname->twrp,
1592                                 smb_fname->flags,
1593                                 &pathref_fname);
1594         if (!NT_STATUS_IS_OK(status)) {
1595                 return status;
1596         }
1597         ret = SMB_VFS_FREMOVEXATTR(pathref_fname->fsp, argv[2]);
1598         if (ret == -1) {
1599                 int err = errno;
1600                 printf("removexattr returned (%s)\n", strerror(err));
1601                 return map_nt_error_from_unix(err);
1602         }
1603         return NT_STATUS_OK;
1604 }
1605
1606 static NTSTATUS cmd_fget_nt_acl(struct vfs_state *vfs, TALLOC_CTX *mem_ctx,
1607                                 int argc, const char **argv)
1608 {
1609         int fd;
1610         NTSTATUS status;
1611         struct security_descriptor *sd;
1612
1613         if (argc != 2) {
1614                 printf("Usage: fget_nt_acl <fd>\n");
1615                 return NT_STATUS_OK;
1616         }
1617
1618         fd = atoi(argv[1]);
1619         if (fd < 0 || fd >= 1024) {
1620                 printf("fget_nt_acl: error=%d (file descriptor out of range)\n", EBADF);
1621                 return NT_STATUS_OK;
1622         }
1623         if (vfs->files[fd] == NULL) {
1624                 printf("fget_nt_acl: error=%d (invalid file descriptor)\n", EBADF);
1625                 return NT_STATUS_OK;
1626         }
1627
1628         status = SMB_VFS_FGET_NT_ACL(vfs->files[fd],
1629                                      SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL,
1630                                      talloc_tos(), &sd);
1631         if (!NT_STATUS_IS_OK(status)) {
1632                 printf("fget_nt_acl returned (%s)\n", nt_errstr(status));
1633                 return status;
1634         }
1635         printf("%s\n", sddl_encode(talloc_tos(), sd, get_global_sam_sid()));
1636         TALLOC_FREE(sd);
1637         return NT_STATUS_OK;
1638 }
1639
1640 static NTSTATUS cmd_get_nt_acl(struct vfs_state *vfs, TALLOC_CTX *mem_ctx,
1641                                int argc, const char **argv)
1642 {
1643         NTSTATUS status;
1644         struct security_descriptor *sd;
1645         struct smb_filename *smb_fname = NULL;
1646         struct smb_filename *pathref_fname = NULL;
1647
1648         if (argc != 2) {
1649                 printf("Usage: get_nt_acl <path>\n");
1650                 return NT_STATUS_OK;
1651         }
1652
1653         smb_fname = synthetic_smb_fname(talloc_tos(),
1654                                         argv[1],
1655                                         NULL,
1656                                         NULL,
1657                                         0,
1658                                         ssf_flags());
1659
1660         if (smb_fname == NULL) {
1661                 return NT_STATUS_NO_MEMORY;
1662         }
1663
1664         status = synthetic_pathref(mem_ctx,
1665                                 vfs->conn->cwd_fsp,
1666                                 smb_fname->base_name,
1667                                 NULL,
1668                                 NULL,
1669                                 smb_fname->twrp,
1670                                 smb_fname->flags,
1671                                 &pathref_fname);
1672         if (!NT_STATUS_IS_OK(status)) {
1673                 TALLOC_FREE(smb_fname);
1674                 return status;
1675         }
1676         status = SMB_VFS_FGET_NT_ACL(pathref_fname->fsp,
1677                                 SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL,
1678                                 talloc_tos(),
1679                                 &sd);
1680         if (!NT_STATUS_IS_OK(status)) {
1681                 printf("get_nt_acl returned (%s)\n", nt_errstr(status));
1682                 TALLOC_FREE(smb_fname);
1683                 TALLOC_FREE(pathref_fname);
1684                 return status;
1685         }
1686         printf("%s\n", sddl_encode(talloc_tos(), sd, get_global_sam_sid()));
1687         TALLOC_FREE(sd);
1688         TALLOC_FREE(smb_fname);
1689         TALLOC_FREE(pathref_fname);
1690         return NT_STATUS_OK;
1691 }
1692
1693 static NTSTATUS cmd_fset_nt_acl(struct vfs_state *vfs, TALLOC_CTX *mem_ctx,
1694                                 int argc, const char **argv)
1695 {
1696         int fd;
1697         NTSTATUS status;
1698         struct security_descriptor *sd;
1699
1700         if (argc != 3) {
1701                 printf("Usage: fset_nt_acl <fd> <sddl>\n");
1702                 return NT_STATUS_OK;
1703         }
1704
1705         fd = atoi(argv[1]);
1706         if (fd < 0 || fd >= 1024) {
1707                 printf("fset_nt_acl: error=%d (file descriptor out of range)\n", EBADF);
1708                 return NT_STATUS_OK;
1709         }
1710         if (vfs->files[fd] == NULL) {
1711                 printf("fset_nt_acl: error=%d (invalid file descriptor)\n", EBADF);
1712                 return NT_STATUS_OK;
1713         }
1714
1715         sd = sddl_decode(talloc_tos(), argv[2], get_global_sam_sid());
1716         if (!sd) {
1717                 printf("sddl_decode failed to parse %s as SDDL\n", argv[2]);
1718                 return NT_STATUS_INVALID_PARAMETER;
1719         }
1720
1721         status = SMB_VFS_FSET_NT_ACL(vfs->files[fd], SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL, sd);
1722         if (!NT_STATUS_IS_OK(status)) {
1723                 printf("fset_nt_acl returned (%s)\n", nt_errstr(status));
1724                 return status;
1725         }
1726         TALLOC_FREE(sd);
1727         return NT_STATUS_OK;
1728 }
1729
1730 static NTSTATUS cmd_set_nt_acl(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
1731 {
1732         int flags;
1733         mode_t mode;
1734         files_struct *fsp;
1735         struct files_struct *fspcwd = NULL;
1736         struct smb_filename *smb_fname = NULL;
1737         NTSTATUS status;
1738         struct security_descriptor *sd = NULL;
1739         int fd;
1740
1741         if (argc != 3) {
1742                 printf("Usage: set_nt_acl <file> <sddl>\n");
1743                 return NT_STATUS_OK;
1744         }
1745
1746         mode = 00400;
1747
1748         fsp = talloc_zero(vfs, struct files_struct);
1749         if (fsp == NULL) {
1750                 return NT_STATUS_NO_MEMORY;
1751         }
1752         fsp->fh = fd_handle_create(fsp);
1753         if (fsp->fh == NULL) {
1754                 TALLOC_FREE(fsp);
1755                 return NT_STATUS_NO_MEMORY;
1756         }
1757         fsp->conn = vfs->conn;
1758
1759         smb_fname = synthetic_smb_fname_split(NULL,
1760                                         argv[1],
1761                                         lp_posix_pathnames());
1762         if (smb_fname == NULL) {
1763                 TALLOC_FREE(fsp);
1764                 return NT_STATUS_NO_MEMORY;
1765         }
1766
1767         fsp->fsp_name = smb_fname;
1768
1769 #ifdef O_DIRECTORY
1770         flags = O_RDONLY|O_DIRECTORY;
1771 #else
1772         /* POSIX allows us to open a directory with O_RDONLY. */
1773         flags = O_RDONLY;
1774 #endif
1775
1776         status = vfs_at_fspcwd(fsp, vfs->conn, &fspcwd);
1777         if (!NT_STATUS_IS_OK(status)) {
1778                 return status;
1779         }
1780
1781         fd = SMB_VFS_OPENAT(vfs->conn,
1782                             fspcwd,
1783                             smb_fname,
1784                             fsp,
1785                             O_RDWR,
1786                             mode);
1787         if (fd == -1 && errno == EISDIR) {
1788                 fd = SMB_VFS_OPENAT(vfs->conn,
1789                                     fspcwd,
1790                                     smb_fname,
1791                                     fsp,
1792                                     flags,
1793                                     mode);
1794         }
1795         if (fd == -1) {
1796                 printf("open: error=%d (%s)\n", errno, strerror(errno));
1797                 TALLOC_FREE(fsp);
1798                 TALLOC_FREE(smb_fname);
1799                 return NT_STATUS_UNSUCCESSFUL;
1800         }
1801         fsp_set_fd(fsp, fd);
1802
1803         status = vfs_stat_fsp(fsp);
1804         if (!NT_STATUS_IS_OK(status)) {
1805                 /* If we have an fd, this stat should succeed. */
1806                 DEBUG(0,("Error doing fstat on open file %s "
1807                          "(%s)\n",
1808                          smb_fname_str_dbg(smb_fname),
1809                          nt_errstr(status) ));
1810                 goto out;
1811         }
1812
1813         fsp->file_id = vfs_file_id_from_sbuf(vfs->conn, &smb_fname->st);
1814         fsp->vuid = UID_FIELD_INVALID;
1815         fsp->file_pid = 0;
1816         fsp->fsp_flags.can_lock = true;
1817         fsp->fsp_flags.can_read = true;
1818         fsp->fsp_flags.can_write = true;
1819         fsp->print_file = NULL;
1820         fsp->fsp_flags.modified = false;
1821         fsp->sent_oplock_break = NO_BREAK_SENT;
1822         fsp->fsp_flags.is_directory = S_ISDIR(smb_fname->st.st_ex_mode);
1823
1824         sd = sddl_decode(talloc_tos(), argv[2], get_global_sam_sid());
1825         if (!sd) {
1826                 printf("sddl_decode failed to parse %s as SDDL\n", argv[2]);
1827                 status = NT_STATUS_INVALID_PARAMETER;
1828                 goto out;
1829         }
1830
1831         status = SMB_VFS_FSET_NT_ACL(fsp, SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL, sd);
1832         if (!NT_STATUS_IS_OK(status)) {
1833                 printf("fset_nt_acl returned (%s)\n", nt_errstr(status));
1834                 goto out;
1835         }
1836 out:
1837         TALLOC_FREE(sd);
1838
1839         status = fd_close(fsp);
1840         if (!NT_STATUS_IS_OK(status))
1841                 printf("close: error= (%s)\n", nt_errstr(status));
1842
1843         TALLOC_FREE(fsp);
1844
1845         return status;
1846 }
1847
1848
1849
1850 static NTSTATUS cmd_sys_acl_get_fd(struct vfs_state *vfs, TALLOC_CTX *mem_ctx,
1851                                    int argc, const char **argv)
1852 {
1853         int fd;
1854         SMB_ACL_T acl;
1855         char *acl_text;
1856
1857         if (argc != 2) {
1858                 printf("Usage: sys_acl_get_fd <fd>\n");
1859                 return NT_STATUS_OK;
1860         }
1861
1862         fd = atoi(argv[1]);
1863         if (fd < 0 || fd >= 1024) {
1864                 printf("sys_acl_get_fd: error=%d (file descriptor out of range)\n", EBADF);
1865                 return NT_STATUS_OK;
1866         }
1867         if (vfs->files[fd] == NULL) {
1868                 printf("sys_acl_get_fd: error=%d (invalid file descriptor)\n", EBADF);
1869                 return NT_STATUS_OK;
1870         }
1871
1872         acl = SMB_VFS_SYS_ACL_GET_FD(vfs->files[fd],
1873                                      SMB_ACL_TYPE_ACCESS,
1874                                      talloc_tos());
1875         if (!acl) {
1876                 printf("sys_acl_get_fd failed (%s)\n", strerror(errno));
1877                 return NT_STATUS_UNSUCCESSFUL;
1878         }
1879         acl_text = sys_acl_to_text(acl, NULL);
1880         printf("%s", acl_text);
1881         TALLOC_FREE(acl);
1882         SAFE_FREE(acl_text);
1883         return NT_STATUS_OK;
1884 }
1885
1886 static NTSTATUS cmd_sys_acl_get_file(struct vfs_state *vfs, TALLOC_CTX *mem_ctx,
1887                                      int argc, const char **argv)
1888 {
1889         SMB_ACL_T acl;
1890         char *acl_text;
1891         int type;
1892         struct smb_filename *smb_fname = NULL;
1893         struct smb_filename *pathref_fname = NULL;
1894         NTSTATUS status;
1895
1896         if (argc != 3) {
1897                 printf("Usage: sys_acl_get_file <path> <type>\n");
1898                 return NT_STATUS_OK;
1899         }
1900
1901         smb_fname = synthetic_smb_fname_split(talloc_tos(),
1902                                         argv[1],
1903                                         lp_posix_pathnames());
1904         if (smb_fname == NULL) {
1905                 return NT_STATUS_NO_MEMORY;
1906         }
1907         type = atoi(argv[2]);
1908
1909         status = synthetic_pathref(mem_ctx,
1910                                 vfs->conn->cwd_fsp,
1911                                 smb_fname->base_name,
1912                                 NULL,
1913                                 NULL,
1914                                 smb_fname->twrp,
1915                                 smb_fname->flags,
1916                                 &pathref_fname);
1917         if (!NT_STATUS_IS_OK(status)) {
1918                 TALLOC_FREE(smb_fname);
1919                 return status;
1920         }
1921
1922         acl = SMB_VFS_SYS_ACL_GET_FD(pathref_fname->fsp,
1923                                 type, talloc_tos());
1924         if (!acl) {
1925                 printf("sys_acl_get_fd failed (%s)\n", strerror(errno));
1926                 TALLOC_FREE(smb_fname);
1927                 TALLOC_FREE(pathref_fname);
1928                 return NT_STATUS_UNSUCCESSFUL;
1929         }
1930         acl_text = sys_acl_to_text(acl, NULL);
1931         printf("%s", acl_text);
1932         TALLOC_FREE(acl);
1933         TALLOC_FREE(smb_fname);
1934         TALLOC_FREE(pathref_fname);
1935         SAFE_FREE(acl_text);
1936         return NT_STATUS_OK;
1937 }
1938
1939 static NTSTATUS cmd_sys_acl_blob_get_file(struct vfs_state *vfs,
1940                                           TALLOC_CTX *mem_ctx,
1941                                           int argc, const char **argv)
1942 {
1943         char *description;
1944         DATA_BLOB blob;
1945         int ret;
1946         size_t i;
1947         struct smb_filename *smb_fname = NULL;
1948         struct smb_filename *pathref_fname = NULL;
1949         NTSTATUS status;
1950
1951         if (argc != 2) {
1952                 printf("Usage: sys_acl_blob_get_file <path>\n");
1953                 return NT_STATUS_OK;
1954         }
1955
1956         smb_fname = synthetic_smb_fname_split(mem_ctx,
1957                                         argv[1],
1958                                         lp_posix_pathnames());
1959         if (smb_fname == NULL) {
1960                 return NT_STATUS_NO_MEMORY;
1961         }
1962         status = synthetic_pathref(mem_ctx,
1963                                 vfs->conn->cwd_fsp,
1964                                 smb_fname->base_name,
1965                                 NULL,
1966                                 NULL,
1967                                 smb_fname->twrp,
1968                                 smb_fname->flags,
1969                                 &pathref_fname);
1970         if (!NT_STATUS_IS_OK(status)) {
1971                 TALLOC_FREE(smb_fname);
1972                 return status;
1973         }
1974
1975         ret = SMB_VFS_SYS_ACL_BLOB_GET_FD(pathref_fname->fsp,
1976                                           talloc_tos(),
1977                                           &description,
1978                                           &blob);
1979         if (ret != 0) {
1980                 status = map_nt_error_from_unix(errno);
1981                 printf("sys_acl_blob_get_file failed (%s)\n", strerror(errno));
1982                 TALLOC_FREE(smb_fname);
1983                 TALLOC_FREE(pathref_fname);
1984                 return status;
1985         }
1986         printf("Description: %s\n", description);
1987         for (i = 0; i < blob.length; i++) {
1988                 printf("%.2x ", blob.data[i]);
1989         }
1990         printf("\n");
1991
1992         TALLOC_FREE(smb_fname);
1993         TALLOC_FREE(pathref_fname);
1994         return NT_STATUS_OK;
1995 }
1996
1997 static NTSTATUS cmd_sys_acl_blob_get_fd(struct vfs_state *vfs,
1998                                         TALLOC_CTX *mem_ctx,
1999                                         int argc, const char **argv)
2000 {
2001         int fd;
2002         char *description;
2003         DATA_BLOB blob;
2004         int ret;
2005         size_t i;
2006
2007         if (argc != 2) {
2008                 printf("Usage: sys_acl_blob_get_fd <fd>\n");
2009                 return NT_STATUS_OK;
2010         }
2011
2012         fd = atoi(argv[1]);
2013         if (fd < 0 || fd >= 1024) {
2014                 printf("sys_acl_blob_get_fd: error=%d "
2015                        "(file descriptor out of range)\n", EBADF);
2016                 return NT_STATUS_OK;
2017         }
2018         if (vfs->files[fd] == NULL) {
2019                 printf("sys_acl_blob_get_fd: error=%d "
2020                        "(invalid file descriptor)\n", EBADF);
2021                 return NT_STATUS_OK;
2022         }
2023
2024         ret = SMB_VFS_SYS_ACL_BLOB_GET_FD(vfs->files[fd], talloc_tos(),
2025                                           &description, &blob);
2026         if (ret != 0) {
2027                 printf("sys_acl_blob_get_fd failed (%s)\n", strerror(errno));
2028                 return map_nt_error_from_unix(errno);
2029         }
2030         printf("Description: %s\n", description);
2031         for (i = 0; i < blob.length; i++) {
2032                 printf("%.2x ", blob.data[i]);
2033         }
2034         printf("\n");
2035
2036         return NT_STATUS_OK;
2037 }
2038
2039
2040
2041 static NTSTATUS cmd_sys_acl_delete_def_file(struct vfs_state *vfs, TALLOC_CTX *mem_ctx,
2042                                             int argc, const char **argv)
2043 {
2044         int ret;
2045         struct smb_filename *smb_fname = NULL;
2046         struct smb_filename *pathref_fname = NULL;
2047         NTSTATUS status;
2048
2049         if (argc != 2) {
2050                 printf("Usage: sys_acl_delete_def_file <path>\n");
2051                 return NT_STATUS_OK;
2052         }
2053
2054         smb_fname = synthetic_smb_fname_split(mem_ctx,
2055                                         argv[1],
2056                                         lp_posix_pathnames());
2057         if (smb_fname == NULL) {
2058                 return NT_STATUS_NO_MEMORY;
2059         }
2060         status = synthetic_pathref(mem_ctx,
2061                                 vfs->conn->cwd_fsp,
2062                                 smb_fname->base_name,
2063                                 NULL,
2064                                 NULL,
2065                                 smb_fname->twrp,
2066                                 smb_fname->flags,
2067                                 &pathref_fname);
2068         if (!NT_STATUS_IS_OK(status)) {
2069                 TALLOC_FREE(smb_fname);
2070                 return status;
2071         }
2072         if (!pathref_fname->fsp->fsp_flags.is_directory) {
2073                 printf("sys_acl_delete_def_file - %s is not a directory\n",
2074                         smb_fname->base_name);
2075                 TALLOC_FREE(smb_fname);
2076                 TALLOC_FREE(pathref_fname);
2077                 return NT_STATUS_INVALID_PARAMETER;
2078         }
2079         ret = SMB_VFS_SYS_ACL_DELETE_DEF_FD(pathref_fname->fsp);
2080         if (ret == -1) {
2081                 int err = errno;
2082                 printf("sys_acl_delete_def_file failed (%s)\n", strerror(err));
2083                 TALLOC_FREE(smb_fname);
2084                 TALLOC_FREE(pathref_fname);
2085                 return map_nt_error_from_unix(err);
2086         }
2087         TALLOC_FREE(smb_fname);
2088         TALLOC_FREE(pathref_fname);
2089         return NT_STATUS_OK;
2090 }
2091
2092 /* Afaik translate name was first introduced with vfs_catia, to be able
2093    to translate unix file/dir-names, containing invalid windows characters,
2094    to valid windows names.
2095    The used translation direction is always unix --> windows
2096 */
2097 static NTSTATUS cmd_translate_name(struct vfs_state *vfs, TALLOC_CTX *mem_ctx,
2098                                             int argc, const char **argv)
2099 {
2100         const char *dname = NULL;
2101         char *dname_talloced = NULL;
2102         SMB_STRUCT_STAT st;
2103         bool found = false;
2104         char *translated = NULL;
2105         struct smb_filename *smb_fname = NULL;
2106         NTSTATUS status;
2107
2108         if (argc != 2) {
2109                 DEBUG(0, ("Usage: translate_name unix_filename\n"));
2110                 return NT_STATUS_UNSUCCESSFUL;
2111         }
2112
2113         smb_fname = synthetic_smb_fname(talloc_tos(),
2114                                         ".",
2115                                         NULL,
2116                                         NULL,
2117                                         0,
2118                                         ssf_flags());
2119         if (smb_fname == NULL) {
2120                 return NT_STATUS_NO_MEMORY;
2121         }
2122
2123         status = OpenDir(vfs->conn,
2124                          vfs->conn,
2125                          smb_fname,
2126                          NULL,
2127                          0,
2128                          &vfs->currentdir);
2129         if (!NT_STATUS_IS_OK(status)) {
2130                 int err = map_errno_from_nt_status(status);
2131                 DEBUG(0, ("cmd_translate_name: opendir error=%d (%s)\n",
2132                           err, strerror(err)));
2133                 TALLOC_FREE(smb_fname);
2134                 errno = err;
2135                 return NT_STATUS_UNSUCCESSFUL;
2136         }
2137         vfs->currentdir_offset = 0;
2138
2139         while (true) {
2140                 /* ReadDirName() returns Windows "encoding" */
2141                 dname = ReadDirName(vfs->currentdir,
2142                                     &vfs->currentdir_offset,
2143                                     &st,
2144                                     &dname_talloced);
2145                 if (dname == NULL) {
2146                         break;
2147                 }
2148
2149                 /* Convert Windows "encoding" from ReadDirName() to UNIX */
2150                 status = SMB_VFS_TRANSLATE_NAME(vfs->conn,
2151                                                 dname,
2152                                                 vfs_translate_to_unix,
2153                                                 talloc_tos(),
2154                                                 &translated);
2155                 if (!NT_STATUS_IS_OK(status)) {
2156                         DBG_ERR("file '%s' cannot be translated\n", argv[1]);
2157                         goto cleanup;
2158                 }
2159
2160                 /*
2161                  * argv[1] uses UNIX "encoding", so compare with translation
2162                  * result.
2163                  */
2164                 if (strcmp(translated, argv[1]) == 0) {
2165                         found = true;
2166                         break;
2167                 }
2168                 TALLOC_FREE(dname_talloced);
2169                 TALLOC_FREE(translated);
2170         };
2171
2172         if (!found) {
2173                 DEBUG(0, ("cmd_translate_name: file '%s' not found.\n", 
2174                           argv[1]));
2175                 status = NT_STATUS_UNSUCCESSFUL;
2176                 goto cleanup;
2177         }
2178
2179         /* translation success. But that could also mean
2180            that translating "aaa" to "aaa" was successful :-(
2181         */ 
2182         DBG_ERR("file '%s' --> '%s'\n", argv[1], dname);
2183         status = NT_STATUS_OK;
2184
2185 cleanup:
2186         TALLOC_FREE(dname_talloced);
2187         TALLOC_FREE(translated);
2188         TALLOC_FREE(smb_fname);
2189         TALLOC_FREE(vfs->currentdir);
2190         vfs->currentdir_offset = 0;
2191         return status;
2192 }
2193
2194 /*
2195  * This is a quick hack to demonstrate a crash in the full_audit
2196  * module when passing fsp->smb_fname into SMB_VFS_CREATE_FILE leading
2197  * to an error.
2198  *
2199  * Feel free to expand with more options as needed
2200  */
2201 static NTSTATUS cmd_create_file(
2202         struct vfs_state *vfs,
2203         TALLOC_CTX *mem_ctx,
2204         int argc,
2205         const char **argv)
2206 {
2207         struct smb_filename *fname = NULL;
2208         struct files_struct *fsp = NULL;
2209         int info, ret;
2210         NTSTATUS status;
2211
2212         if (argc != 2) {
2213                 DBG_ERR("Usage: create_file filename\n");
2214                 return NT_STATUS_UNSUCCESSFUL;
2215         }
2216
2217         fname = synthetic_smb_fname(
2218                 talloc_tos(), argv[1], NULL, NULL, 0, 0);
2219         if (fname == NULL) {
2220                 return NT_STATUS_NO_MEMORY;
2221         }
2222
2223         ret = vfs_stat(vfs->conn, fname);
2224         if (ret != 0) {
2225                 status = map_nt_error_from_unix(errno);
2226                 DBG_DEBUG("vfs_stat() failed: %s\n", strerror(errno));
2227                 TALLOC_FREE(fname);
2228                 return status;
2229         }
2230
2231         status = openat_pathref_fsp(vfs->conn->cwd_fsp, fname);
2232         if (!NT_STATUS_IS_OK(status)) {
2233                 DBG_DEBUG("Could not open %s: %s\n",
2234                           fname->base_name,
2235                           nt_errstr(status));
2236                 TALLOC_FREE(fname);
2237                 return status;
2238         }
2239
2240         status = SMB_VFS_CREATE_FILE(
2241                 vfs->conn,
2242                 NULL,
2243
2244                 /*
2245                  * Using fname->fsp->fsp_name seems to be legal,
2246                  * there's code to handle this in
2247                  * create_file_unixpath(). And it is actually very
2248                  * worthwhile re-using the fsp_name, we can save quite
2249                  * a few copies of smb_filename with that.
2250                  */
2251                 fname->fsp->fsp_name,
2252                 SEC_FILE_ALL,
2253                 FILE_SHARE_NONE,
2254                 FILE_OPEN,
2255                 FILE_NON_DIRECTORY_FILE,
2256                 0,
2257                 0,
2258                 NULL,
2259                 0,
2260                 0,
2261                 NULL,
2262                 NULL,
2263                 &fsp,
2264                 &info,
2265                 NULL,
2266                 NULL
2267                 );
2268         DBG_DEBUG("create_file returned %s\n", nt_errstr(status));
2269
2270         TALLOC_FREE(fname);
2271
2272         return NT_STATUS_OK;
2273 }
2274
2275 struct cmd_set vfs_commands[] = {
2276
2277         { .name = "VFS Commands" },
2278
2279         { "load", cmd_load_module, "Load a module", "load <module.so>" },
2280         { "populate", cmd_populate, "Populate a data buffer", "populate <char> <size>" },
2281         { "showdata", cmd_show_data, "Show data currently in data buffer", "show_data [<offset> <len>]"},
2282         { "connect",   cmd_connect,   "VFS connect()",    "connect" },
2283         { "disconnect",   cmd_disconnect,   "VFS disconnect()",    "disconnect" },
2284         { "disk_free",   cmd_disk_free,   "VFS disk_free()",    "disk_free <path>" },
2285         { "opendir",   cmd_opendir,   "VFS opendir()",    "opendir <fname>" },
2286         { "readdir",   cmd_readdir,   "VFS readdir()",    "readdir" },
2287         { "mkdir",   cmd_mkdir,   "VFS mkdir()",    "mkdir <path>" },
2288         { "rmdir",   cmd_pathfunc,   "VFS rmdir()",    "rmdir <path>" },
2289         { "closedir",   cmd_closedir,   "VFS closedir()",    "closedir" },
2290         { "open",   cmd_open,   "VFS open()",    "open <fname> <flags> <mode>" },
2291         { "close",   cmd_close,   "VFS close()",    "close <fd>" },
2292         { "read",   cmd_read,   "VFS read()",    "read <fd> <size>" },
2293         { "write",   cmd_write,   "VFS write()",    "write <fd> <size>" },
2294         { "lseek",   cmd_lseek,   "VFS lseek()",    "lseek <fd> <offset> <whence>" },
2295         { "rename",   cmd_rename,   "VFS rename()",    "rename <old> <new>" },
2296         { "fsync",   cmd_fsync,   "VFS fsync()",    "fsync <fd>" },
2297         { "stat",   cmd_stat,   "VFS stat()",    "stat <fname>" },
2298         { "fstat",   cmd_fstat,   "VFS fstat()",    "fstat <fd>" },
2299         { "lstat",   cmd_lstat,   "VFS lstat()",    "lstat <fname>" },
2300         { "unlink",   cmd_pathfunc,   "VFS unlink()",    "unlink <fname>" },
2301         { "chmod",   cmd_chmod,   "VFS chmod()",    "chmod <path> <mode>" },
2302         { "fchmod",   cmd_fchmod,   "VFS fchmod()",    "fchmod <fd> <mode>" },
2303         { "fchown",   cmd_fchown,   "VFS fchown()",    "fchown <fd> <uid> <gid>" },
2304         { "chdir",   cmd_pathfunc,   "VFS chdir()",    "chdir <path>" },
2305         { "getwd",   cmd_getwd,   "VFS getwd()",    "getwd" },
2306         { "utime",   cmd_utime,   "VFS utime()",    "utime <path> <access> <modify>" },
2307         { "ftruncate",   cmd_ftruncate,   "VFS ftruncate()",    "ftruncate <fd> <length>" },
2308         { "lock",   cmd_lock,   "VFS lock()",    "lock <f> <op> <offset> <count> <type>" },
2309         { "symlink",   cmd_symlink,   "VFS symlink()",    "symlink <old> <new>" },
2310         { "readlink",   cmd_readlink,   "VFS readlink()",    "readlink <path>" },
2311         { "link",   cmd_link,   "VFS link()",    "link <oldpath> <newpath>" },
2312         { "mknod",   cmd_mknod,   "VFS mknod()",    "mknod <path> <mode> <dev>" },
2313         { "realpath",   cmd_realpath,   "VFS realpath()",    "realpath <path>" },
2314         { "getxattr", cmd_getxattr, "VFS getxattr()",
2315           "getxattr <path> <name>" },
2316         { "listxattr", cmd_listxattr, "VFS listxattr()",
2317           "listxattr <path>" },
2318         { "fsetxattr", cmd_fsetxattr, "VFS fsetxattr()",
2319           "fsetxattr <path> <name> <value> [<flags>]" },
2320         { "removexattr", cmd_removexattr, "VFS removexattr()",
2321           "removexattr <path> <name>\n" },
2322         { "fget_nt_acl", cmd_fget_nt_acl, "VFS fget_nt_acl()", 
2323           "fget_nt_acl <fd>\n" },
2324         { "get_nt_acl", cmd_get_nt_acl, "VFS get_nt_acl()", 
2325           "get_nt_acl <path>\n" },
2326         { "fset_nt_acl", cmd_fset_nt_acl, "VFS fset_nt_acl()", 
2327           "fset_nt_acl <fd>\n" },
2328         { "set_nt_acl", cmd_set_nt_acl, "VFS open() and fset_nt_acl()", 
2329           "set_nt_acl <file>\n" },
2330         { "sys_acl_get_file", cmd_sys_acl_get_file, "VFS sys_acl_get_file()", "sys_acl_get_file <path>" },
2331         { "sys_acl_get_fd", cmd_sys_acl_get_fd, "VFS sys_acl_get_fd()", "sys_acl_get_fd <fd>" },
2332         { "sys_acl_blob_get_file", cmd_sys_acl_blob_get_file,
2333           "VFS sys_acl_blob_get_file()", "sys_acl_blob_get_file <path>" },
2334         { "sys_acl_blob_get_fd", cmd_sys_acl_blob_get_fd,
2335           "VFS sys_acl_blob_get_fd()", "sys_acl_blob_get_fd <path>" },
2336         { "sys_acl_delete_def_file", cmd_sys_acl_delete_def_file, "VFS sys_acl_delete_def_file()", "sys_acl_delete_def_file <path>" },
2337
2338
2339 #if defined(WITH_SMB1SERVER)
2340         { "test_chain", cmd_test_chain, "test chain code",
2341           "test_chain" },
2342 #endif
2343         { "translate_name", cmd_translate_name, "VFS translate_name()", "translate_name unix_filename" },
2344         { "create_file",
2345           cmd_create_file,
2346           "VFS create_file()",
2347           "create_file <filename>"
2348         },
2349         {0}
2350 };