r15018: Merge Volker's ipc/trans2/nttrans changes over
[samba.git] / source3 / libsmb / clifile.c
index ff0edc6bb4e40c1dcee02cddcdf197b53f773105..80deb3a3320b1211c06195d783c12c6b8cdf1746 100644 (file)
@@ -19,8 +19,6 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#define NO_SYSLOG
-
 #include "includes.h"
 
 /****************************************************************************
@@ -77,7 +75,7 @@ static BOOL cli_link_internal(struct cli_state *cli, const char *oldname, const
  Map standard UNIX permissions onto wire representations.
 ****************************************************************************/
 
-uint32  unix_perms_to_wire(mode_t perms)
+uint32 unix_perms_to_wire(mode_t perms)
 {
         unsigned int ret = 0;
 
@@ -102,6 +100,195 @@ uint32  unix_perms_to_wire(mode_t perms)
         return ret;
 }
 
+/****************************************************************************
+ Map wire permissions to standard UNIX.
+****************************************************************************/
+
+mode_t wire_perms_to_unix(uint32 perms)
+{
+        mode_t ret = (mode_t)0;
+
+        ret |= ((perms & UNIX_X_OTH) ? S_IXOTH : 0);
+        ret |= ((perms & UNIX_W_OTH) ? S_IWOTH : 0);
+        ret |= ((perms & UNIX_R_OTH) ? S_IROTH : 0);
+        ret |= ((perms & UNIX_X_GRP) ? S_IXGRP : 0);
+        ret |= ((perms & UNIX_W_GRP) ? S_IWGRP : 0);
+        ret |= ((perms & UNIX_R_GRP) ? S_IRGRP : 0);
+        ret |= ((perms & UNIX_X_USR) ? S_IXUSR : 0);
+        ret |= ((perms & UNIX_W_USR) ? S_IWUSR : 0);
+        ret |= ((perms & UNIX_R_USR) ? S_IRUSR : 0);
+#ifdef S_ISVTX
+        ret |= ((perms & UNIX_STICKY) ? S_ISVTX : 0);
+#endif
+#ifdef S_ISGID
+        ret |= ((perms & UNIX_SET_GID) ? S_ISGID : 0);
+#endif
+#ifdef S_ISUID
+        ret |= ((perms & UNIX_SET_UID) ? S_ISUID : 0);
+#endif
+        return ret;
+}
+
+/****************************************************************************
+ Return the file type from the wire filetype for UNIX extensions.
+****************************************************************************/
+                                                                                                                
+static mode_t unix_filetype_from_wire(uint32 wire_type)
+{
+       switch (wire_type) {
+               case UNIX_TYPE_FILE:
+                       return S_IFREG;
+               case UNIX_TYPE_DIR:
+                       return S_IFDIR;
+#ifdef S_IFLNK
+               case UNIX_TYPE_SYMLINK:
+                       return S_IFLNK;
+#endif
+#ifdef S_IFCHR
+               case UNIX_TYPE_CHARDEV:
+                       return S_IFCHR;
+#endif
+#ifdef S_IFBLK
+               case UNIX_TYPE_BLKDEV:
+                       return S_IFBLK;
+#endif
+#ifdef S_IFIFO
+               case UNIX_TYPE_FIFO:
+                       return S_IFIFO;
+#endif
+#ifdef S_IFSOCK
+               case UNIX_TYPE_SOCKET:
+                       return S_IFSOCK;
+#endif
+               default:
+                       return (mode_t)0;
+       }
+}
+
+/****************************************************************************
+ Do a POSIX getfacl (UNIX extensions).
+****************************************************************************/
+
+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;
+       uint16 setup = TRANSACT2_QPATHINFO;
+       char param[sizeof(pstring)+6];
+       char *rparam=NULL, *rdata=NULL;
+       char *p;
+
+       p = param;
+       memset(p, 0, 6);
+       SSVAL(p, 0, SMB_QUERY_POSIX_ACL);
+       p += 6;
+       p += clistr_push(cli, p, name, sizeof(pstring)-6, STR_TERMINATE);
+       param_len = PTR_DIFF(p, param);
+
+       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 */
+               NULL,  0, cli->max_xmit      /* data, length, max */
+               )) {
+                       return False;
+       }
+
+       if (!cli_receive_trans(cli, SMBtrans2,
+               &rparam, &param_len,
+               &rdata, &data_len)) {
+                       return False;
+       }
+
+       if (data_len < 6) {
+               SAFE_FREE(rdata);
+               SAFE_FREE(rparam);
+               return False;
+       }
+
+       SAFE_FREE(rparam);
+       *retbuf = rdata;
+       *prb_size = (size_t)data_len;
+
+       return True;
+}
+
+/****************************************************************************
+ Stat a file (UNIX extensions).
+****************************************************************************/
+
+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;
+       uint16 setup = TRANSACT2_QPATHINFO;
+       char param[sizeof(pstring)+6];
+       char *rparam=NULL, *rdata=NULL;
+       char *p;
+
+       ZERO_STRUCTP(sbuf);
+
+       p = param;
+       memset(p, 0, 6);
+       SSVAL(p, 0, SMB_QUERY_FILE_UNIX_BASIC);
+       p += 6;
+       p += clistr_push(cli, p, name, sizeof(pstring)-6, STR_TERMINATE);
+       param_len = PTR_DIFF(p, param);
+
+       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 */
+               NULL,  0, cli->max_xmit      /* data, length, max */
+               )) {
+                       return False;
+       }
+
+       if (!cli_receive_trans(cli, SMBtrans2,
+               &rparam, &param_len,
+               &rdata, &data_len)) {
+                       return False;
+       }
+
+       if (data_len < 96) {
+               SAFE_FREE(rdata);
+               SAFE_FREE(rparam);
+               return False;
+       }
+
+       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;
+#else
+       /* assume 512 byte blocks */
+       sbuf->st_blocks /= 512;
+#endif
+       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 = (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)
+       {
+               uint32 dev_major = IVAL(rdata,60);
+               uint32 dev_minor = IVAL(rdata,68);
+               sbuf->st_rdev = makedev(dev_major, dev_minor);
+       }
+#endif
+       sbuf->st_ino = (SMB_INO_T)IVAL2_TO_SMB_BIG_UINT(rdata,76);      /* inode */
+       sbuf->st_mode |= wire_perms_to_unix(IVAL(rdata,84));     /* protection */
+       sbuf->st_nlink = IVAL(rdata,92);    /* number of hard links */
+
+       SAFE_FREE(rdata);
+       SAFE_FREE(rparam);
+
+       return True;
+}
+
 /****************************************************************************
  Symlink a file (UNIX extensions).
 ****************************************************************************/
@@ -516,7 +703,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);
 }
 
 /****************************************************************************
@@ -629,6 +816,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)
 {
@@ -676,11 +864,11 @@ 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, 
              uint32 offset, uint32 len, int timeout, enum brl_type lock_type)
 {
@@ -881,13 +1069,115 @@ 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, 
-                 uint16 *attr, SMB_BIG_UINT *size, 
+                 uint16 *attr, SMB_OFF_T *size, 
                  time_t *c_time, time_t *a_time, time_t *m_time)
 {
        memset(cli->outbuf,'\0',smb_size);
@@ -919,15 +1209,15 @@ BOOL cli_getattrE(struct cli_state *cli, int fd,
        }
 
        if (c_time) {
-               *c_time = make_unix_date3(cli->inbuf+smb_vwv0);
+               *c_time = cli_make_unix_date2(cli, cli->inbuf+smb_vwv0);
        }
 
        if (a_time) {
-               *a_time = make_unix_date3(cli->inbuf+smb_vwv2);
+               *a_time = cli_make_unix_date2(cli, cli->inbuf+smb_vwv2);
        }
 
        if (m_time) {
-               *m_time = make_unix_date3(cli->inbuf+smb_vwv4);
+               *m_time = cli_make_unix_date2(cli, cli->inbuf+smb_vwv4);
        }
 
        return True;
@@ -938,7 +1228,7 @@ BOOL cli_getattrE(struct cli_state *cli, int fd,
 ****************************************************************************/
 
 BOOL cli_getatr(struct cli_state *cli, const char *fname, 
-               uint16 *attr, size_t *size, time_t *t)
+               uint16 *attr, SMB_OFF_T *size, time_t *t)
 {
        char *p;
 
@@ -971,7 +1261,7 @@ BOOL cli_getatr(struct cli_state *cli, const char *fname,
        }
 
        if (t) {
-               *t = make_unix_date3(cli->inbuf+smb_vwv1);
+               *t = cli_make_unix_date3(cli, cli->inbuf+smb_vwv1);
        }
 
        if (attr) {
@@ -1002,9 +1292,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, c_time);
+       cli_put_dos_date2(cli, cli->outbuf,smb_vwv3, a_time);
+       cli_put_dos_date2(cli, cli->outbuf,smb_vwv5, m_time);
 
        p = smb_buf(cli->outbuf);
        *p++ = 4;
@@ -1041,7 +1331,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;
@@ -1167,7 +1457,7 @@ int cli_ctemp(struct cli_state *cli, const char *path, char **tmp_path)
                pstring path2;
                clistr_pull(cli, path2, p, 
                            sizeof(path2), len, STR_ASCII);
-               *tmp_path = strdup(path2);
+               *tmp_path = SMB_STRDUP(path2);
        }
 
        return SVAL(cli->inbuf,smb_vwv0);
@@ -1217,19 +1507,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 = malloc(data_len);
-       if (!data) {
-               return False;
+       if (ea_namelen == 0 && ea_len == 0) {
+               data_len = 4;
+               data = 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 = 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 */
@@ -1374,7 +1674,7 @@ static BOOL cli_get_ea_list(struct cli_state *cli,
                goto out;
        }
 
-       ea_list = (struct ea_struct *)talloc(ctx, num_eas*sizeof(struct ea_struct));
+       ea_list = TALLOC_ARRAY(ctx, struct ea_struct, num_eas);
        if (!ea_list) {
                goto out;
        }