RIP BOOL. Convert BOOL -> bool. I found a few interesting
[tprouty/samba.git] / source3 / libsmb / clifile.c
index 93492ec08229654b38ca5502321e31689a61a3dd..27ad8364eeaefd2bfcfe37b68fea027e45e9cb6c 100644 (file)
@@ -6,7 +6,7 @@
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-#define NO_SYSLOG
-
 #include "includes.h"
 
 /****************************************************************************
@@ -28,7 +25,7 @@
  Creates new name (sym)linked to oldname.
 ****************************************************************************/
 
-static BOOL cli_link_internal(struct cli_state *cli, const char *oldname, const char *newname, BOOL hard_link)
+static bool cli_link_internal(struct cli_state *cli, const char *oldname, const char *newname, bool hard_link)
 {
        unsigned int data_len = 0;
        unsigned int param_len = 0;
@@ -171,7 +168,7 @@ static mode_t unix_filetype_from_wire(uint32 wire_type)
  Do a POSIX getfacl (UNIX extensions).
 ****************************************************************************/
 
-BOOL cli_unix_getfacl(struct cli_state *cli, const char *name, size_t *prb_size, char **retbuf)
+bool cli_unix_getfacl(struct cli_state *cli, const char *name, size_t *prb_size, char **retbuf)
 {
        unsigned int param_len = 0;
        unsigned int data_len = 0;
@@ -220,7 +217,7 @@ BOOL cli_unix_getfacl(struct cli_state *cli, const char *name, size_t *prb_size,
  Stat a file (UNIX extensions).
 ****************************************************************************/
 
-BOOL cli_unix_stat(struct cli_state *cli, const char *name, SMB_STRUCT_STAT *sbuf)
+bool cli_unix_stat(struct cli_state *cli, const char *name, SMB_STRUCT_STAT *sbuf)
 {
        unsigned int param_len = 0;
        unsigned int data_len = 0;
@@ -262,12 +259,18 @@ BOOL cli_unix_stat(struct cli_state *cli, const char *name, SMB_STRUCT_STAT *sbu
 
        sbuf->st_size = IVAL2_TO_SMB_BIG_UINT(rdata,0);     /* total size, in bytes */
        sbuf->st_blocks = IVAL2_TO_SMB_BIG_UINT(rdata,8);   /* number of blocks allocated */
+#if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
        sbuf->st_blocks /= STAT_ST_BLOCKSIZE;
-       sbuf->st_ctime = interpret_long_date(rdata + 16);    /* time of last change */
-       sbuf->st_atime = interpret_long_date(rdata + 24);    /* time of last access */
-       sbuf->st_mtime = interpret_long_date(rdata + 32);    /* time of last modification */
-       sbuf->st_uid = IVAL(rdata,40);      /* user ID of owner */
-       sbuf->st_gid = IVAL(rdata,48);      /* group ID of owner */
+#else
+       /* assume 512 byte blocks */
+       sbuf->st_blocks /= 512;
+#endif
+       set_ctimespec(sbuf, interpret_long_date(rdata + 16));    /* time of last change */
+       set_atimespec(sbuf, interpret_long_date(rdata + 24));    /* time of last access */
+       set_mtimespec(sbuf, interpret_long_date(rdata + 32));    /* time of last modification */
+
+       sbuf->st_uid = (uid_t) IVAL(rdata,40);      /* user ID of owner */
+       sbuf->st_gid = (gid_t) IVAL(rdata,48);      /* group ID of owner */
        sbuf->st_mode |= unix_filetype_from_wire(IVAL(rdata, 56));
 #if defined(HAVE_MAKEDEV)
        {
@@ -290,7 +293,7 @@ BOOL cli_unix_stat(struct cli_state *cli, const char *name, SMB_STRUCT_STAT *sbu
  Symlink a file (UNIX extensions).
 ****************************************************************************/
 
-BOOL cli_unix_symlink(struct cli_state *cli, const char *oldname, const char *newname)
+bool cli_unix_symlink(struct cli_state *cli, const char *oldname, const char *newname)
 {
        return cli_link_internal(cli, oldname, newname, False);
 }
@@ -299,7 +302,7 @@ BOOL cli_unix_symlink(struct cli_state *cli, const char *oldname, const char *ne
  Hard a file (UNIX extensions).
 ****************************************************************************/
 
-BOOL cli_unix_hardlink(struct cli_state *cli, const char *oldname, const char *newname)
+bool cli_unix_hardlink(struct cli_state *cli, const char *oldname, const char *newname)
 {
        return cli_link_internal(cli, oldname, newname, True);
 }
@@ -308,7 +311,7 @@ BOOL cli_unix_hardlink(struct cli_state *cli, const char *oldname, const char *n
  Chmod or chown a file internal (UNIX extensions).
 ****************************************************************************/
 
-static BOOL cli_unix_chmod_chown_internal(struct cli_state *cli, const char *fname, uint32 mode, uint32 uid, uint32 gid)
+static bool cli_unix_chmod_chown_internal(struct cli_state *cli, const char *fname, uint32 mode, uint32 uid, uint32 gid)
 {
        unsigned int data_len = 0;
        unsigned int param_len = 0;
@@ -326,6 +329,8 @@ static BOOL cli_unix_chmod_chown_internal(struct cli_state *cli, const char *fna
        p += clistr_push(cli, p, fname, -1, STR_TERMINATE);
        param_len = PTR_DIFF(p, param);
 
+       memset(data, 0xff, 40); /* Set all sizes/times to no change. */
+
        SIVAL(data,40,uid);
        SIVAL(data,48,gid);
        SIVAL(data,84,mode);
@@ -358,7 +363,7 @@ static BOOL cli_unix_chmod_chown_internal(struct cli_state *cli, const char *fna
  chmod a file (UNIX extensions).
 ****************************************************************************/
 
-BOOL cli_unix_chmod(struct cli_state *cli, const char *fname, mode_t mode)
+bool cli_unix_chmod(struct cli_state *cli, const char *fname, mode_t mode)
 {
        return cli_unix_chmod_chown_internal(cli, fname, 
                unix_perms_to_wire(mode), SMB_UID_NO_CHANGE, SMB_GID_NO_CHANGE);
@@ -368,7 +373,7 @@ BOOL cli_unix_chmod(struct cli_state *cli, const char *fname, mode_t mode)
  chown a file (UNIX extensions).
 ****************************************************************************/
 
-BOOL cli_unix_chown(struct cli_state *cli, const char *fname, uid_t uid, gid_t gid)
+bool cli_unix_chown(struct cli_state *cli, const char *fname, uid_t uid, gid_t gid)
 {
        return cli_unix_chmod_chown_internal(cli, fname, SMB_MODE_NO_CHANGE, (uint32)uid, (uint32)gid);
 }
@@ -377,7 +382,7 @@ BOOL cli_unix_chown(struct cli_state *cli, const char *fname, uid_t uid, gid_t g
  Rename a file.
 ****************************************************************************/
 
-BOOL cli_rename(struct cli_state *cli, const char *fname_src, const char *fname_dst)
+bool cli_rename(struct cli_state *cli, const char *fname_src, const char *fname_dst)
 {
        char *p;
 
@@ -414,7 +419,7 @@ BOOL cli_rename(struct cli_state *cli, const char *fname_src, const char *fname_
  NT Rename a file.
 ****************************************************************************/
 
-BOOL cli_ntrename(struct cli_state *cli, const char *fname_src, const char *fname_dst)
+bool cli_ntrename(struct cli_state *cli, const char *fname_src, const char *fname_dst)
 {
        char *p;
 
@@ -452,7 +457,7 @@ BOOL cli_ntrename(struct cli_state *cli, const char *fname_src, const char *fnam
  NT hardlink a file.
 ****************************************************************************/
 
-BOOL cli_nt_hardlink(struct cli_state *cli, const char *fname_src, const char *fname_dst)
+bool cli_nt_hardlink(struct cli_state *cli, const char *fname_src, const char *fname_dst)
 {
        char *p;
 
@@ -490,7 +495,7 @@ BOOL cli_nt_hardlink(struct cli_state *cli, const char *fname_src, const char *f
  Delete a file.
 ****************************************************************************/
 
-BOOL cli_unlink(struct cli_state *cli, const char *fname)
+bool cli_unlink_full(struct cli_state *cli, const char *fname, uint16 attrs)
 {
        char *p;
 
@@ -503,7 +508,7 @@ BOOL cli_unlink(struct cli_state *cli, const char *fname)
        SSVAL(cli->outbuf,smb_tid,cli->cnum);
        cli_setup_packet(cli);
 
-       SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
+       SSVAL(cli->outbuf,smb_vwv0, attrs);
   
        p = smb_buf(cli->outbuf);
        *p++ = 4;      
@@ -522,11 +527,20 @@ BOOL cli_unlink(struct cli_state *cli, const char *fname)
        return True;
 }
 
+/****************************************************************************
+ Delete a file.
+****************************************************************************/
+
+bool cli_unlink(struct cli_state *cli, const char *fname)
+{
+       return cli_unlink_full(cli, fname, aSYSTEM | aHIDDEN);
+}
+
 /****************************************************************************
  Create a directory.
 ****************************************************************************/
 
-BOOL cli_mkdir(struct cli_state *cli, const char *dname)
+bool cli_mkdir(struct cli_state *cli, const char *dname)
 {
        char *p;
 
@@ -561,7 +575,7 @@ BOOL cli_mkdir(struct cli_state *cli, const char *dname)
  Remove a directory.
 ****************************************************************************/
 
-BOOL cli_rmdir(struct cli_state *cli, const char *dname)
+bool cli_rmdir(struct cli_state *cli, const char *dname)
 {
        char *p;
 
@@ -596,7 +610,7 @@ BOOL cli_rmdir(struct cli_state *cli, const char *dname)
  Set or clear the delete on close flag.
 ****************************************************************************/
 
-int cli_nt_delete_on_close(struct cli_state *cli, int fnum, BOOL flag)
+int cli_nt_delete_on_close(struct cli_state *cli, int fnum, bool flag)
 {
        unsigned int data_len = 1;
        unsigned int param_len = 6;
@@ -700,7 +714,7 @@ int cli_nt_create_full(struct cli_state *cli, const char *fname,
 int cli_nt_create(struct cli_state *cli, const char *fname, uint32 DesiredAccess)
 {
        return cli_nt_create_full(cli, fname, 0, DesiredAccess, 0,
-                               FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_EXISTS_OPEN, 0x0, 0x0);
+                               FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0);
 }
 
 /****************************************************************************
@@ -786,7 +800,7 @@ int cli_open(struct cli_state *cli, const char *fname, int flags, int share_mode
  Close a file.
 ****************************************************************************/
 
-BOOL cli_close(struct cli_state *cli, int fnum)
+bool cli_close(struct cli_state *cli, int fnum)
 {
        memset(cli->outbuf,'\0',smb_size);
        memset(cli->inbuf,'\0',smb_size);
@@ -813,6 +827,7 @@ BOOL cli_close(struct cli_state *cli, int fnum)
  send a lock with a specified locktype 
  this is used for testing LOCKING_ANDX_CANCEL_LOCK
 ****************************************************************************/
+
 NTSTATUS cli_locktype(struct cli_state *cli, int fnum, 
                      uint32 offset, uint32 len, int timeout, unsigned char locktype)
 {
@@ -860,12 +875,12 @@ NTSTATUS cli_locktype(struct cli_state *cli, int fnum,
        return cli_nt_error(cli);
 }
 
-
 /****************************************************************************
  Lock a file.
  note that timeout is in units of 2 milliseconds
 ****************************************************************************/
-BOOL cli_lock(struct cli_state *cli, int fnum, 
+
+bool cli_lock(struct cli_state *cli, int fnum, 
              uint32 offset, uint32 len, int timeout, enum brl_type lock_type)
 {
        char *p;
@@ -920,7 +935,7 @@ BOOL cli_lock(struct cli_state *cli, int fnum,
  Unlock a file.
 ****************************************************************************/
 
-BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len)
+bool cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len)
 {
        char *p;
 
@@ -962,7 +977,7 @@ BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len)
  Lock a file with 64 bit offsets.
 ****************************************************************************/
 
-BOOL cli_lock64(struct cli_state *cli, int fnum, 
+bool cli_lock64(struct cli_state *cli, int fnum, 
                SMB_BIG_UINT offset, SMB_BIG_UINT len, int timeout, enum brl_type lock_type)
 {
        char *p;
@@ -1023,7 +1038,7 @@ BOOL cli_lock64(struct cli_state *cli, int fnum,
  Unlock a file with 64 bit offsets.
 ****************************************************************************/
 
-BOOL cli_unlock64(struct cli_state *cli, int fnum, SMB_BIG_UINT offset, SMB_BIG_UINT len)
+bool cli_unlock64(struct cli_state *cli, int fnum, SMB_BIG_UINT offset, SMB_BIG_UINT len)
 {
        char *p;
 
@@ -1065,14 +1080,118 @@ BOOL cli_unlock64(struct cli_state *cli, int fnum, SMB_BIG_UINT offset, SMB_BIG_
        return True;
 }
 
+/****************************************************************************
+ Get/unlock a POSIX lock on a file - internal function.
+****************************************************************************/
+
+static bool cli_posix_lock_internal(struct cli_state *cli, int fnum, 
+               SMB_BIG_UINT offset, SMB_BIG_UINT len, bool wait_lock, enum brl_type lock_type)
+{
+       unsigned int param_len = 4;
+       unsigned int data_len = POSIX_LOCK_DATA_SIZE;
+       uint16 setup = TRANSACT2_SETFILEINFO;
+       char param[4];
+       unsigned char data[POSIX_LOCK_DATA_SIZE];
+       char *rparam=NULL, *rdata=NULL;
+       int saved_timeout = cli->timeout;
+
+       SSVAL(param,0,fnum);
+       SSVAL(param,2,SMB_SET_POSIX_LOCK);
+
+       switch (lock_type) {
+               case READ_LOCK:
+                       SSVAL(data, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_READ);
+                       break;
+               case WRITE_LOCK:
+                       SSVAL(data, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_WRITE);
+                       break;
+               case UNLOCK_LOCK:
+                       SSVAL(data, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
+                       break;
+               default:
+                       return False;
+       }
+
+       if (wait_lock) {
+               SSVAL(data, POSIX_LOCK_FLAGS_OFFSET, POSIX_LOCK_FLAG_WAIT);
+               cli->timeout = 0x7FFFFFFF;
+       } else {
+               SSVAL(data, POSIX_LOCK_FLAGS_OFFSET, POSIX_LOCK_FLAG_NOWAIT);
+       }
+
+       SIVAL(data, POSIX_LOCK_PID_OFFSET, cli->pid);
+       SOFF_T(data, POSIX_LOCK_START_OFFSET, offset);
+       SOFF_T(data, POSIX_LOCK_LEN_OFFSET, len);
+
+       if (!cli_send_trans(cli, SMBtrans2,
+                               NULL,                        /* name */
+                               -1, 0,                          /* fid, flags */
+                               &setup, 1, 0,                   /* setup, length, max */
+                               param, param_len, 2,            /* param, length, max */
+                               (char *)&data,  data_len, cli->max_xmit /* data, length, max */
+                               )) {
+               cli->timeout = saved_timeout;
+               return False;
+       }
+
+       if (!cli_receive_trans(cli, SMBtrans2,
+                               &rparam, &param_len,
+                               &rdata, &data_len)) {
+               cli->timeout = saved_timeout;
+               SAFE_FREE(rdata);
+               SAFE_FREE(rparam);
+               return False;
+       }
+
+       cli->timeout = saved_timeout;
+
+       SAFE_FREE(rdata);
+       SAFE_FREE(rparam);
+
+       return True;
+}
+
+/****************************************************************************
+ POSIX Lock a file.
+****************************************************************************/
+
+bool cli_posix_lock(struct cli_state *cli, int fnum,
+                       SMB_BIG_UINT offset, SMB_BIG_UINT len,
+                       bool wait_lock, enum brl_type lock_type)
+{
+       if (lock_type != READ_LOCK && lock_type != WRITE_LOCK) {
+               return False;
+       }
+       return cli_posix_lock_internal(cli, fnum, offset, len, wait_lock, lock_type);
+}
+
+/****************************************************************************
+ POSIX Unlock a file.
+****************************************************************************/
+
+bool cli_posix_unlock(struct cli_state *cli, int fnum, SMB_BIG_UINT offset, SMB_BIG_UINT len)
+{
+       return cli_posix_lock_internal(cli, fnum, offset, len, False, UNLOCK_LOCK);
+}
+
+/****************************************************************************
+ POSIX Get any lock covering a file.
+****************************************************************************/
+
+bool cli_posix_getlock(struct cli_state *cli, int fnum, SMB_BIG_UINT *poffset, SMB_BIG_UINT *plen)
+{
+       return True;
+}
 
 /****************************************************************************
  Do a SMBgetattrE call.
 ****************************************************************************/
 
-BOOL cli_getattrE(struct cli_state *cli, int fd, 
+bool cli_getattrE(struct cli_state *cli, int fd, 
                  uint16 *attr, SMB_OFF_T *size, 
-                 time_t *c_time, time_t *a_time, time_t *m_time)
+                 time_t *change_time,
+                  time_t *access_time,
+                  time_t *write_time)
 {
        memset(cli->outbuf,'\0',smb_size);
        memset(cli->inbuf,'\0',smb_size);
@@ -1102,16 +1221,16 @@ BOOL cli_getattrE(struct cli_state *cli, int fd,
                *attr = SVAL(cli->inbuf,smb_vwv10);
        }
 
-       if (c_time) {
-               *c_time = make_unix_date3(cli->inbuf+smb_vwv0);
+       if (change_time) {
+               *change_time = cli_make_unix_date2(cli, cli->inbuf+smb_vwv0);
        }
 
-       if (a_time) {
-               *a_time = make_unix_date3(cli->inbuf+smb_vwv2);
+       if (access_time) {
+               *access_time = cli_make_unix_date2(cli, cli->inbuf+smb_vwv2);
        }
 
-       if (m_time) {
-               *m_time = make_unix_date3(cli->inbuf+smb_vwv4);
+       if (write_time) {
+               *write_time = cli_make_unix_date2(cli, cli->inbuf+smb_vwv4);
        }
 
        return True;
@@ -1121,8 +1240,8 @@ BOOL cli_getattrE(struct cli_state *cli, int fd,
  Do a SMBgetatr call
 ****************************************************************************/
 
-BOOL cli_getatr(struct cli_state *cli, const char *fname, 
-               uint16 *attr, SMB_OFF_T *size, time_t *t)
+bool cli_getatr(struct cli_state *cli, const char *fname, 
+               uint16 *attr, SMB_OFF_T *size, time_t *write_time)
 {
        char *p;
 
@@ -1154,8 +1273,8 @@ BOOL cli_getatr(struct cli_state *cli, const char *fname,
                *size = IVAL(cli->inbuf, smb_vwv3);
        }
 
-       if (t) {
-               *t = make_unix_date3(cli->inbuf+smb_vwv1);
+       if (write_time) {
+               *write_time = cli_make_unix_date3(cli, cli->inbuf+smb_vwv1);
        }
 
        if (attr) {
@@ -1170,8 +1289,10 @@ BOOL cli_getatr(struct cli_state *cli, const char *fname,
  Do a SMBsetattrE call.
 ****************************************************************************/
 
-BOOL cli_setattrE(struct cli_state *cli, int fd,
-                 time_t c_time, time_t a_time, time_t m_time)
+bool cli_setattrE(struct cli_state *cli, int fd,
+                 time_t change_time,
+                  time_t access_time,
+                  time_t write_time)
 
 {
        char *p;
@@ -1186,9 +1307,9 @@ BOOL cli_setattrE(struct cli_state *cli, int fd,
        cli_setup_packet(cli);
 
        SSVAL(cli->outbuf,smb_vwv0, fd);
-       put_dos_date3(cli->outbuf,smb_vwv1, c_time);
-       put_dos_date3(cli->outbuf,smb_vwv3, a_time);
-       put_dos_date3(cli->outbuf,smb_vwv5, m_time);
+       cli_put_dos_date2(cli, cli->outbuf,smb_vwv1, change_time);
+       cli_put_dos_date2(cli, cli->outbuf,smb_vwv3, access_time);
+       cli_put_dos_date2(cli, cli->outbuf,smb_vwv5, write_time);
 
        p = smb_buf(cli->outbuf);
        *p++ = 4;
@@ -1211,7 +1332,7 @@ BOOL cli_setattrE(struct cli_state *cli, int fd,
  Do a SMBsetatr call.
 ****************************************************************************/
 
-BOOL cli_setatr(struct cli_state *cli, const char *fname, uint16 attr, time_t t)
+bool cli_setatr(struct cli_state *cli, const char *fname, uint16 attr, time_t t)
 {
        char *p;
 
@@ -1225,7 +1346,7 @@ BOOL cli_setatr(struct cli_state *cli, const char *fname, uint16 attr, time_t t)
        cli_setup_packet(cli);
 
        SSVAL(cli->outbuf,smb_vwv0, attr);
-       put_dos_date3(cli->outbuf,smb_vwv1, t);
+       cli_put_dos_date3(cli, cli->outbuf,smb_vwv1, t);
 
        p = smb_buf(cli->outbuf);
        *p++ = 4;
@@ -1249,7 +1370,7 @@ BOOL cli_setatr(struct cli_state *cli, const char *fname, uint16 attr, time_t t)
 /****************************************************************************
  Check for existance of a dir.
 ****************************************************************************/
-BOOL cli_chkpath(struct cli_state *cli, const char *path)
+bool cli_chkpath(struct cli_state *cli, const char *path)
 {
        pstring path2;
        char *p;
@@ -1261,7 +1382,7 @@ BOOL cli_chkpath(struct cli_state *cli, const char *path)
        
        memset(cli->outbuf,'\0',smb_size);
        set_message(cli->outbuf,0,0,True);
-       SCVAL(cli->outbuf,smb_com,SMBchkpth);
+       SCVAL(cli->outbuf,smb_com,SMBcheckpath);
        SSVAL(cli->outbuf,smb_tid,cli->cnum);
        cli_setup_packet(cli);
        p = smb_buf(cli->outbuf);
@@ -1284,7 +1405,7 @@ BOOL cli_chkpath(struct cli_state *cli, const char *path)
  Query disk space.
 ****************************************************************************/
 
-BOOL cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail)
+bool cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail)
 {
        memset(cli->outbuf,'\0',smb_size);
        set_message(cli->outbuf,0,0,True);
@@ -1383,7 +1504,7 @@ NTSTATUS cli_raw_ioctl(struct cli_state *cli, int fnum, uint32 code, DATA_BLOB *
                return cli_nt_error(cli);
        }
 
-       *blob = data_blob(NULL, 0);
+       *blob = data_blob_null;
 
        return NT_STATUS_OK;
 }
@@ -1392,7 +1513,7 @@ NTSTATUS cli_raw_ioctl(struct cli_state *cli, int fnum, uint32 code, DATA_BLOB *
  Set an extended attribute utility fn.
 *********************************************************/
 
-static BOOL cli_set_ea(struct cli_state *cli, uint16 setup, char *param, unsigned int param_len,
+static bool cli_set_ea(struct cli_state *cli, uint16 setup, char *param, unsigned int param_len,
                        const char *ea_name, const char *ea_val, size_t ea_len)
 {      
        unsigned int data_len = 0;
@@ -1401,19 +1522,29 @@ static BOOL cli_set_ea(struct cli_state *cli, uint16 setup, char *param, unsigne
        char *p;
        size_t ea_namelen = strlen(ea_name);
 
-       data_len = 4 + 4 + ea_namelen + 1 + ea_len;
-       data = SMB_MALLOC(data_len);
-       if (!data) {
-               return False;
+       if (ea_namelen == 0 && ea_len == 0) {
+               data_len = 4;
+               data = (char *)SMB_MALLOC(data_len);
+               if (!data) {
+                       return False;
+               }
+               p = data;
+               SIVAL(p,0,data_len);
+       } else {
+               data_len = 4 + 4 + ea_namelen + 1 + ea_len;
+               data = (char *)SMB_MALLOC(data_len);
+               if (!data) {
+                       return False;
+               }
+               p = data;
+               SIVAL(p,0,data_len);
+               p += 4;
+               SCVAL(p, 0, 0); /* EA flags. */
+               SCVAL(p, 1, ea_namelen);
+               SSVAL(p, 2, ea_len);
+               memcpy(p+4, ea_name, ea_namelen+1); /* Copy in the name. */
+               memcpy(p+4+ea_namelen+1, ea_val, ea_len);
        }
-       p = data;
-       SIVAL(p,0,data_len);
-       p += 4;
-       SCVAL(p, 0, 0); /* EA flags. */
-       SCVAL(p, 1, ea_namelen);
-       SSVAL(p, 2, ea_len);
-       memcpy(p+4, ea_name, ea_namelen+1); /* Copy in the name. */
-       memcpy(p+4+ea_namelen+1, ea_val, ea_len);
 
        if (!cli_send_trans(cli, SMBtrans2,
                NULL,                        /* name */
@@ -1442,7 +1573,7 @@ static BOOL cli_set_ea(struct cli_state *cli, uint16 setup, char *param, unsigne
  Set an extended attribute on a pathname.
 *********************************************************/
 
-BOOL cli_set_ea_path(struct cli_state *cli, const char *path, const char *ea_name, const char *ea_val, size_t ea_len)
+bool cli_set_ea_path(struct cli_state *cli, const char *path, const char *ea_name, const char *ea_val, size_t ea_len)
 {
        uint16 setup = TRANSACT2_SETPATHINFO;
        unsigned int param_len = 0;
@@ -1464,7 +1595,7 @@ BOOL cli_set_ea_path(struct cli_state *cli, const char *path, const char *ea_nam
  Set an extended attribute on an fnum.
 *********************************************************/
 
-BOOL cli_set_ea_fnum(struct cli_state *cli, int fnum, const char *ea_name, const char *ea_val, size_t ea_len)
+bool cli_set_ea_fnum(struct cli_state *cli, int fnum, const char *ea_name, const char *ea_val, size_t ea_len)
 {
        char param[6];
        uint16 setup = TRANSACT2_SETFILEINFO;
@@ -1480,7 +1611,7 @@ BOOL cli_set_ea_fnum(struct cli_state *cli, int fnum, const char *ea_name, const
  Get an extended attribute list tility fn.
 *********************************************************/
 
-static BOOL cli_get_ea_list(struct cli_state *cli,
+static bool cli_get_ea_list(struct cli_state *cli,
                uint16 setup, char *param, unsigned int param_len,
                TALLOC_CTX *ctx,
                size_t *pnum_eas,
@@ -1492,11 +1623,13 @@ static BOOL cli_get_ea_list(struct cli_state *cli,
        char *p;
        size_t ea_size;
        size_t num_eas;
-       BOOL ret = False;
+       bool ret = False;
        struct ea_struct *ea_list;
 
        *pnum_eas = 0;
-       *pea_list = NULL;
+       if (pea_list) {
+               *pea_list = NULL;
+       }
 
        if (!cli_send_trans(cli, SMBtrans2,
                        NULL,           /* Name */
@@ -1603,7 +1736,7 @@ static BOOL cli_get_ea_list(struct cli_state *cli,
  Get an extended attribute list from a pathname.
 *********************************************************/
 
-BOOL cli_get_ea_list_path(struct cli_state *cli, const char *path,
+bool cli_get_ea_list_path(struct cli_state *cli, const char *path,
                TALLOC_CTX *ctx,
                size_t *pnum_eas,
                struct ea_struct **pea_list)
@@ -1627,7 +1760,7 @@ BOOL cli_get_ea_list_path(struct cli_state *cli, const char *path,
  Get an extended attribute list from an fnum.
 *********************************************************/
 
-BOOL cli_get_ea_list_fnum(struct cli_state *cli, int fnum,
+bool cli_get_ea_list_fnum(struct cli_state *cli, int fnum,
                TALLOC_CTX *ctx,
                size_t *pnum_eas,
                struct ea_struct **pea_list)
@@ -1641,3 +1774,200 @@ BOOL cli_get_ea_list_fnum(struct cli_state *cli, int fnum,
 
        return cli_get_ea_list(cli, setup, param, 6, ctx, pnum_eas, pea_list);
 }
+
+/****************************************************************************
+ Convert open "flags" arg to uint32 on wire.
+****************************************************************************/
+
+static uint32 open_flags_to_wire(int flags)
+{
+       int open_mode = flags & O_ACCMODE;
+       uint32 ret = 0;
+
+       switch (open_mode) {
+               case O_WRONLY:
+                       ret |= SMB_O_WRONLY;
+                       break;
+               case O_RDWR:
+                       ret |= SMB_O_RDWR;
+                       break;
+               default:
+               case O_RDONLY:
+                       ret |= SMB_O_RDONLY;
+                       break;
+       }
+
+       if (flags & O_CREAT) {
+               ret |= SMB_O_CREAT;
+       }
+       if (flags & O_EXCL) {
+               ret |= SMB_O_EXCL;
+       }
+       if (flags & O_TRUNC) {
+               ret |= SMB_O_TRUNC;
+       }
+#if defined(O_SYNC)
+       if (flags & O_SYNC) {
+               ret |= SMB_O_SYNC;
+       }
+#endif /* O_SYNC */
+       if (flags & O_APPEND) {
+               ret |= SMB_O_APPEND;
+       }
+#if defined(O_DIRECT)
+       if (flags & O_DIRECT) {
+               ret |= SMB_O_DIRECT;
+       }
+#endif
+#if defined(O_DIRECTORY)
+       if (flags & O_DIRECTORY) {
+               ret &= ~(SMB_O_RDONLY|SMB_O_RDWR|SMB_O_WRONLY);
+               ret |= SMB_O_DIRECTORY;
+       }
+#endif
+       return ret;
+}
+
+/****************************************************************************
+ Open a file - POSIX semantics. Returns fnum. Doesn't request oplock.
+****************************************************************************/
+
+static int cli_posix_open_internal(struct cli_state *cli, const char *fname, int flags, mode_t mode, bool is_dir)
+{
+       unsigned int data_len = 0;
+       unsigned int param_len = 0;
+       uint16 setup = TRANSACT2_SETPATHINFO;
+       char param[sizeof(pstring)+6];
+       char data[18];
+       char *rparam=NULL, *rdata=NULL;
+       char *p;
+       int fnum = -1;
+       uint32 wire_flags = open_flags_to_wire(flags);
+
+       memset(param, 0, sizeof(param));
+       SSVAL(param,0, SMB_POSIX_PATH_OPEN);
+       p = &param[6];
+
+       p += clistr_push(cli, p, fname, sizeof(param)-6, STR_TERMINATE);
+       param_len = PTR_DIFF(p, param);
+
+       if (is_dir) {
+               wire_flags &= ~(SMB_O_RDONLY|SMB_O_RDWR|SMB_O_WRONLY);
+               wire_flags |= SMB_O_DIRECTORY;
+       }
+
+       p = data;
+       SIVAL(p,0,0); /* No oplock. */
+       SIVAL(p,4,wire_flags);
+       SIVAL(p,8,unix_perms_to_wire(mode));
+       SIVAL(p,12,0); /* Top bits of perms currently undefined. */
+       SSVAL(p,16,SMB_NO_INFO_LEVEL_RETURNED); /* No info level returned. */
+
+       data_len = 18;
+
+       if (!cli_send_trans(cli, SMBtrans2,
+               NULL,                        /* name */
+               -1, 0,                          /* fid, flags */
+               &setup, 1, 0,                   /* setup, length, max */
+               param, param_len, 2,            /* param, length, max */
+               (char *)&data,  data_len, cli->max_xmit /* data, length, max */
+               )) {
+                       return -1;
+       }
+
+       if (!cli_receive_trans(cli, SMBtrans2,
+               &rparam, &param_len,
+               &rdata, &data_len)) {
+                       return -1;
+       }
+
+       fnum = SVAL(rdata,2);
+
+       SAFE_FREE(rdata);
+       SAFE_FREE(rparam);
+
+       return fnum;
+}
+
+/****************************************************************************
+ open - POSIX semantics.
+****************************************************************************/
+
+int cli_posix_open(struct cli_state *cli, const char *fname, int flags, mode_t mode)
+{
+       return cli_posix_open_internal(cli, fname, flags, mode, False);
+}
+
+/****************************************************************************
+ mkdir - POSIX semantics.
+****************************************************************************/
+
+int cli_posix_mkdir(struct cli_state *cli, const char *fname, mode_t mode)
+{
+       return (cli_posix_open_internal(cli, fname, O_CREAT, mode, True) == -1) ? -1 : 0;
+}
+
+/****************************************************************************
+ unlink or rmdir - POSIX semantics.
+****************************************************************************/
+
+static bool cli_posix_unlink_internal(struct cli_state *cli, const char *fname, bool is_dir)
+{
+       unsigned int data_len = 0;
+       unsigned int param_len = 0;
+       uint16 setup = TRANSACT2_SETPATHINFO;
+       char param[sizeof(pstring)+6];
+       char data[2];
+       char *rparam=NULL, *rdata=NULL;
+       char *p;
+
+       memset(param, 0, sizeof(param));
+       SSVAL(param,0, SMB_POSIX_PATH_UNLINK);
+       p = &param[6];
+
+       p += clistr_push(cli, p, fname, sizeof(param)-6, STR_TERMINATE);
+       param_len = PTR_DIFF(p, param);
+
+       SSVAL(data, 0, is_dir ? SMB_POSIX_UNLINK_DIRECTORY_TARGET :
+                       SMB_POSIX_UNLINK_FILE_TARGET);
+       data_len = 2;
+
+       if (!cli_send_trans(cli, SMBtrans2,
+               NULL,                        /* name */
+               -1, 0,                          /* fid, flags */
+               &setup, 1, 0,                   /* setup, length, max */
+               param, param_len, 2,            /* param, length, max */
+               (char *)&data,  data_len, cli->max_xmit /* data, length, max */
+               )) {
+                       return False;
+       }
+
+       if (!cli_receive_trans(cli, SMBtrans2,
+               &rparam, &param_len,
+               &rdata, &data_len)) {
+                       return False;
+       }
+
+       SAFE_FREE(rdata);
+       SAFE_FREE(rparam);
+
+       return True;
+}
+
+/****************************************************************************
+ unlink - POSIX semantics.
+****************************************************************************/
+
+bool cli_posix_unlink(struct cli_state *cli, const char *fname)
+{
+       return cli_posix_unlink_internal(cli, fname, False);
+}
+
+/****************************************************************************
+ rmdir - POSIX semantics.
+****************************************************************************/
+
+int cli_posix_rmdir(struct cli_state *cli, const char *fname)
+{
+       return cli_posix_unlink_internal(cli, fname, True);
+}