1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-17 02:05:21 +03:00
Andrew Tridgell 87fbb7092b The big character set handling changeover!
This commit gets rid of all our old codepage handling and replaces it with
iconv. All internal strings in Samba are now in "unix" charset, which may
be multi-byte. See internals.doc and my posting to samba-technical for
a more complete explanation.
(This used to be commit debb471267960e56005a741817ebd227ecfc512a)
2001-07-04 07:15:53 +00:00

821 lines
19 KiB
C

/*
Unix SMB/Netbios implementation.
Version 3.0
client file operations
Copyright (C) Andrew Tridgell 1994-1998
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
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
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.
*/
#define NO_SYSLOG
#include "includes.h"
/****************************************************************************
rename a file
****************************************************************************/
BOOL cli_rename(struct cli_state *cli, char *fname_src, char *fname_dst)
{
char *p;
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
set_message(cli->outbuf,1, 0, True);
CVAL(cli->outbuf,smb_com) = SMBmv;
SSVAL(cli->outbuf,smb_tid,cli->cnum);
cli_setup_packet(cli);
SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN | aDIR);
p = smb_buf(cli->outbuf);
*p++ = 4;
p += clistr_push(cli, p, fname_src, -1,
STR_TERMINATE);
*p++ = 4;
p += clistr_push(cli, p, fname_dst, -1,
STR_TERMINATE);
cli_setup_bcc(cli, p);
cli_send_smb(cli);
if (!cli_receive_smb(cli)) {
return False;
}
if (CVAL(cli->inbuf,smb_rcls) != 0) {
return False;
}
return True;
}
/****************************************************************************
delete a file
****************************************************************************/
BOOL cli_unlink(struct cli_state *cli, char *fname)
{
char *p;
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
set_message(cli->outbuf,1, 0,True);
CVAL(cli->outbuf,smb_com) = SMBunlink;
SSVAL(cli->outbuf,smb_tid,cli->cnum);
cli_setup_packet(cli);
SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
p = smb_buf(cli->outbuf);
*p++ = 4;
p += clistr_push(cli, p, fname, -1, STR_TERMINATE);
cli_setup_bcc(cli, p);
cli_send_smb(cli);
if (!cli_receive_smb(cli)) {
return False;
}
if (CVAL(cli->inbuf,smb_rcls) != 0) {
return False;
}
return True;
}
/****************************************************************************
create a directory
****************************************************************************/
BOOL cli_mkdir(struct cli_state *cli, char *dname)
{
char *p;
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
set_message(cli->outbuf,0, 0,True);
CVAL(cli->outbuf,smb_com) = SMBmkdir;
SSVAL(cli->outbuf,smb_tid,cli->cnum);
cli_setup_packet(cli);
p = smb_buf(cli->outbuf);
*p++ = 4;
p += clistr_push(cli, p, dname, -1, 0);
cli_setup_bcc(cli, p);
cli_send_smb(cli);
if (!cli_receive_smb(cli)) {
return False;
}
if (CVAL(cli->inbuf,smb_rcls) != 0) {
return False;
}
return True;
}
/****************************************************************************
remove a directory
****************************************************************************/
BOOL cli_rmdir(struct cli_state *cli, char *dname)
{
char *p;
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
set_message(cli->outbuf,0, 0, True);
CVAL(cli->outbuf,smb_com) = SMBrmdir;
SSVAL(cli->outbuf,smb_tid,cli->cnum);
cli_setup_packet(cli);
p = smb_buf(cli->outbuf);
*p++ = 4;
p += clistr_push(cli, p, dname, -1, STR_TERMINATE);
cli_setup_bcc(cli, p);
cli_send_smb(cli);
if (!cli_receive_smb(cli)) {
return False;
}
if (CVAL(cli->inbuf,smb_rcls) != 0) {
return False;
}
return True;
}
/****************************************************************************
Set or clear the delete on close flag.
****************************************************************************/
int cli_nt_delete_on_close(struct cli_state *cli, int fnum, BOOL flag)
{
int data_len = 1;
int param_len = 6;
uint16 setup = TRANSACT2_SETFILEINFO;
pstring param;
unsigned char data;
char *rparam=NULL, *rdata=NULL;
memset(param, 0, param_len);
SSVAL(param,0,fnum);
SSVAL(param,2,SMB_SET_FILE_DISPOSITION_INFO);
data = flag ? 1 : 0;
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;
}
if (rdata) free(rdata);
if (rparam) free(rparam);
return True;
}
/****************************************************************************
open a file - exposing the full horror of the NT API :-).
Used in smbtorture.
****************************************************************************/
int cli_nt_create_full(struct cli_state *cli, char *fname, uint32 DesiredAccess,
uint32 FileAttributes, uint32 ShareAccess,
uint32 CreateDisposition, uint32 CreateOptions)
{
char *p;
int len;
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
set_message(cli->outbuf,24,0,True);
CVAL(cli->outbuf,smb_com) = SMBntcreateX;
SSVAL(cli->outbuf,smb_tid,cli->cnum);
cli_setup_packet(cli);
SSVAL(cli->outbuf,smb_vwv0,0xFF);
if (cli->use_oplocks)
SIVAL(cli->outbuf,smb_ntcreate_Flags, REQUEST_OPLOCK|REQUEST_BATCH_OPLOCK);
else
SIVAL(cli->outbuf,smb_ntcreate_Flags, 0);
SIVAL(cli->outbuf,smb_ntcreate_RootDirectoryFid, 0x0);
SIVAL(cli->outbuf,smb_ntcreate_DesiredAccess, DesiredAccess);
SIVAL(cli->outbuf,smb_ntcreate_FileAttributes, FileAttributes);
SIVAL(cli->outbuf,smb_ntcreate_ShareAccess, ShareAccess);
SIVAL(cli->outbuf,smb_ntcreate_CreateDisposition, CreateDisposition);
SIVAL(cli->outbuf,smb_ntcreate_CreateOptions, CreateOptions);
SIVAL(cli->outbuf,smb_ntcreate_ImpersonationLevel, 0x02);
p = smb_buf(cli->outbuf);
/* this alignment and termination is critical for netapp filers. Don't change */
p += clistr_align_out(cli, p, 0);
len = clistr_push(cli, p, fname, -1, 0);
p += len;
SSVAL(cli->outbuf,smb_ntcreate_NameLength, len);
/* sigh. this copes with broken netapp filer behaviour */
p += clistr_push(cli, p, "", -1, STR_TERMINATE);
cli_setup_bcc(cli, p);
cli_send_smb(cli);
if (!cli_receive_smb(cli)) {
return -1;
}
if (CVAL(cli->inbuf,smb_rcls) != 0) {
return -1;
}
return SVAL(cli->inbuf,smb_vwv2 + 1);
}
/****************************************************************************
open a file
****************************************************************************/
int cli_nt_create(struct cli_state *cli, char *fname, uint32 DesiredAccess)
{
return cli_nt_create_full(cli, fname, DesiredAccess, 0,
FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_EXISTS_OPEN, 0x0);
}
/****************************************************************************
open a file
WARNING: if you open with O_WRONLY then getattrE won't work!
****************************************************************************/
int cli_open(struct cli_state *cli, char *fname, int flags, int share_mode)
{
char *p;
unsigned openfn=0;
unsigned accessmode=0;
if (flags & O_CREAT)
openfn |= (1<<4);
if (!(flags & O_EXCL)) {
if (flags & O_TRUNC)
openfn |= (1<<1);
else
openfn |= (1<<0);
}
accessmode = (share_mode<<4);
if ((flags & O_ACCMODE) == O_RDWR) {
accessmode |= 2;
} else if ((flags & O_ACCMODE) == O_WRONLY) {
accessmode |= 1;
}
#if defined(O_SYNC)
if ((flags & O_SYNC) == O_SYNC) {
accessmode |= (1<<14);
}
#endif /* O_SYNC */
if (share_mode == DENY_FCB) {
accessmode = 0xFF;
}
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
set_message(cli->outbuf,15,0,True);
CVAL(cli->outbuf,smb_com) = SMBopenX;
SSVAL(cli->outbuf,smb_tid,cli->cnum);
cli_setup_packet(cli);
SSVAL(cli->outbuf,smb_vwv0,0xFF);
SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
SSVAL(cli->outbuf,smb_vwv3,accessmode);
SSVAL(cli->outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
SSVAL(cli->outbuf,smb_vwv5,0);
SSVAL(cli->outbuf,smb_vwv8,openfn);
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;
SSVAL(cli->outbuf,smb_vwv2,SVAL(cli->outbuf,smb_vwv2) | 6);
}
p = smb_buf(cli->outbuf);
p += clistr_push(cli, p, fname, -1, STR_TERMINATE);
cli_setup_bcc(cli, p);
cli_send_smb(cli);
if (!cli_receive_smb(cli)) {
return -1;
}
if (CVAL(cli->inbuf,smb_rcls) != 0) {
return -1;
}
return SVAL(cli->inbuf,smb_vwv2);
}
/****************************************************************************
close a file
****************************************************************************/
BOOL cli_close(struct cli_state *cli, int fnum)
{
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
set_message(cli->outbuf,3,0,True);
CVAL(cli->outbuf,smb_com) = SMBclose;
SSVAL(cli->outbuf,smb_tid,cli->cnum);
cli_setup_packet(cli);
SSVAL(cli->outbuf,smb_vwv0,fnum);
SIVALS(cli->outbuf,smb_vwv1,-1);
cli_send_smb(cli);
if (!cli_receive_smb(cli)) {
return False;
}
if (CVAL(cli->inbuf,smb_rcls) != 0) {
return False;
}
return True;
}
/****************************************************************************
lock a file
****************************************************************************/
BOOL cli_lock(struct cli_state *cli, int fnum,
uint32 offset, uint32 len, int timeout, enum brl_type lock_type)
{
char *p;
int saved_timeout = cli->timeout;
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0', smb_size);
set_message(cli->outbuf,8,0,True);
CVAL(cli->outbuf,smb_com) = SMBlockingX;
SSVAL(cli->outbuf,smb_tid,cli->cnum);
cli_setup_packet(cli);
CVAL(cli->outbuf,smb_vwv0) = 0xFF;
SSVAL(cli->outbuf,smb_vwv2,fnum);
CVAL(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);
p = smb_buf(cli->outbuf);
SSVAL(p, 0, cli->pid);
SIVAL(p, 2, offset);
SIVAL(p, 6, len);
p += 10;
cli_setup_bcc(cli, p);
cli_send_smb(cli);
cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout + 2*1000);
if (!cli_receive_smb(cli)) {
cli->timeout = saved_timeout;
return False;
}
cli->timeout = saved_timeout;
if (CVAL(cli->inbuf,smb_rcls) != 0) {
return False;
}
return True;
}
/****************************************************************************
unlock a file
****************************************************************************/
BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len)
{
char *p;
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
set_message(cli->outbuf,8,0,True);
CVAL(cli->outbuf,smb_com) = SMBlockingX;
SSVAL(cli->outbuf,smb_tid,cli->cnum);
cli_setup_packet(cli);
CVAL(cli->outbuf,smb_vwv0) = 0xFF;
SSVAL(cli->outbuf,smb_vwv2,fnum);
CVAL(cli->outbuf,smb_vwv3) = 0;
SIVALS(cli->outbuf, smb_vwv4, 0);
SSVAL(cli->outbuf,smb_vwv6,1);
SSVAL(cli->outbuf,smb_vwv7,0);
p = smb_buf(cli->outbuf);
SSVAL(p, 0, cli->pid);
SIVAL(p, 2, offset);
SIVAL(p, 6, len);
p += 10;
cli_setup_bcc(cli, p);
cli_send_smb(cli);
if (!cli_receive_smb(cli)) {
return False;
}
if (CVAL(cli->inbuf,smb_rcls) != 0) {
return False;
}
return True;
}
/****************************************************************************
lock a file with 64 bit offsets
****************************************************************************/
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;
int saved_timeout = cli->timeout;
int ltype;
ltype = (lock_type == READ_LOCK? 1 : 0);
ltype |= LOCKING_ANDX_LARGE_FILES;
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0', smb_size);
set_message(cli->outbuf,8,0,True);
CVAL(cli->outbuf,smb_com) = SMBlockingX;
SSVAL(cli->outbuf,smb_tid,cli->cnum);
cli_setup_packet(cli);
CVAL(cli->outbuf,smb_vwv0) = 0xFF;
SSVAL(cli->outbuf,smb_vwv2,fnum);
CVAL(cli->outbuf,smb_vwv3) = ltype;
SIVALS(cli->outbuf, smb_vwv4, timeout);
SSVAL(cli->outbuf,smb_vwv6,0);
SSVAL(cli->outbuf,smb_vwv7,1);
p = smb_buf(cli->outbuf);
SIVAL(p, 0, cli->pid);
SOFF_T_R(p, 4, offset);
SOFF_T_R(p, 12, len);
p += 20;
cli_setup_bcc(cli, p);
cli_send_smb(cli);
cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout + 2*1000);
if (!cli_receive_smb(cli)) {
cli->timeout = saved_timeout;
return False;
}
cli->timeout = saved_timeout;
if (CVAL(cli->inbuf,smb_rcls) != 0) {
return False;
}
return True;
}
/****************************************************************************
unlock a file with 64 bit offsets
****************************************************************************/
BOOL cli_unlock64(struct cli_state *cli, int fnum, SMB_BIG_UINT offset, SMB_BIG_UINT len)
{
char *p;
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
set_message(cli->outbuf,8,0,True);
CVAL(cli->outbuf,smb_com) = SMBlockingX;
SSVAL(cli->outbuf,smb_tid,cli->cnum);
cli_setup_packet(cli);
CVAL(cli->outbuf,smb_vwv0) = 0xFF;
SSVAL(cli->outbuf,smb_vwv2,fnum);
CVAL(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);
p = smb_buf(cli->outbuf);
SIVAL(p, 0, cli->pid);
SOFF_T_R(p, 4, offset);
SOFF_T_R(p, 12, len);
p += 20;
cli_setup_bcc(cli, p);
cli_send_smb(cli);
if (!cli_receive_smb(cli)) {
return False;
}
if (CVAL(cli->inbuf,smb_rcls) != 0) {
return False;
}
return True;
}
/****************************************************************************
do a SMBgetattrE call
****************************************************************************/
BOOL cli_getattrE(struct cli_state *cli, int fd,
uint16 *attr, size_t *size,
time_t *c_time, time_t *a_time, time_t *m_time)
{
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
set_message(cli->outbuf,1,0,True);
CVAL(cli->outbuf,smb_com) = SMBgetattrE;
SSVAL(cli->outbuf,smb_tid,cli->cnum);
cli_setup_packet(cli);
SSVAL(cli->outbuf,smb_vwv0,fd);
cli_send_smb(cli);
if (!cli_receive_smb(cli)) {
return False;
}
if (CVAL(cli->inbuf,smb_rcls) != 0) {
return False;
}
if (size) {
*size = IVAL(cli->inbuf, smb_vwv6);
}
if (attr) {
*attr = SVAL(cli->inbuf,smb_vwv10);
}
if (c_time) {
*c_time = make_unix_date3(cli->inbuf+smb_vwv0);
}
if (a_time) {
*a_time = make_unix_date3(cli->inbuf+smb_vwv2);
}
if (m_time) {
*m_time = make_unix_date3(cli->inbuf+smb_vwv4);
}
return True;
}
/****************************************************************************
do a SMBgetatr call
****************************************************************************/
BOOL cli_getatr(struct cli_state *cli, char *fname,
uint16 *attr, size_t *size, time_t *t)
{
char *p;
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
set_message(cli->outbuf,0,0,True);
CVAL(cli->outbuf,smb_com) = SMBgetatr;
SSVAL(cli->outbuf,smb_tid,cli->cnum);
cli_setup_packet(cli);
p = smb_buf(cli->outbuf);
*p++ = 4;
p += clistr_push(cli, p, fname, -1, STR_TERMINATE);
cli_setup_bcc(cli, p);
cli_send_smb(cli);
if (!cli_receive_smb(cli)) {
return False;
}
if (CVAL(cli->inbuf,smb_rcls) != 0) {
return False;
}
if (size) {
*size = IVAL(cli->inbuf, smb_vwv3);
}
if (t) {
*t = make_unix_date3(cli->inbuf+smb_vwv1);
}
if (attr) {
*attr = SVAL(cli->inbuf,smb_vwv0);
}
return True;
}
/****************************************************************************
do a SMBsetatr call
****************************************************************************/
BOOL cli_setatr(struct cli_state *cli, char *fname, uint16 attr, time_t t)
{
char *p;
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
set_message(cli->outbuf,8,0,True);
CVAL(cli->outbuf,smb_com) = SMBsetatr;
SSVAL(cli->outbuf,smb_tid,cli->cnum);
cli_setup_packet(cli);
SSVAL(cli->outbuf,smb_vwv0, attr);
put_dos_date3(cli->outbuf,smb_vwv1, t);
p = smb_buf(cli->outbuf);
*p++ = 4;
p += clistr_push(cli, p, fname, -1, STR_TERMINATE);
*p++ = 4;
cli_setup_bcc(cli, p);
cli_send_smb(cli);
if (!cli_receive_smb(cli)) {
return False;
}
if (CVAL(cli->inbuf,smb_rcls) != 0) {
return False;
}
return True;
}
/****************************************************************************
check for existance of a dir
****************************************************************************/
BOOL cli_chkpath(struct cli_state *cli, char *path)
{
pstring path2;
char *p;
safe_strcpy(path2,path,sizeof(pstring));
trim_string(path2,NULL,"\\");
if (!*path2) *path2 = '\\';
memset(cli->outbuf,'\0',smb_size);
set_message(cli->outbuf,0,0,True);
SCVAL(cli->outbuf,smb_com,SMBchkpth);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
cli_setup_packet(cli);
p = smb_buf(cli->outbuf);
*p++ = 4;
p += clistr_push(cli, p, path2, -1, STR_TERMINATE);
cli_setup_bcc(cli, p);
cli_send_smb(cli);
if (!cli_receive_smb(cli)) {
return False;
}
if (cli_error(cli, NULL, NULL, NULL)) return False;
return True;
}
/****************************************************************************
query disk space
****************************************************************************/
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;
SSVAL(cli->outbuf,smb_tid,cli->cnum);
cli_setup_packet(cli);
cli_send_smb(cli);
if (!cli_receive_smb(cli)) {
return False;
}
*bsize = SVAL(cli->inbuf,smb_vwv1)*SVAL(cli->inbuf,smb_vwv2);
*total = SVAL(cli->inbuf,smb_vwv0);
*avail = SVAL(cli->inbuf,smb_vwv3);
return True;
}
/****************************************************************************
create and open a temporary file
****************************************************************************/
int cli_ctemp(struct cli_state *cli, char *path, char **tmp_path)
{
char *p;
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
set_message(cli->outbuf,1,0,True);
CVAL(cli->outbuf,smb_com) = SMBctemp;
SSVAL(cli->outbuf,smb_tid,cli->cnum);
cli_setup_packet(cli);
SSVAL(cli->outbuf,smb_vwv0,0);
p = smb_buf(cli->outbuf);
*p++ = 4;
p += clistr_push(cli, p, path, -1, STR_TERMINATE);
cli_setup_bcc(cli, p);
cli_send_smb(cli);
if (!cli_receive_smb(cli)) {
return -1;
}
if (CVAL(cli->inbuf,smb_rcls) != 0) {
return -1;
}
if (tmp_path) {
pstring path2;
clistr_pull(cli, path2, smb_buf(cli->inbuf)+1,
sizeof(path2), -1, STR_TERMINATE);
*tmp_path = strdup(path2);
}
return SVAL(cli->inbuf,smb_vwv0);
}