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