1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-23 17:34:34 +03:00
samba-mirror/source4/libcli/clifile.c
Andrew Tridgell 8e4ab747b0 more fixes from the IRIX compiler (thanks herb!)
(This used to be commit 4cf3839b72)
2003-08-15 18:33:43 +00:00

649 lines
19 KiB
C

/*
Unix SMB/CIFS implementation.
client file operations
Copyright (C) Andrew Tridgell 1994-1998
Copyright (C) Jeremy Allison 2001-2002
Copyright (C) James Myers 2003
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.
*/
#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)
{
union smb_setfileinfo parms;
NTSTATUS status;
if (hard_link) {
parms.generic.level = RAW_SFILEINFO_UNIX_HLINK;
parms.unix_hlink.file.fname = fname_src;
parms.unix_hlink.in.link_dest = fname_dst;
} else {
parms.generic.level = RAW_SFILEINFO_UNIX_LINK;
parms.unix_link.file.fname = fname_src;
parms.unix_link.in.link_dest = fname_dst;
}
status = smb_raw_setpathinfo(cli->tree, &parms);
return NT_STATUS_IS_OK(status);
}
/****************************************************************************
Map standard UNIX permissions onto wire representations.
****************************************************************************/
static uint32 unix_perms_to_wire(mode_t perms)
{
unsigned int 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_ISUID) ? 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)
{
union smb_setfileinfo parms;
NTSTATUS status;
parms.generic.level = SMB_SFILEINFO_UNIX_BASIC;
parms.unix_basic.file.fname = fname;
parms.unix_basic.in.uid = uid;
parms.unix_basic.in.gid = gid;
parms.unix_basic.in.mode = mode;
status = smb_raw_setpathinfo(cli->tree, &parms);
return NT_STATUS_IS_OK(status);
}
/****************************************************************************
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.
****************************************************************************/
BOOL cli_rename(struct cli_state *cli, const char *fname_src, const char *fname_dst)
{
union smb_rename parms;
parms.generic.level = RAW_RENAME_RENAME;
parms.rename.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
parms.rename.in.pattern1 = fname_src;
parms.rename.in.pattern2 = fname_dst;
return NT_STATUS_IS_OK(smb_raw_rename(cli->tree, &parms));
}
/****************************************************************************
Delete a file.
****************************************************************************/
BOOL cli_unlink(struct cli_state *cli, const char *fname)
{
struct smb_unlink parms;
parms.in.pattern = fname;
if (strchr(fname, '*')) {
parms.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
} else {
parms.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
}
return NT_STATUS_IS_OK(smb_raw_unlink(cli->tree, &parms));
}
/****************************************************************************
Create a directory.
****************************************************************************/
BOOL cli_mkdir(struct cli_state *cli, const char *dname)
{
union smb_mkdir parms;
parms.mkdir.level = RAW_MKDIR_MKDIR;
parms.mkdir.in.path = dname;
return NT_STATUS_IS_OK(smb_raw_mkdir(cli->tree, &parms));
}
/****************************************************************************
Remove a directory.
****************************************************************************/
BOOL cli_rmdir(struct cli_state *cli, const char *dname)
{
struct smb_rmdir parms;
parms.in.path = dname;
return NT_STATUS_IS_OK(smb_raw_rmdir(cli->tree, &parms));
}
/****************************************************************************
Set or clear the delete on close flag.
****************************************************************************/
BOOL cli_nt_delete_on_close(struct cli_state *cli, int fnum, BOOL flag)
{
union smb_setfileinfo parms;
NTSTATUS status;
parms.disposition_info.level = RAW_SFILEINFO_DISPOSITION_INFO;
parms.disposition_info.file.fnum = fnum;
parms.disposition_info.in.delete_on_close = flag;
status = smb_raw_setfileinfo(cli->tree, &parms);
return NT_STATUS_IS_OK(status);
}
/****************************************************************************
Create/open a file - exposing the full horror of the NT API :-).
Used in CIFS-on-CIFS NTVFS.
****************************************************************************/
int cli_nt_create_full(struct cli_state *cli, const char *fname,
uint32 CreatFlags, uint32 DesiredAccess,
uint32 FileAttributes, uint32 ShareAccess,
uint32 CreateDisposition, uint32 CreateOptions,
uint8 SecurityFlags)
{
union smb_open open_parms;
TALLOC_CTX *mem_ctx;
NTSTATUS status;
mem_ctx = talloc_init("raw_open");
if (!mem_ctx) return -1;
open_parms.ntcreatex.level = RAW_OPEN_NTCREATEX;
open_parms.ntcreatex.in.flags = CreatFlags;
open_parms.ntcreatex.in.root_fid = 0;
open_parms.ntcreatex.in.access_mask = DesiredAccess;
open_parms.ntcreatex.in.file_attr = FileAttributes;
open_parms.ntcreatex.in.alloc_size = 0;
open_parms.ntcreatex.in.share_access = ShareAccess;
open_parms.ntcreatex.in.open_disposition = CreateDisposition;
open_parms.ntcreatex.in.create_options = CreateOptions;
open_parms.ntcreatex.in.impersonation = 0;
open_parms.ntcreatex.in.security_flags = SecurityFlags;
open_parms.ntcreatex.in.fname = fname;
status = smb_raw_open(cli->tree, mem_ctx, &open_parms);
talloc_destroy(mem_ctx);
if (NT_STATUS_IS_OK(status)) {
return open_parms.ntcreatex.out.fnum;
}
return -1;
}
/****************************************************************************
Open a file (using SMBopenx)
WARNING: if you open with O_WRONLY then getattrE won't work!
****************************************************************************/
int cli_open(struct cli_state *cli, const char *fname, int flags, int share_mode)
{
union smb_open open_parms;
unsigned openfn=0;
unsigned accessmode=0;
TALLOC_CTX *mem_ctx;
NTSTATUS status;
mem_ctx = talloc_init("raw_open");
if (!mem_ctx) return -1;
if (flags & O_CREAT) {
openfn |= OPENX_OPEN_FUNC_CREATE;
}
if (!(flags & O_EXCL)) {
if (flags & O_TRUNC) {
openfn |= OPENX_OPEN_FUNC_TRUNC;
} else {
openfn |= OPENX_OPEN_FUNC_OPEN;
}
}
accessmode = (share_mode<<OPENX_MODE_DENY_SHIFT);
if ((flags & O_ACCMODE) == O_RDWR) {
accessmode |= OPENX_MODE_ACCESS_RDWR;
} else if ((flags & O_ACCMODE) == O_WRONLY) {
accessmode |= OPENX_MODE_ACCESS_WRITE;
}
#if defined(O_SYNC)
if ((flags & O_SYNC) == O_SYNC) {
accessmode |= OPENX_MODE_WRITE_THRU;
}
#endif
if (share_mode == DENY_FCB) {
accessmode = OPENX_MODE_ACCESS_FCB | OPENX_MODE_DENY_FCB;
}
open_parms.openx.level = RAW_OPEN_OPENX;
open_parms.openx.in.flags = 0;
open_parms.openx.in.open_mode = accessmode;
open_parms.openx.in.search_attrs = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
open_parms.openx.in.file_attrs = 0;
open_parms.openx.in.write_time = 0;
open_parms.openx.in.open_func = openfn;
open_parms.openx.in.size = 0;
open_parms.openx.in.timeout = 0;
open_parms.openx.in.fname = fname;
status = smb_raw_open(cli->tree, mem_ctx, &open_parms);
talloc_destroy(mem_ctx);
if (NT_STATUS_IS_OK(status)) {
return open_parms.openx.out.fnum;
}
return -1;
}
/****************************************************************************
Close a file.
****************************************************************************/
BOOL cli_close(struct cli_state *cli, int fnum)
{
union smb_close close_parms;
NTSTATUS status;
close_parms.close.level = RAW_CLOSE_CLOSE;
close_parms.close.in.fnum = fnum;
close_parms.close.in.write_time = 0;
status = smb_raw_close(cli->tree, &close_parms);
return NT_STATUS_IS_OK(status);
}
/****************************************************************************
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)
{
union smb_lock parms;
struct smb_lock_entry lock[1];
NTSTATUS status;
parms.lockx.level = RAW_LOCK_LOCKX;
parms.lockx.in.fnum = fnum;
parms.lockx.in.mode = locktype;
parms.lockx.in.timeout = timeout;
parms.lockx.in.ulock_cnt = 0;
parms.lockx.in.lock_cnt = 1;
lock[0].pid = cli->session->pid;
lock[0].offset = offset;
lock[0].count = len;
parms.lockx.in.locks = &lock[0];
status = smb_raw_lock(cli->tree, &parms);
return status;
}
/****************************************************************************
Lock a file.
****************************************************************************/
BOOL cli_lock(struct cli_state *cli, int fnum,
uint32 offset, uint32 len, int timeout, enum brl_type lock_type)
{
union smb_lock parms;
struct smb_lock_entry lock[1];
NTSTATUS status;
parms.lockx.level = RAW_LOCK_LOCKX;
parms.lockx.in.fnum = fnum;
parms.lockx.in.mode = (lock_type == READ_LOCK? 1 : 0);
parms.lockx.in.timeout = timeout;
parms.lockx.in.ulock_cnt = 0;
parms.lockx.in.lock_cnt = 1;
lock[0].pid = cli->session->pid;
lock[0].offset = offset;
lock[0].count = len;
parms.lockx.in.locks = &lock[0];
status = smb_raw_lock(cli->tree, &parms);
return NT_STATUS_IS_OK(status);
}
/****************************************************************************
Unlock a file.
****************************************************************************/
BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len)
{
union smb_lock parms;
struct smb_lock_entry lock[1];
NTSTATUS status;
parms.lockx.level = RAW_LOCK_LOCKX;
parms.lockx.in.fnum = fnum;
parms.lockx.in.mode = 0;
parms.lockx.in.timeout = 0;
parms.lockx.in.ulock_cnt = 1;
parms.lockx.in.lock_cnt = 0;
lock[0].pid = cli->session->pid;
lock[0].offset = offset;
lock[0].count = len;
parms.lockx.in.locks = &lock[0];
status = smb_raw_lock(cli->tree, &parms);
return NT_STATUS_IS_OK(status);
}
/****************************************************************************
Lock a file with 64 bit offsets.
****************************************************************************/
BOOL cli_lock64(struct cli_state *cli, int fnum,
SMB_OFF_T offset, SMB_OFF_T len, int timeout, enum brl_type lock_type)
{
union smb_lock parms;
int ltype;
struct smb_lock_entry lock[1];
NTSTATUS status;
if (!(cli->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
return cli_lock(cli, fnum, offset, len, timeout, lock_type);
}
parms.lockx.level = RAW_LOCK_LOCKX;
parms.lockx.in.fnum = fnum;
ltype = (lock_type == READ_LOCK? 1 : 0);
ltype |= LOCKING_ANDX_LARGE_FILES;
parms.lockx.in.mode = ltype;
parms.lockx.in.timeout = timeout;
parms.lockx.in.ulock_cnt = 0;
parms.lockx.in.lock_cnt = 1;
lock[0].pid = cli->session->pid;
lock[0].offset = offset;
lock[0].count = len;
parms.lockx.in.locks = &lock[0];
status = smb_raw_lock(cli->tree, &parms);
return NT_STATUS_IS_OK(status);
}
/****************************************************************************
Unlock a file with 64 bit offsets.
****************************************************************************/
BOOL cli_unlock64(struct cli_state *cli, int fnum, SMB_OFF_T offset, SMB_OFF_T len)
{
union smb_lock parms;
struct smb_lock_entry lock[1];
NTSTATUS status;
if (!(cli->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
return cli_unlock(cli, fnum, offset, len);
}
parms.lockx.level = RAW_LOCK_LOCKX;
parms.lockx.in.fnum = fnum;
parms.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
parms.lockx.in.timeout = 0;
parms.lockx.in.ulock_cnt = 1;
parms.lockx.in.lock_cnt = 0;
lock[0].pid = cli->session->pid;
lock[0].offset = offset;
lock[0].count = len;
parms.lockx.in.locks = &lock[0];
status = smb_raw_lock(cli->tree, &parms);
return NT_STATUS_IS_OK(status);
}
/****************************************************************************
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)
{
union smb_fileinfo parms;
NTSTATUS status;
parms.getattre.level = RAW_FILEINFO_GETATTRE;
parms.getattre.in.fnum = fd;
status = smb_raw_fileinfo(cli->tree, NULL, &parms);
if (!NT_STATUS_IS_OK(status))
return False;
if (size) {
*size = parms.getattre.out.size;
}
if (attr) {
*attr = parms.getattre.out.attrib;
}
if (c_time) {
*c_time = parms.getattre.out.create_time;
}
if (a_time) {
*a_time = parms.getattre.out.access_time;
}
if (m_time) {
*m_time = parms.getattre.out.write_time;
}
return True;
}
/****************************************************************************
Do a SMBgetatr call
****************************************************************************/
BOOL cli_getatr(struct cli_state *cli, const char *fname,
uint16 *attr, size_t *size, time_t *t)
{
union smb_fileinfo parms;
NTSTATUS status;
parms.getattr.level = RAW_FILEINFO_GETATTR;
parms.getattr.in.fname = fname;
status = smb_raw_pathinfo(cli->tree, NULL, &parms);
if (!NT_STATUS_IS_OK(status)) {
return False;
}
if (size) {
*size = parms.getattr.out.size;
}
if (t) {
*t = parms.getattr.out.write_time;
}
if (attr) {
*attr = parms.getattr.out.attrib;
}
return True;
}
/****************************************************************************
Do a SMBsetatr call.
****************************************************************************/
BOOL cli_setatr(struct cli_state *cli, const char *fname, uint16 mode, time_t t)
{
union smb_setfileinfo parms;
NTSTATUS status;
parms.setattr.level = RAW_SFILEINFO_SETATTR;
parms.setattr.in.attrib = mode;
parms.setattr.in.write_time = t;
parms.setattr.file.fname = fname;
status = smb_raw_setpathinfo(cli->tree, &parms);
return NT_STATUS_IS_OK(status);
}
/****************************************************************************
Check for existence of a dir.
****************************************************************************/
BOOL cli_chkpath(struct cli_state *cli, const char *path)
{
struct smb_chkpath parms;
char *path2;
NTSTATUS status;
path2 = strdup(path);
trim_string(path2,NULL,"\\");
if (!*path2) {
free(path2);
path2 = strdup("\\");
}
parms.in.path = path2;
status = smb_raw_chkpath(cli->tree, &parms);
free(path2);
return NT_STATUS_IS_OK(status);
}
/****************************************************************************
Query disk space.
****************************************************************************/
BOOL cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail)
{
union smb_fsinfo fsinfo_parms;
TALLOC_CTX *mem_ctx;
NTSTATUS status;
mem_ctx = talloc_init("cli_dskattr");
fsinfo_parms.dskattr.level = RAW_QFS_DSKATTR;
status = smb_raw_fsinfo(cli->tree, mem_ctx, &fsinfo_parms);
if (NT_STATUS_IS_OK(status)) {
*bsize = fsinfo_parms.dskattr.out.block_size;
*total = fsinfo_parms.dskattr.out.units_total;
*avail = fsinfo_parms.dskattr.out.units_free;
}
talloc_destroy(mem_ctx);
return NT_STATUS_IS_OK(status);
}
/****************************************************************************
Create and open a temporary file.
****************************************************************************/
int cli_ctemp(struct cli_state *cli, const char *path, char **tmp_path)
{
union smb_open open_parms;
TALLOC_CTX *mem_ctx;
NTSTATUS status;
mem_ctx = talloc_init("raw_open");
if (!mem_ctx) return -1;
open_parms.openx.level = RAW_OPEN_CTEMP;
open_parms.ctemp.in.attrib = 0;
open_parms.ctemp.in.directory = path;
status = smb_raw_open(cli->tree, mem_ctx, &open_parms);
if (tmp_path) {
*tmp_path = strdup(open_parms.ctemp.out.name);
}
talloc_destroy(mem_ctx);
if (NT_STATUS_IS_OK(status)) {
return open_parms.ctemp.out.fnum;
}
return -1;
}