Removed version number from file header.
[samba.git] / source / libsmb / clifile.c
index 5c3725527845b7cab02f02208e653b9d439e9938..71b3f44b0dac737117d9c62ef2575800bda13b99 100644 (file)
@@ -1,8 +1,8 @@
 /* 
-   Unix SMB/Netbios implementation.
-   Version 3.0
+   Unix SMB/CIFS implementation.
    client file operations
    Copyright (C) Andrew Tridgell 1994-1998
+   Copyright (C) Jeremy Allison 2001-2002
    
    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
 
 #include "includes.h"
 
+/****************************************************************************
+ Hard/Symlink a file (UNIX extensions).
+****************************************************************************/
+
+static BOOL cli_link_internal(struct cli_state *cli, const char *fname_src, const char *fname_dst, BOOL hard_link)
+{
+       int data_len = 0;
+       int param_len = 0;
+       uint16 setup = TRANSACT2_SETPATHINFO;
+       char param[sizeof(pstring)+6];
+       pstring data;
+       char *rparam=NULL, *rdata=NULL;
+       char *p;
+
+       memset(param, 0, sizeof(param));
+       SSVAL(param,0,hard_link ? SMB_SET_FILE_UNIX_HLINK : SMB_SET_FILE_UNIX_LINK);
+       p = &param[6];
+
+       p += clistr_push(cli, p, fname_src, -1, STR_TERMINATE);
+       param_len = PTR_DIFF(p, param);
+
+       p = data;
+       p += clistr_push(cli, p, fname_dst, -1, STR_TERMINATE);
+       data_len = PTR_DIFF(p, data);
+
+       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;
+}
+
+/****************************************************************************
+ Map standard UNIX permissions onto wire representations.
+****************************************************************************/
+
+uint32  unix_perms_to_wire(mode_t perms)
+{
+        uint ret = 0;
+
+        ret |= ((perms & S_IXOTH) ?  UNIX_X_OTH : 0);
+        ret |= ((perms & S_IWOTH) ?  UNIX_W_OTH : 0);
+        ret |= ((perms & S_IROTH) ?  UNIX_R_OTH : 0);
+        ret |= ((perms & S_IXGRP) ?  UNIX_X_GRP : 0);
+        ret |= ((perms & S_IWGRP) ?  UNIX_W_GRP : 0);
+        ret |= ((perms & S_IRGRP) ?  UNIX_R_GRP : 0);
+        ret |= ((perms & S_IXUSR) ?  UNIX_X_USR : 0);
+        ret |= ((perms & S_IWUSR) ?  UNIX_W_USR : 0);
+        ret |= ((perms & S_IRUSR) ?  UNIX_R_USR : 0);
+#ifdef S_ISVTX
+        ret |= ((perms & S_ISVTX) ?  UNIX_STICKY : 0);
+#endif
+#ifdef S_ISGID
+        ret |= ((perms & S_ISGID) ?  UNIX_SET_GID : 0);
+#endif
+#ifdef S_ISUID
+        ret |= ((perms & S_ISVTX) ?  UNIX_SET_UID : 0);
+#endif
+        return ret;
+}
+
+/****************************************************************************
+ Symlink a file (UNIX extensions).
+****************************************************************************/
+
+BOOL cli_unix_symlink(struct cli_state *cli, const char *fname_src, const char *fname_dst)
+{
+       return cli_link_internal(cli, fname_src, fname_dst, False);
+}
+
+/****************************************************************************
+ Hard a file (UNIX extensions).
+****************************************************************************/
+
+BOOL cli_unix_hardlink(struct cli_state *cli, const char *fname_src, const char *fname_dst)
+{
+       return cli_link_internal(cli, fname_src, fname_dst, True);
+}
+
+/****************************************************************************
+ 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)
+{
+       int data_len = 0;
+       int param_len = 0;
+       uint16 setup = TRANSACT2_SETPATHINFO;
+       char param[sizeof(pstring)+6];
+       char data[100];
+       char *rparam=NULL, *rdata=NULL;
+       char *p;
+
+       memset(param, 0, sizeof(param));
+       memset(data, 0, sizeof(data));
+       SSVAL(param,0,SMB_SET_FILE_UNIX_BASIC);
+       p = &param[6];
+
+       p += clistr_push(cli, p, fname, -1, STR_TERMINATE);
+       param_len = PTR_DIFF(p, param);
+
+       SIVAL(data,40,uid);
+       SIVAL(data,48,gid);
+       SIVAL(data,84,mode);
+
+       data_len = 100;
+
+       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;
+}
+
+/****************************************************************************
+ chmod a file (UNIX extensions).
+****************************************************************************/
+
+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);
+}
+
+/****************************************************************************
+ chown a file (UNIX extensions).
+****************************************************************************/
+
+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);
+}
+
 /****************************************************************************
  Rename a file.
 ****************************************************************************/
@@ -36,7 +199,7 @@ BOOL cli_rename(struct cli_state *cli, const char *fname_src, const char *fname_
 
        set_message(cli->outbuf,1, 0, True);
 
-       CVAL(cli->outbuf,smb_com) = SMBmv;
+       SCVAL(cli->outbuf,smb_com,SMBmv);
        SSVAL(cli->outbuf,smb_tid,cli->cnum);
        cli_setup_packet(cli);
 
@@ -73,7 +236,7 @@ BOOL cli_unlink(struct cli_state *cli, const char *fname)
 
        set_message(cli->outbuf,1, 0,True);
 
-       CVAL(cli->outbuf,smb_com) = SMBunlink;
+       SCVAL(cli->outbuf,smb_com,SMBunlink);
        SSVAL(cli->outbuf,smb_tid,cli->cnum);
        cli_setup_packet(cli);
 
@@ -109,7 +272,7 @@ BOOL cli_mkdir(struct cli_state *cli, const char *dname)
 
        set_message(cli->outbuf,0, 0,True);
 
-       CVAL(cli->outbuf,smb_com) = SMBmkdir;
+       SCVAL(cli->outbuf,smb_com,SMBmkdir);
        SSVAL(cli->outbuf,smb_tid,cli->cnum);
        cli_setup_packet(cli);
 
@@ -144,7 +307,7 @@ BOOL cli_rmdir(struct cli_state *cli, const char *dname)
 
        set_message(cli->outbuf,0, 0, True);
 
-       CVAL(cli->outbuf,smb_com) = SMBrmdir;
+       SCVAL(cli->outbuf,smb_com,SMBrmdir);
        SSVAL(cli->outbuf,smb_tid,cli->cnum);
        cli_setup_packet(cli);
 
@@ -224,7 +387,7 @@ int cli_nt_create_full(struct cli_state *cli, const char *fname, uint32 DesiredA
 
        set_message(cli->outbuf,24,0,True);
 
-       CVAL(cli->outbuf,smb_com) = SMBntcreateX;
+       SCVAL(cli->outbuf,smb_com,SMBntcreateX);
        SSVAL(cli->outbuf,smb_tid,cli->cnum);
        cli_setup_packet(cli);
 
@@ -317,7 +480,7 @@ int cli_open(struct cli_state *cli, const char *fname, int flags, int share_mode
 
        set_message(cli->outbuf,15,0,True);
 
-       CVAL(cli->outbuf,smb_com) = SMBopenX;
+       SCVAL(cli->outbuf,smb_com,SMBopenX);
        SSVAL(cli->outbuf,smb_tid,cli->cnum);
        cli_setup_packet(cli);
 
@@ -331,8 +494,8 @@ int cli_open(struct cli_state *cli, const char *fname, int flags, int share_mode
        if (cli->use_oplocks) {
                /* if using oplocks then ask for a batch oplock via
                    core and extended methods */
-               CVAL(cli->outbuf,smb_flg) |= 
-                       FLAG_REQUEST_OPLOCK|FLAG_REQUEST_BATCH_OPLOCK;
+               SCVAL(cli->outbuf,smb_flg, CVAL(cli->outbuf,smb_flg)|
+                       FLAG_REQUEST_OPLOCK|FLAG_REQUEST_BATCH_OPLOCK);
                SSVAL(cli->outbuf,smb_vwv2,SVAL(cli->outbuf,smb_vwv2) | 6);
        }
   
@@ -364,7 +527,7 @@ BOOL cli_close(struct cli_state *cli, int fnum)
 
        set_message(cli->outbuf,3,0,True);
 
-       CVAL(cli->outbuf,smb_com) = SMBclose;
+       SCVAL(cli->outbuf,smb_com,SMBclose);
        SSVAL(cli->outbuf,smb_tid,cli->cnum);
        cli_setup_packet(cli);
 
@@ -394,13 +557,13 @@ BOOL cli_lock(struct cli_state *cli, int fnum,
 
        set_message(cli->outbuf,8,0,True);
 
-       CVAL(cli->outbuf,smb_com) = SMBlockingX;
+       SCVAL(cli->outbuf,smb_com,SMBlockingX);
        SSVAL(cli->outbuf,smb_tid,cli->cnum);
        cli_setup_packet(cli);
 
-       CVAL(cli->outbuf,smb_vwv0) = 0xFF;
+       SCVAL(cli->outbuf,smb_vwv0,0xFF);
        SSVAL(cli->outbuf,smb_vwv2,fnum);
-       CVAL(cli->outbuf,smb_vwv3) = (lock_type == READ_LOCK? 1 : 0);
+       SCVAL(cli->outbuf,smb_vwv3,(lock_type == READ_LOCK? 1 : 0));
        SIVALS(cli->outbuf, smb_vwv4, timeout);
        SSVAL(cli->outbuf,smb_vwv6,0);
        SSVAL(cli->outbuf,smb_vwv7,1);
@@ -445,13 +608,13 @@ BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len)
 
        set_message(cli->outbuf,8,0,True);
 
-       CVAL(cli->outbuf,smb_com) = SMBlockingX;
+       SCVAL(cli->outbuf,smb_com,SMBlockingX);
        SSVAL(cli->outbuf,smb_tid,cli->cnum);
        cli_setup_packet(cli);
 
-       CVAL(cli->outbuf,smb_vwv0) = 0xFF;
+       SCVAL(cli->outbuf,smb_vwv0,0xFF);
        SSVAL(cli->outbuf,smb_vwv2,fnum);
-       CVAL(cli->outbuf,smb_vwv3) = 0;
+       SCVAL(cli->outbuf,smb_vwv3,0);
        SIVALS(cli->outbuf, smb_vwv4, 0);
        SSVAL(cli->outbuf,smb_vwv6,1);
        SSVAL(cli->outbuf,smb_vwv7,0);
@@ -497,13 +660,13 @@ BOOL cli_lock64(struct cli_state *cli, int fnum,
 
        set_message(cli->outbuf,8,0,True);
 
-       CVAL(cli->outbuf,smb_com) = SMBlockingX;
+       SCVAL(cli->outbuf,smb_com,SMBlockingX);
        SSVAL(cli->outbuf,smb_tid,cli->cnum);
        cli_setup_packet(cli);
 
-       CVAL(cli->outbuf,smb_vwv0) = 0xFF;
+       SCVAL(cli->outbuf,smb_vwv0,0xFF);
        SSVAL(cli->outbuf,smb_vwv2,fnum);
-       CVAL(cli->outbuf,smb_vwv3) = ltype;
+       SCVAL(cli->outbuf,smb_vwv3,ltype);
        SIVALS(cli->outbuf, smb_vwv4, timeout);
        SSVAL(cli->outbuf,smb_vwv6,0);
        SSVAL(cli->outbuf,smb_vwv7,1);
@@ -550,13 +713,13 @@ BOOL cli_unlock64(struct cli_state *cli, int fnum, SMB_BIG_UINT offset, SMB_BIG_
 
        set_message(cli->outbuf,8,0,True);
 
-       CVAL(cli->outbuf,smb_com) = SMBlockingX;
+       SCVAL(cli->outbuf,smb_com,SMBlockingX);
        SSVAL(cli->outbuf,smb_tid,cli->cnum);
        cli_setup_packet(cli);
 
-       CVAL(cli->outbuf,smb_vwv0) = 0xFF;
+       SCVAL(cli->outbuf,smb_vwv0,0xFF);
        SSVAL(cli->outbuf,smb_vwv2,fnum);
-       CVAL(cli->outbuf,smb_vwv3) = LOCKING_ANDX_LARGE_FILES;
+       SCVAL(cli->outbuf,smb_vwv3,LOCKING_ANDX_LARGE_FILES);
        SIVALS(cli->outbuf, smb_vwv4, 0);
        SSVAL(cli->outbuf,smb_vwv6,1);
        SSVAL(cli->outbuf,smb_vwv7,0);
@@ -592,7 +755,7 @@ BOOL cli_getattrE(struct cli_state *cli, int fd,
 
        set_message(cli->outbuf,1,0,True);
 
-       CVAL(cli->outbuf,smb_com) = SMBgetattrE;
+       SCVAL(cli->outbuf,smb_com,SMBgetattrE);
        SSVAL(cli->outbuf,smb_tid,cli->cnum);
        cli_setup_packet(cli);
 
@@ -644,7 +807,7 @@ BOOL cli_getatr(struct cli_state *cli, const char *fname,
 
        set_message(cli->outbuf,0,0,True);
 
-       CVAL(cli->outbuf,smb_com) = SMBgetatr;
+       SCVAL(cli->outbuf,smb_com,SMBgetatr);
        SSVAL(cli->outbuf,smb_tid,cli->cnum);
        cli_setup_packet(cli);
 
@@ -692,7 +855,7 @@ BOOL cli_setatr(struct cli_state *cli, const char *fname, uint16 attr, time_t t)
 
        set_message(cli->outbuf,8,0,True);
 
-       CVAL(cli->outbuf,smb_com) = SMBsetatr;
+       SCVAL(cli->outbuf,smb_com,SMBsetatr);
        SSVAL(cli->outbuf,smb_tid,cli->cnum);
        cli_setup_packet(cli);
 
@@ -760,7 +923,7 @@ 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);
-       CVAL(cli->outbuf,smb_com) = SMBdskattr;
+       SCVAL(cli->outbuf,smb_com,SMBdskattr);
        SSVAL(cli->outbuf,smb_tid,cli->cnum);
        cli_setup_packet(cli);
 
@@ -790,7 +953,7 @@ int cli_ctemp(struct cli_state *cli, const char *path, char **tmp_path)
 
        set_message(cli->outbuf,3,0,True);
 
-       CVAL(cli->outbuf,smb_com) = SMBctemp;
+       SCVAL(cli->outbuf,smb_com,SMBctemp);
        SSVAL(cli->outbuf,smb_tid,cli->cnum);
        cli_setup_packet(cli);