mirror of
https://github.com/samba-team/samba.git
synced 2024-12-28 07:21:54 +03:00
Wrote VFS initialisation routines.
Converted some useful routines from doscalls.c and changed them to use VFS I/O functions: dos_file_exist dos_read_data dos_write_data dos_transfer_file dos_readdirname Some of these functions have been #ifdef'ed out of doscalls.c as they are not used anywhere else. Not sure whether they should be deleted or not. The remaining dos_* calls seem to be used by clients and for locking stuff. This should be cleaned up sometime.
This commit is contained in:
parent
6e607ef760
commit
ddde0ab9a1
407
source/smbd/vfs.c
Normal file
407
source/smbd/vfs.c
Normal file
@ -0,0 +1,407 @@
|
||||
/*
|
||||
Unix SMB/Netbios implementation.
|
||||
Version 1.9.
|
||||
vfs initialisation and support functions
|
||||
Copyright (C) Tim Potter 1992-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.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include <dlfcn.h>
|
||||
|
||||
extern int DEBUGLEVEL;
|
||||
|
||||
/* Some structures to help us initialise the vfs operations table */
|
||||
|
||||
struct vfs_syminfo {
|
||||
char *name;
|
||||
void *fptr;
|
||||
};
|
||||
|
||||
struct vfs_ops dl_ops;
|
||||
|
||||
struct vfs_syminfo vfs_syminfo[] = {
|
||||
|
||||
/* Global operations */
|
||||
|
||||
{"vfs_init", &dl_ops.init},
|
||||
|
||||
/* Disk operations */
|
||||
|
||||
{"vfs_connect", &dl_ops.connect},
|
||||
{"vfs_disconnect", &dl_ops.disconnect},
|
||||
{"vfs_disk_free", &dl_ops.disk_free},
|
||||
|
||||
/* Directory operations */
|
||||
|
||||
{"vfs_opendir", &dl_ops.opendir},
|
||||
{"vfs_readdir", &dl_ops.readdir},
|
||||
{"vfs_mkdir", &dl_ops.mkdir},
|
||||
{"vfs_rmdir", &dl_ops.rmdir},
|
||||
|
||||
/* File operations */
|
||||
|
||||
{"vfs_open", &dl_ops.open},
|
||||
{"vfs_close", &dl_ops.close},
|
||||
{"vfs_read", &dl_ops.read},
|
||||
{"vfs_write", &dl_ops.write},
|
||||
{"vfs_lseek", &dl_ops.lseek},
|
||||
{"vfs_rename", &dl_ops.rename},
|
||||
{"vfs_sync", &dl_ops.sync},
|
||||
{"vfs_stat", &dl_ops.stat},
|
||||
{"vfs_fstat", &dl_ops.fstat},
|
||||
{"vfs_lstat", &dl_ops.lstat},
|
||||
{"vfs_lock", &dl_ops.lock},
|
||||
{"vfs_unlink", &dl_ops.unlink},
|
||||
{"vfs_chmod", &dl_ops.chmod},
|
||||
{"vfs_utime", &dl_ops.utime},
|
||||
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
/* Default vfs hooks. WARNING: The order of these initialisers is
|
||||
very important. Change at your own peril. */
|
||||
|
||||
struct vfs_ops default_vfs_ops = {
|
||||
|
||||
/* Global operations */
|
||||
|
||||
NULL, /* init */
|
||||
|
||||
/* Disk operations */
|
||||
|
||||
NULL, /* connect */
|
||||
NULL, /* disconnect */
|
||||
vfswrap_disk_free,
|
||||
|
||||
/* Directory operations */
|
||||
|
||||
vfswrap_opendir,
|
||||
vfswrap_readdir,
|
||||
vfswrap_mkdir,
|
||||
vfswrap_rmdir,
|
||||
|
||||
/* File operations */
|
||||
|
||||
vfswrap_open,
|
||||
vfswrap_close,
|
||||
vfswrap_read,
|
||||
vfswrap_write,
|
||||
vfswrap_lseek,
|
||||
vfswrap_rename,
|
||||
vfswrap_sync_file,
|
||||
vfswrap_stat,
|
||||
vfswrap_fstat,
|
||||
vfswrap_lstat,
|
||||
vfswrap_fcntl_lock,
|
||||
vfswrap_unlink,
|
||||
vfswrap_chmod,
|
||||
vfswrap_utime
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
call vfs_init function of loadable module
|
||||
****************************************************************************/
|
||||
BOOL do_vfs_init(char *vfs_object)
|
||||
{
|
||||
void *handle, (*fptr)(void);
|
||||
|
||||
DEBUG(3, ("Calling vfs_init for module %s\n", vfs_object));
|
||||
|
||||
handle = dlopen(vfs_object, RTLD_NOW);
|
||||
if (!handle) {
|
||||
DEBUG(0, ("Error opening %s: %s\n", vfs_object, dlerror()));
|
||||
return False;
|
||||
}
|
||||
|
||||
fptr = dlsym(handle, "vfs_init");
|
||||
|
||||
/* Call initialisation function */
|
||||
|
||||
if (fptr != NULL) {
|
||||
fptr();
|
||||
}
|
||||
|
||||
dlclose(handle);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
initialise default vfs hooks
|
||||
****************************************************************************/
|
||||
int vfs_init_default(connection_struct *conn)
|
||||
{
|
||||
DEBUG(3, ("Initialising default vfs hooks\n"));
|
||||
|
||||
bcopy(&default_vfs_ops, &conn->vfs_ops, sizeof(conn->vfs_ops));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
initialise custom vfs hooks
|
||||
****************************************************************************/
|
||||
int vfs_init_custom(connection_struct *conn)
|
||||
{
|
||||
void *handle, *fptr;
|
||||
int index;
|
||||
|
||||
DEBUG(3, ("Initialising custom vfs hooks from %s\n",
|
||||
lp_vfsobj(SNUM(conn))));
|
||||
|
||||
/* Open object file */
|
||||
|
||||
handle = dlopen(lp_vfsobj(SNUM(conn)), RTLD_NOW);
|
||||
if (!handle) {
|
||||
DEBUG(0, ("Error opening %s: %s\n", lp_vfsobj(SNUM(conn)),
|
||||
dlerror()));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Read list of symbols */
|
||||
|
||||
for(index = 0; vfs_syminfo[index].name; index++) {
|
||||
fptr = dlsym(handle, vfs_syminfo[index].name);
|
||||
if (fptr == NULL) {
|
||||
DEBUG(0, ("Symbol %s not found in %s\n", vfs_syminfo[index].name,
|
||||
lp_vfsobj(SNUM(conn))));
|
||||
return -1;
|
||||
}
|
||||
|
||||
*((void **)vfs_syminfo[index].fptr) = fptr;
|
||||
}
|
||||
|
||||
/* Copy loaded symbols into connection struct */
|
||||
|
||||
bcopy(&dl_ops, &conn->vfs_ops, sizeof(dl_ops));
|
||||
dlclose(handle);
|
||||
|
||||
#if 0
|
||||
do_vfs_init(lp_vfsobj(SNUM(conn)));
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
check if a vfs file exists
|
||||
********************************************************************/
|
||||
BOOL vfs_file_exist(connection_struct *conn,char *fname,SMB_STRUCT_STAT *sbuf)
|
||||
{
|
||||
SMB_STRUCT_STAT st;
|
||||
if (!sbuf) sbuf = &st;
|
||||
|
||||
if (conn->vfs_ops.stat(fname,sbuf) != 0)
|
||||
return(False);
|
||||
|
||||
return(S_ISREG(sbuf->st_mode));
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
read data from the client vfs, reading exactly N bytes.
|
||||
****************************************************************************/
|
||||
ssize_t vfs_read_data(files_struct *fsp,char *buffer,size_t N)
|
||||
{
|
||||
ssize_t ret;
|
||||
size_t total=0;
|
||||
int fd = fsp->fd_ptr->fd;
|
||||
extern int smb_read_error;
|
||||
|
||||
smb_read_error = 0;
|
||||
|
||||
while (total < N)
|
||||
{
|
||||
#ifdef WITH_SSL
|
||||
DEBUG(0, ("WARNING: read_data() called with SSL enabled\n"));
|
||||
if(fd == sslFd){
|
||||
ret = SSL_read(ssl, buffer + total, N - total);
|
||||
}else{
|
||||
ret = read(fd,buffer + total,N - total);
|
||||
}
|
||||
#else /* WITH_SSL */
|
||||
ret = fsp->conn->vfs_ops.read(fd,buffer + total,N - total);
|
||||
DEBUG(0, ("VFS_READ -> read %d/%d bytes\n", ret, N));
|
||||
#endif /* WITH_SSL */
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
smb_read_error = READ_EOF;
|
||||
return 0;
|
||||
}
|
||||
if (ret == -1)
|
||||
{
|
||||
smb_read_error = READ_ERROR;
|
||||
return -1;
|
||||
}
|
||||
total += ret;
|
||||
}
|
||||
return (ssize_t)total;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
write data to a fd on the vfs
|
||||
****************************************************************************/
|
||||
ssize_t vfs_write_data(files_struct *fsp,char *buffer,size_t N)
|
||||
{
|
||||
size_t total=0;
|
||||
ssize_t ret;
|
||||
int fd = fsp->fd_ptr->fd;
|
||||
|
||||
while (total < N)
|
||||
{
|
||||
#ifdef WITH_SSL
|
||||
DEBUG(0, ("WARNING: write_data called with SSL enabled\n"));
|
||||
if(fd == sslFd){
|
||||
ret = SSL_write(ssl,buffer + total,N - total);
|
||||
}else{
|
||||
ret = write(fd,buffer + total,N - total);
|
||||
}
|
||||
#else /* WITH_SSL */
|
||||
ret = fsp->conn->vfs_ops.write(fd,buffer + total,N - total);
|
||||
#endif /* WITH_SSL */
|
||||
|
||||
if (ret == -1) return -1;
|
||||
if (ret == 0) return total;
|
||||
|
||||
total += ret;
|
||||
}
|
||||
return (ssize_t)total;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
transfer some data between two file_struct's
|
||||
****************************************************************************/
|
||||
SMB_OFF_T vfs_transfer_file(int in_fd, files_struct *in_fsp,
|
||||
int out_fd, files_struct *out_fsp,
|
||||
SMB_OFF_T n, char *header, int headlen, int align)
|
||||
{
|
||||
static char *buf=NULL;
|
||||
static int size=0;
|
||||
char *buf1,*abuf;
|
||||
SMB_OFF_T total = 0;
|
||||
|
||||
DEBUG(4,("vfs_transfer_file n=%.0f (head=%d) called\n",(double)n,headlen));
|
||||
|
||||
/* Check we have at least somewhere to read from */
|
||||
|
||||
SMB_ASSERT((in_fd != -1) || (in_fsp != NULL));
|
||||
|
||||
if (size == 0) {
|
||||
size = lp_readsize();
|
||||
size = MAX(size,1024);
|
||||
}
|
||||
|
||||
while (!buf && size>0) {
|
||||
buf = (char *)Realloc(buf,size+8);
|
||||
if (!buf) size /= 2;
|
||||
}
|
||||
|
||||
if (!buf) {
|
||||
DEBUG(0,("Can't allocate transfer buffer!\n"));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
abuf = buf + (align%8);
|
||||
|
||||
if (header)
|
||||
n += headlen;
|
||||
|
||||
while (n > 0)
|
||||
{
|
||||
int s = (int)MIN(n,(SMB_OFF_T)size);
|
||||
int ret,ret2=0;
|
||||
|
||||
ret = 0;
|
||||
|
||||
if (header && (headlen >= MIN(s,1024))) {
|
||||
buf1 = header;
|
||||
s = headlen;
|
||||
ret = headlen;
|
||||
headlen = 0;
|
||||
header = NULL;
|
||||
} else {
|
||||
buf1 = abuf;
|
||||
}
|
||||
|
||||
if (header && headlen > 0)
|
||||
{
|
||||
ret = MIN(headlen,size);
|
||||
memcpy(buf1,header,ret);
|
||||
headlen -= ret;
|
||||
header += ret;
|
||||
if (headlen <= 0) header = NULL;
|
||||
}
|
||||
|
||||
if (s > ret) {
|
||||
ret += in_fsp ?
|
||||
in_fsp->conn->vfs_ops.read(in_fsp->fd_ptr->fd,buf1+ret,s-ret) : read(in_fd,buf1+ret,s-ret);
|
||||
}
|
||||
|
||||
if (ret > 0)
|
||||
{
|
||||
if (out_fsp) {
|
||||
ret2 = out_fsp->conn->vfs_ops.write(out_fsp->fd_ptr->fd,buf1,ret);
|
||||
} else {
|
||||
ret2= (out_fd != -1) ? write_data(out_fd,buf1,ret) : ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret2 > 0) total += ret2;
|
||||
/* if we can't write then dump excess data */
|
||||
if (ret2 != ret)
|
||||
vfs_transfer_file(in_fd, in_fsp, -1,NULL,n-(ret+headlen),NULL,0,0);
|
||||
|
||||
if (ret <= 0 || ret2 != ret)
|
||||
return(total);
|
||||
n -= ret;
|
||||
}
|
||||
return(total);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
a vfs_readdir wrapper which just returns the file name
|
||||
********************************************************************/
|
||||
char *vfs_readdirname(connection_struct *conn, void *p)
|
||||
{
|
||||
struct dirent *ptr;
|
||||
char *dname;
|
||||
|
||||
if (!p) return(NULL);
|
||||
|
||||
ptr = (struct dirent *)conn->vfs_ops.readdir(p);
|
||||
if (!ptr) return(NULL);
|
||||
|
||||
dname = ptr->d_name;
|
||||
|
||||
#ifdef NEXT2
|
||||
if (telldir(p) < 0) return(NULL);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_BROKEN_READDIR
|
||||
/* using /usr/ucb/cc is BAD */
|
||||
dname = dname - 2;
|
||||
#endif
|
||||
|
||||
{
|
||||
static pstring buf;
|
||||
memcpy(buf, dname, NAMLEN(ptr)+1);
|
||||
unix_to_dos(buf, True);
|
||||
dname = buf;
|
||||
}
|
||||
|
||||
unix_to_dos(dname, True);
|
||||
return(dname);
|
||||
}
|
Loading…
Reference in New Issue
Block a user