2 Unix SMB/Netbios implementation.
4 VFS initialisation and support functions
5 Copyright (C) Tim Potter 1999
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 extern int DEBUGLEVEL;
26 /* Some structures to help us initialise the vfs operations table */
33 /* Default vfs hooks. WARNING: The order of these initialisers is
34 very important. They must be in the same order as defined in
35 vfs.h. Change at your own peril. */
37 struct vfs_ops default_vfs_ops = {
41 vfswrap_dummy_connect,
42 vfswrap_dummy_disconnect,
45 /* Directory operations */
70 /****************************************************************************
71 initialise default vfs hooks
72 ****************************************************************************/
73 int vfs_init_default(connection_struct *conn)
75 DEBUG(3, ("Initialising default vfs hooks\n"));
77 memcpy(&conn->vfs_ops, &default_vfs_ops, sizeof(conn->vfs_ops));
81 /****************************************************************************
82 initialise custom vfs hooks
83 ****************************************************************************/
85 BOOL vfs_init_custom(connection_struct *conn)
88 struct vfs_ops *ops, *(*fptr)(struct vfs_options *options);
90 DEBUG(3, ("Initialising custom vfs hooks from %s\n",
91 lp_vfsobj(SNUM(conn))));
93 /* Open object file */
95 handle = dlopen(lp_vfsobj(SNUM(conn)), RTLD_NOW | RTLD_GLOBAL);
96 conn->vfs_conn->dl_handle = handle;
99 DEBUG(0, ("Error opening %s: %s\n", lp_vfsobj(SNUM(conn)),
104 /* Get handle on vfs_init() symbol */
106 fptr = dlsym(handle, "vfs_init");
109 DEBUG(0, ("No vfs_init() symbol found in %s\n",
110 lp_vfsobj(SNUM(conn))));
114 /* Initialise vfs_ops structure */
116 if ((ops = fptr(NULL)) == NULL) {
117 DEBUG(0, ("vfs_init function from %s failed\n", lp_vfsobj(SNUM(conn))));
121 /* Fill in unused operations with default (disk based) ones.
122 There's probably a neater way to do this then a whole bunch of
125 memcpy(&conn->vfs_ops, ops, sizeof(conn->vfs_ops));
127 if (conn->vfs_ops.connect == NULL) {
128 conn->vfs_ops.connect = default_vfs_ops.connect;
131 if (conn->vfs_ops.disconnect == NULL) {
132 conn->vfs_ops.disconnect = default_vfs_ops.disconnect;
135 if (conn->vfs_ops.disk_free == NULL) {
136 conn->vfs_ops.disk_free = default_vfs_ops.disk_free;
139 if (conn->vfs_ops.opendir == NULL) {
140 conn->vfs_ops.opendir = default_vfs_ops.opendir;
143 if (conn->vfs_ops.readdir == NULL) {
144 conn->vfs_ops.readdir = default_vfs_ops.readdir;
147 if (conn->vfs_ops.mkdir == NULL) {
148 conn->vfs_ops.mkdir = default_vfs_ops.mkdir;
151 if (conn->vfs_ops.rmdir == NULL) {
152 conn->vfs_ops.rmdir = default_vfs_ops.rmdir;
155 if (conn->vfs_ops.closedir == NULL) {
156 conn->vfs_ops.closedir = default_vfs_ops.closedir;
159 if (conn->vfs_ops.open == NULL) {
160 conn->vfs_ops.open = default_vfs_ops.open;
163 if (conn->vfs_ops.close == NULL) {
164 conn->vfs_ops.close = default_vfs_ops.close;
167 if (conn->vfs_ops.read == NULL) {
168 conn->vfs_ops.read = default_vfs_ops.read;
171 if (conn->vfs_ops.write == NULL) {
172 conn->vfs_ops.write = default_vfs_ops.write;
175 if (conn->vfs_ops.lseek == NULL) {
176 conn->vfs_ops.lseek = default_vfs_ops.lseek;
179 if (conn->vfs_ops.rename == NULL) {
180 conn->vfs_ops.rename = default_vfs_ops.rename;
183 if (conn->vfs_ops.fsync == NULL) {
184 conn->vfs_ops.fsync = default_vfs_ops.fsync;
187 if (conn->vfs_ops.stat == NULL) {
188 conn->vfs_ops.stat = default_vfs_ops.stat;
191 if (conn->vfs_ops.fstat == NULL) {
192 conn->vfs_ops.fstat = default_vfs_ops.fstat;
195 if (conn->vfs_ops.lstat == NULL) {
196 conn->vfs_ops.lstat = default_vfs_ops.lstat;
199 if (conn->vfs_ops.unlink == NULL) {
200 conn->vfs_ops.unlink = default_vfs_ops.unlink;
203 if (conn->vfs_ops.chmod == NULL) {
204 conn->vfs_ops.chmod = default_vfs_ops.chmod;
207 if (conn->vfs_ops.utime == NULL) {
208 conn->vfs_ops.utime = default_vfs_ops.utime;
215 BOOL vfs_directory_exist(connection_struct *conn, char *dname,
223 if (conn->vfs_ops.stat(dname,st) != 0)
226 ret = S_ISDIR(st->st_mode);
233 /*******************************************************************
234 check if a vfs file exists
235 ********************************************************************/
236 BOOL vfs_file_exist(connection_struct *conn,char *fname,SMB_STRUCT_STAT *sbuf)
239 if (!sbuf) sbuf = &st;
241 if (conn->vfs_ops.stat(fname,sbuf) != 0)
244 return(S_ISREG(sbuf->st_mode));
247 /****************************************************************************
248 write data to a fd on the vfs
249 ****************************************************************************/
250 ssize_t vfs_write_data(files_struct *fsp,char *buffer,size_t N)
254 int fd = fsp->fd_ptr->fd;
258 ret = fsp->conn->vfs_ops.write(fd,buffer + total,N - total);
260 if (ret == -1) return -1;
261 if (ret == 0) return total;
265 return (ssize_t)total;
268 /****************************************************************************
269 transfer some data between two file_struct's
270 ****************************************************************************/
271 SMB_OFF_T vfs_transfer_file(int in_fd, files_struct *in_fsp,
272 int out_fd, files_struct *out_fsp,
273 SMB_OFF_T n, char *header, int headlen, int align)
275 static char *buf=NULL;
280 DEBUG(4,("vfs_transfer_file n=%.0f (head=%d) called\n",(double)n,headlen));
282 /* Check we have at least somewhere to read from */
284 SMB_ASSERT((in_fd != -1) || (in_fsp != NULL));
287 size = lp_readsize();
288 size = MAX(size,1024);
291 while (!buf && size>0) {
292 buf = (char *)Realloc(buf,size+8);
297 DEBUG(0,("Can't allocate transfer buffer!\n"));
301 abuf = buf + (align%8);
308 int s = (int)MIN(n,(SMB_OFF_T)size);
313 if (header && (headlen >= MIN(s,1024))) {
323 if (header && headlen > 0)
325 ret = MIN(headlen,size);
326 memcpy(buf1,header,ret);
329 if (headlen <= 0) header = NULL;
334 in_fsp->conn->vfs_ops.read(in_fsp->fd_ptr->fd,buf1+ret,s-ret) : read(in_fd,buf1+ret,s-ret);
340 ret2 = out_fsp->conn->vfs_ops.write(out_fsp->fd_ptr->fd,buf1,ret);
342 ret2= (out_fd != -1) ? write_data(out_fd,buf1,ret) : ret;
346 if (ret2 > 0) total += ret2;
347 /* if we can't write then dump excess data */
349 vfs_transfer_file(in_fd, in_fsp, -1,NULL,n-(ret+headlen),NULL,0,0);
351 if (ret <= 0 || ret2 != ret)
358 /*******************************************************************
359 a vfs_readdir wrapper which just returns the file name
360 ********************************************************************/
361 char *vfs_readdirname(connection_struct *conn, void *p)
366 if (!p) return(NULL);
368 ptr = (struct dirent *)conn->vfs_ops.readdir(p);
369 if (!ptr) return(NULL);
374 if (telldir(p) < 0) return(NULL);
377 #ifdef HAVE_BROKEN_READDIR
378 /* using /usr/ucb/cc is BAD */
384 memcpy(buf, dname, NAMLEN(ptr)+1);
385 unix_to_dos(buf, True);
389 unix_to_dos(dname, True);
393 /***************************************************************************
394 handle the interpretation of the vfs option parameter
395 *************************************************************************/
396 static BOOL handle_vfs_option(char *pszParmValue, char **ptr)
398 struct vfs_options *new_option, **options = (struct vfs_options **)ptr;
401 /* Create new vfs option */
403 new_option = (struct vfs_options *)malloc(sizeof(*new_option));
404 if (new_option == NULL) {
408 ZERO_STRUCTP(new_option);
410 /* Get name and value */
412 new_option->name = strtok(pszParmValue, "=");
414 if (new_option->name == NULL) {
418 while(isspace(*new_option->name)) {
422 for (i = strlen(new_option->name); i > 0; i--) {
423 if (!isspace(new_option->name[i - 1])) break;
426 new_option->name[i] = '\0';
427 new_option->name = strdup(new_option->name);
429 new_option->value = strtok(NULL, "=");
431 if (new_option->value != NULL) {
433 while(isspace(*new_option->value)) {
437 for (i = strlen(new_option->value); i > 0; i--) {
438 if (!isspace(new_option->value[i - 1])) break;
441 new_option->value[i] = '\0';
442 new_option->value = strdup(new_option->value);
447 DLIST_ADD(*options, new_option);