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