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