LCOV - code coverage report
Current view: top level - source3/torture - cmd_vfs.c (source / functions) Hit Total Coverage
Test: coverage report for support-claim-type-attributes 6b5c566e Lines: 295 1273 23.2 %
Date: 2023-11-21 12:31:41 Functions: 13 49 26.5 %

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

Generated by: LCOV version 1.14