2 Unix SMB/Netbios implementation.
4 VFS initialisation and support functions
5 Copyright (C) Tim Potter 1999
6 Copyright (C) Alexander Bokovoy 2002
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This work was sponsored by Optifacio Software Services, Inc.
28 #define DBGC_CLASS DBGC_VFS
32 struct vfs_init_function_entry
{
34 vfs_op_tuple
*vfs_op_tuples
;
35 struct vfs_init_function_entry
*prev
, *next
;
38 static struct vfs_init_function_entry
*backends
= NULL
;
40 /* Some structures to help us initialise the vfs operations table */
47 /* Default vfs hooks. WARNING: The order of these initialisers is
48 very important. They must be in the same order as defined in
49 vfs.h. Change at your own peril. */
51 static struct vfs_ops default_vfs
= {
56 vfswrap_dummy_connect
,
57 vfswrap_dummy_disconnect
,
61 vfswrap_get_shadow_copy_data
,
64 /* Directory operations */
107 /* Windows ACL operations. */
113 /* POSIX ACL operations. */
117 vfswrap_sys_acl_get_entry
,
118 vfswrap_sys_acl_get_tag_type
,
119 vfswrap_sys_acl_get_permset
,
120 vfswrap_sys_acl_get_qualifier
,
121 vfswrap_sys_acl_get_file
,
122 vfswrap_sys_acl_get_fd
,
123 vfswrap_sys_acl_clear_perms
,
124 vfswrap_sys_acl_add_perm
,
125 vfswrap_sys_acl_to_text
,
126 vfswrap_sys_acl_init
,
127 vfswrap_sys_acl_create_entry
,
128 vfswrap_sys_acl_set_tag_type
,
129 vfswrap_sys_acl_set_qualifier
,
130 vfswrap_sys_acl_set_permset
,
131 vfswrap_sys_acl_valid
,
132 vfswrap_sys_acl_set_file
,
133 vfswrap_sys_acl_set_fd
,
134 vfswrap_sys_acl_delete_def_file
,
135 vfswrap_sys_acl_get_perm
,
136 vfswrap_sys_acl_free_text
,
137 vfswrap_sys_acl_free_acl
,
138 vfswrap_sys_acl_free_qualifier
,
148 vfswrap_lremovexattr
,
149 vfswrap_fremovexattr
,
154 /* AIO operations. */
165 /****************************************************************************
166 maintain the list of available backends
167 ****************************************************************************/
169 static struct vfs_init_function_entry
*vfs_find_backend_entry(const char *name
)
171 struct vfs_init_function_entry
*entry
= backends
;
174 if (strcmp(entry
->name
, name
)==0) return entry
;
181 NTSTATUS
smb_register_vfs(int version
, const char *name
, vfs_op_tuple
*vfs_op_tuples
)
183 struct vfs_init_function_entry
*entry
= backends
;
185 if ((version
!= SMB_VFS_INTERFACE_VERSION
)) {
186 DEBUG(0, ("Failed to register vfs module.\n"
187 "The module was compiled against SMB_VFS_INTERFACE_VERSION %d,\n"
188 "current SMB_VFS_INTERFACE_VERSION is %d.\n"
189 "Please recompile against the current Samba Version!\n",
190 version
, SMB_VFS_INTERFACE_VERSION
));
191 return NT_STATUS_OBJECT_TYPE_MISMATCH
;
194 if (!name
|| !name
[0] || !vfs_op_tuples
) {
195 DEBUG(0,("smb_register_vfs() called with NULL pointer or empty name!\n"));
196 return NT_STATUS_INVALID_PARAMETER
;
199 if (vfs_find_backend_entry(name
)) {
200 DEBUG(0,("VFS module %s already loaded!\n", name
));
201 return NT_STATUS_OBJECT_NAME_COLLISION
;
204 entry
= SMB_XMALLOC_P(struct vfs_init_function_entry
);
205 entry
->name
= smb_xstrdup(name
);
206 entry
->vfs_op_tuples
= vfs_op_tuples
;
208 DLIST_ADD(backends
, entry
);
209 DEBUG(5, ("Successfully added vfs backend '%s'\n", name
));
213 /****************************************************************************
214 initialise default vfs hooks
215 ****************************************************************************/
217 static void vfs_init_default(connection_struct
*conn
)
219 DEBUG(3, ("Initialising default vfs hooks\n"));
221 memcpy(&conn
->vfs
.ops
, &default_vfs
.ops
, sizeof(default_vfs
.ops
));
222 memcpy(&conn
->vfs_opaque
.ops
, &default_vfs
.ops
, sizeof(default_vfs
.ops
));
225 /****************************************************************************
226 initialise custom vfs hooks
227 ****************************************************************************/
229 BOOL
vfs_init_custom(connection_struct
*conn
, const char *vfs_object
)
232 char *module_name
= NULL
;
233 char *module_param
= NULL
, *p
;
235 vfs_handle_struct
*handle
;
236 struct vfs_init_function_entry
*entry
;
238 if (!conn
||!vfs_object
||!vfs_object
[0]) {
239 DEBUG(0,("vfs_init_custon() called with NULL pointer or emtpy vfs_object!\n"));
247 DEBUG(3, ("Initialising custom vfs hooks from [%s]\n", vfs_object
));
249 module_name
= smb_xstrdup(vfs_object
);
251 p
= strchr_m(module_name
, ':');
256 trim_char(module_param
, ' ', ' ');
259 trim_char(module_name
, ' ', ' ');
261 /* First, try to load the module with the new module system */
262 if((entry
= vfs_find_backend_entry(module_name
)) ||
263 (NT_STATUS_IS_OK(smb_probe_module("vfs", module_name
)) &&
264 (entry
= vfs_find_backend_entry(module_name
)))) {
266 DEBUGADD(5,("Successfully loaded vfs module [%s] with the new modules system\n", vfs_object
));
268 if ((ops
= entry
->vfs_op_tuples
) == NULL
) {
269 DEBUG(0, ("entry->vfs_op_tuples==NULL for [%s] failed\n", vfs_object
));
270 SAFE_FREE(module_name
);
274 DEBUG(0,("Can't find a vfs module [%s]\n",vfs_object
));
275 SAFE_FREE(module_name
);
279 handle
= TALLOC_ZERO_P(conn
->mem_ctx
,vfs_handle_struct
);
281 DEBUG(0,("talloc_zero() failed!\n"));
282 SAFE_FREE(module_name
);
285 memcpy(&handle
->vfs_next
, &conn
->vfs
, sizeof(struct vfs_ops
));
288 handle
->param
= talloc_strdup(conn
->mem_ctx
, module_param
);
290 DLIST_ADD(conn
->vfs_handles
, handle
);
292 for(i
=0; ops
[i
].op
!= NULL
; i
++) {
293 DEBUG(5, ("Checking operation #%d (type %d, layer %d)\n", i
, ops
[i
].type
, ops
[i
].layer
));
294 if(ops
[i
].layer
== SMB_VFS_LAYER_OPAQUE
) {
295 /* Check whether this operation was already made opaque by different module */
296 if(((void**)&conn
->vfs_opaque
.ops
)[ops
[i
].type
] == ((void**)&default_vfs
.ops
)[ops
[i
].type
]) {
297 /* No, it isn't overloaded yet. Overload. */
298 DEBUGADD(5, ("Making operation type %d opaque [module %s]\n", ops
[i
].type
, vfs_object
));
299 ((void**)&conn
->vfs_opaque
.ops
)[ops
[i
].type
] = ops
[i
].op
;
300 ((vfs_handle_struct
**)&conn
->vfs_opaque
.handles
)[ops
[i
].type
] = handle
;
303 /* Change current VFS disposition*/
304 DEBUGADD(5, ("Accepting operation type %d from module %s\n", ops
[i
].type
, vfs_object
));
305 ((void**)&conn
->vfs
.ops
)[ops
[i
].type
] = ops
[i
].op
;
306 ((vfs_handle_struct
**)&conn
->vfs
.handles
)[ops
[i
].type
] = handle
;
309 SAFE_FREE(module_name
);
313 /*****************************************************************
315 ******************************************************************/
317 BOOL
smbd_vfs_init(connection_struct
*conn
)
319 const char **vfs_objects
;
323 /* Normal share - initialise with disk access functions */
324 vfs_init_default(conn
);
325 vfs_objects
= lp_vfs_objects(SNUM(conn
));
327 /* Override VFS functions if 'vfs object' was not specified*/
328 if (!vfs_objects
|| !vfs_objects
[0])
331 for (i
=0; vfs_objects
[i
] ;) {
335 for (j
=i
-1; j
>= 0; j
--) {
336 if (!vfs_init_custom(conn
, vfs_objects
[j
])) {
337 DEBUG(0, ("smbd_vfs_init: vfs_init_custom failed for %s\n", vfs_objects
[j
]));
344 /*******************************************************************
345 Check if directory exists.
346 ********************************************************************/
348 BOOL
vfs_directory_exist(connection_struct
*conn
, const char *dname
, SMB_STRUCT_STAT
*st
)
356 if (SMB_VFS_STAT(conn
,dname
,st
) != 0)
359 ret
= S_ISDIR(st
->st_mode
);
366 /*******************************************************************
368 ********************************************************************/
370 int vfs_MkDir(connection_struct
*conn
, const char *name
, mode_t mode
)
373 SMB_STRUCT_STAT sbuf
;
375 if(!(ret
=SMB_VFS_MKDIR(conn
, name
, mode
))) {
377 inherit_access_acl(conn
, name
, mode
);
380 * Check if high bits should have been set,
381 * then (if bits are missing): add them.
382 * Consider bits automagically set by UNIX, i.e. SGID bit from parent dir.
384 if(mode
& ~(S_IRWXU
|S_IRWXG
|S_IRWXO
) &&
385 !SMB_VFS_STAT(conn
,name
,&sbuf
) && (mode
& ~sbuf
.st_mode
))
386 SMB_VFS_CHMOD(conn
,name
,sbuf
.st_mode
| (mode
& ~sbuf
.st_mode
));
391 /*******************************************************************
392 Check if an object exists in the vfs.
393 ********************************************************************/
395 BOOL
vfs_object_exist(connection_struct
*conn
,const char *fname
,SMB_STRUCT_STAT
*sbuf
)
404 if (SMB_VFS_STAT(conn
,fname
,sbuf
) == -1)
409 /*******************************************************************
410 Check if a file exists in the vfs.
411 ********************************************************************/
413 BOOL
vfs_file_exist(connection_struct
*conn
, const char *fname
,SMB_STRUCT_STAT
*sbuf
)
422 if (SMB_VFS_STAT(conn
,fname
,sbuf
) == -1)
424 return(S_ISREG(sbuf
->st_mode
));
427 /****************************************************************************
428 Read data from fsp on the vfs. (note: EINTR re-read differs from vfs_write_data)
429 ****************************************************************************/
431 ssize_t
vfs_read_data(files_struct
*fsp
, char *buf
, size_t byte_count
)
435 while (total
< byte_count
)
437 ssize_t ret
= SMB_VFS_READ(fsp
, fsp
->fh
->fd
, buf
+ total
,
440 if (ret
== 0) return total
;
449 return (ssize_t
)total
;
452 ssize_t
vfs_pread_data(files_struct
*fsp
, char *buf
,
453 size_t byte_count
, SMB_OFF_T offset
)
457 while (total
< byte_count
)
459 ssize_t ret
= SMB_VFS_PREAD(fsp
, fsp
->fh
->fd
, buf
+ total
,
460 byte_count
- total
, offset
+ total
);
462 if (ret
== 0) return total
;
471 return (ssize_t
)total
;
474 /****************************************************************************
475 Write data to a fd on the vfs.
476 ****************************************************************************/
478 ssize_t
vfs_write_data(files_struct
*fsp
,const char *buffer
,size_t N
)
484 ret
= SMB_VFS_WRITE(fsp
,fsp
->fh
->fd
,buffer
+ total
,N
- total
);
493 return (ssize_t
)total
;
496 ssize_t
vfs_pwrite_data(files_struct
*fsp
,const char *buffer
,
497 size_t N
, SMB_OFF_T offset
)
503 ret
= SMB_VFS_PWRITE(fsp
, fsp
->fh
->fd
, buffer
+ total
,
504 N
- total
, offset
+ total
);
513 return (ssize_t
)total
;
515 /****************************************************************************
516 An allocate file space call using the vfs interface.
517 Allocates space for a file from a filedescriptor.
518 Returns 0 on success, -1 on failure.
519 ****************************************************************************/
521 int vfs_allocate_file_space(files_struct
*fsp
, SMB_BIG_UINT len
)
525 connection_struct
*conn
= fsp
->conn
;
526 SMB_BIG_UINT space_avail
;
527 SMB_BIG_UINT bsize
,dfree
,dsize
;
529 release_level_2_oplocks_on_change(fsp
);
532 * Actually try and commit the space on disk....
535 DEBUG(10,("vfs_allocate_file_space: file %s, len %.0f\n", fsp
->fsp_name
, (double)len
));
537 if (((SMB_OFF_T
)len
) < 0) {
538 DEBUG(0,("vfs_allocate_file_space: %s negative len requested.\n", fsp
->fsp_name
));
542 ret
= SMB_VFS_FSTAT(fsp
,fsp
->fh
->fd
,&st
);
546 if (len
== (SMB_BIG_UINT
)st
.st_size
)
549 if (len
< (SMB_BIG_UINT
)st
.st_size
) {
550 /* Shrink - use ftruncate. */
552 DEBUG(10,("vfs_allocate_file_space: file %s, shrink. Current size %.0f\n",
553 fsp
->fsp_name
, (double)st
.st_size
));
555 flush_write_cache(fsp
, SIZECHANGE_FLUSH
);
556 if ((ret
= SMB_VFS_FTRUNCATE(fsp
, fsp
->fh
->fd
, (SMB_OFF_T
)len
)) != -1) {
557 set_filelen_write_cache(fsp
, len
);
562 /* Grow - we need to test if we have enough space. */
564 if (!lp_strict_allocate(SNUM(fsp
->conn
)))
568 len
/= 1024; /* Len is now number of 1k blocks needed. */
569 space_avail
= get_dfree_info(conn
,fsp
->fsp_name
,False
,&bsize
,&dfree
,&dsize
);
570 if (space_avail
== (SMB_BIG_UINT
)-1) {
574 DEBUG(10,("vfs_allocate_file_space: file %s, grow. Current size %.0f, needed blocks = %.0f, space avail = %.0f\n",
575 fsp
->fsp_name
, (double)st
.st_size
, (double)len
, (double)space_avail
));
577 if (len
> space_avail
) {
585 /****************************************************************************
586 A vfs set_filelen call.
587 set the length of a file from a filedescriptor.
588 Returns 0 on success, -1 on failure.
589 ****************************************************************************/
591 int vfs_set_filelen(files_struct
*fsp
, SMB_OFF_T len
)
595 release_level_2_oplocks_on_change(fsp
);
596 DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n", fsp
->fsp_name
, (double)len
));
597 flush_write_cache(fsp
, SIZECHANGE_FLUSH
);
598 if ((ret
= SMB_VFS_FTRUNCATE(fsp
, fsp
->fh
->fd
, len
)) != -1)
599 set_filelen_write_cache(fsp
, len
);
604 /****************************************************************************
605 A vfs fill sparse call.
606 Writes zeros from the end of file to len, if len is greater than EOF.
607 Used only by strict_sync.
608 Returns 0 on success, -1 on failure.
609 ****************************************************************************/
611 static char *sparse_buf
;
612 #define SPARSE_BUF_WRITE_SIZE (32*1024)
614 int vfs_fill_sparse(files_struct
*fsp
, SMB_OFF_T len
)
623 release_level_2_oplocks_on_change(fsp
);
624 ret
= SMB_VFS_FSTAT(fsp
,fsp
->fh
->fd
,&st
);
629 if (len
<= st
.st_size
) {
633 DEBUG(10,("vfs_fill_sparse: write zeros in file %s from len %.0f to len %.0f (%.0f bytes)\n",
634 fsp
->fsp_name
, (double)st
.st_size
, (double)len
, (double)(len
- st
.st_size
)));
636 flush_write_cache(fsp
, SIZECHANGE_FLUSH
);
639 sparse_buf
= SMB_CALLOC_ARRAY(char, SPARSE_BUF_WRITE_SIZE
);
647 num_to_write
= len
- st
.st_size
;
650 while (total
< num_to_write
) {
651 size_t curr_write_size
= MIN(SPARSE_BUF_WRITE_SIZE
, (num_to_write
- total
));
653 pwrite_ret
= SMB_VFS_PWRITE(fsp
, fsp
->fh
->fd
, sparse_buf
, curr_write_size
, offset
+ total
);
654 if (pwrite_ret
== -1) {
655 DEBUG(10,("vfs_fill_sparse: SMB_VFS_PWRITE for file %s failed with error %s\n",
656 fsp
->fsp_name
, strerror(errno
) ));
659 if (pwrite_ret
== 0) {
666 set_filelen_write_cache(fsp
, len
);
670 /****************************************************************************
671 Transfer some data (n bytes) between two file_struct's.
672 ****************************************************************************/
674 static files_struct
*in_fsp
;
675 static files_struct
*out_fsp
;
677 static ssize_t
read_fn(int fd
, void *buf
, size_t len
)
679 return SMB_VFS_READ(in_fsp
, fd
, buf
, len
);
682 static ssize_t
write_fn(int fd
, const void *buf
, size_t len
)
684 return SMB_VFS_WRITE(out_fsp
, fd
, buf
, len
);
687 SMB_OFF_T
vfs_transfer_file(files_struct
*in
, files_struct
*out
, SMB_OFF_T n
)
692 return transfer_file_internal(in_fsp
->fh
->fd
, out_fsp
->fh
->fd
, n
, read_fn
, write_fn
);
695 /*******************************************************************
696 A vfs_readdir wrapper which just returns the file name.
697 ********************************************************************/
699 char *vfs_readdirname(connection_struct
*conn
, void *p
)
701 SMB_STRUCT_DIRENT
*ptr
= NULL
;
707 ptr
= SMB_VFS_READDIR(conn
,p
);
718 #ifdef HAVE_BROKEN_READDIR_NAME
719 /* using /usr/ucb/cc is BAD */
726 /*******************************************************************
727 A wrapper for vfs_chdir().
728 ********************************************************************/
730 int vfs_ChDir(connection_struct
*conn
, const char *path
)
733 static pstring LastDir
="";
735 if (strcsequal(path
,"."))
738 if (*path
== '/' && strcsequal(LastDir
,path
))
741 DEBUG(4,("vfs_ChDir to %s\n",path
));
743 res
= SMB_VFS_CHDIR(conn
,path
);
745 pstrcpy(LastDir
,path
);
749 /* number of list structures for a caching GetWd function. */
750 #define MAX_GETWDCACHE (50)
753 SMB_DEV_T dev
; /* These *must* be compatible with the types returned in a stat() call. */
754 SMB_INO_T inode
; /* These *must* be compatible with the types returned in a stat() call. */
755 char *dos_path
; /* The pathname in DOS format. */
757 } ino_list
[MAX_GETWDCACHE
];
759 extern BOOL use_getwd_cache
;
761 /****************************************************************************
762 Prompte a ptr (to make it recently used)
763 ****************************************************************************/
765 static void array_promote(char *array
,int elsize
,int element
)
771 p
= (char *)SMB_MALLOC(elsize
);
774 DEBUG(5,("array_promote: malloc fail\n"));
778 memcpy(p
,array
+ element
* elsize
, elsize
);
779 memmove(array
+ elsize
,array
,elsize
*element
);
780 memcpy(array
,p
,elsize
);
784 /*******************************************************************
785 Return the absolute current directory path - given a UNIX pathname.
786 Note that this path is returned in DOS format, not UNIX
787 format. Note this can be called with conn == NULL.
788 ********************************************************************/
790 char *vfs_GetWd(connection_struct
*conn
, char *path
)
793 static BOOL getwd_cache_init
= False
;
794 SMB_STRUCT_STAT st
, st2
;
799 if (!use_getwd_cache
)
800 return(SMB_VFS_GETWD(conn
,path
));
803 if (!getwd_cache_init
) {
804 getwd_cache_init
= True
;
805 for (i
=0;i
<MAX_GETWDCACHE
;i
++) {
806 string_set(&ino_list
[i
].dos_path
,"");
807 ino_list
[i
].valid
= False
;
811 /* Get the inode of the current directory, if this doesn't work we're
814 if (SMB_VFS_STAT(conn
, ".",&st
) == -1) {
815 /* Known to fail for root: the directory may be
816 * NFS-mounted and exported with root_squash (so has no root access). */
817 DEBUG(1,("vfs_GetWd: couldn't stat \".\" path=%s error %s (NFS problem ?)\n", path
, strerror(errno
) ));
818 return(SMB_VFS_GETWD(conn
,path
));
822 for (i
=0; i
<MAX_GETWDCACHE
; i
++) {
823 if (ino_list
[i
].valid
) {
825 /* If we have found an entry with a matching inode and dev number
826 then find the inode number for the directory in the cached string.
827 If this agrees with that returned by the stat for the current
828 directory then all is o.k. (but make sure it is a directory all
831 if (st
.st_ino
== ino_list
[i
].inode
&& st
.st_dev
== ino_list
[i
].dev
) {
832 if (SMB_VFS_STAT(conn
,ino_list
[i
].dos_path
,&st2
) == 0) {
833 if (st
.st_ino
== st2
.st_ino
&& st
.st_dev
== st2
.st_dev
&&
834 (st2
.st_mode
& S_IFMT
) == S_IFDIR
) {
835 pstrcpy (path
, ino_list
[i
].dos_path
);
837 /* promote it for future use */
838 array_promote((char *)&ino_list
[0],sizeof(ino_list
[0]),i
);
841 /* If the inode is different then something's changed,
842 scrub the entry and start from scratch. */
843 ino_list
[i
].valid
= False
;
850 /* We don't have the information to hand so rely on traditional methods.
851 The very slow getcwd, which spawns a process on some systems, or the
852 not quite so bad getwd. */
854 if (!SMB_VFS_GETWD(conn
,s
)) {
855 DEBUG(0,("vfs_GetWd: SMB_VFS_GETWD call failed, errno %s\n",strerror(errno
)));
861 DEBUG(5,("vfs_GetWd %s, inode %.0f, dev %.0f\n",s
,(double)st
.st_ino
,(double)st
.st_dev
));
863 /* add it to the cache */
864 i
= MAX_GETWDCACHE
- 1;
865 string_set(&ino_list
[i
].dos_path
,s
);
866 ino_list
[i
].dev
= st
.st_dev
;
867 ino_list
[i
].inode
= st
.st_ino
;
868 ino_list
[i
].valid
= True
;
870 /* put it at the top of the list */
871 array_promote((char *)&ino_list
[0],sizeof(ino_list
[0]),i
);
876 BOOL
canonicalize_path(connection_struct
*conn
, pstring path
)
878 #ifdef REALPATH_TAKES_NULL
879 char *resolved_name
= SMB_VFS_REALPATH(conn
,path
,NULL
);
880 if (!resolved_name
) {
883 pstrcpy(path
, resolved_name
);
884 SAFE_FREE(resolved_name
);
888 char resolved_name_buf
[PATH_MAX
+1];
890 pstring resolved_name_buf
;
892 char *resolved_name
= SMB_VFS_REALPATH(conn
,path
,resolved_name_buf
);
893 if (!resolved_name
) {
896 pstrcpy(path
, resolved_name
);
898 #endif /* REALPATH_TAKES_NULL */
901 /*******************************************************************
902 Reduce a file name, removing .. elements and checking that
903 it is below dir in the heirachy. This uses realpath.
904 ********************************************************************/
906 BOOL
reduce_name(connection_struct
*conn
, const pstring fname
)
908 #ifdef REALPATH_TAKES_NULL
909 BOOL free_resolved_name
= True
;
912 char resolved_name_buf
[PATH_MAX
+1];
914 pstring resolved_name_buf
;
916 BOOL free_resolved_name
= False
;
918 char *resolved_name
= NULL
;
919 size_t con_path_len
= strlen(conn
->connectpath
);
921 int saved_errno
= errno
;
923 DEBUG(3,("reduce_name [%s] [%s]\n", fname
, conn
->connectpath
));
925 #ifdef REALPATH_TAKES_NULL
926 resolved_name
= SMB_VFS_REALPATH(conn
,fname
,NULL
);
928 resolved_name
= SMB_VFS_REALPATH(conn
,fname
,resolved_name_buf
);
931 if (!resolved_name
) {
934 DEBUG(3,("reduce_name: Component not a directory in getting realpath for %s\n", fname
));
940 fstring last_component
;
941 /* Last component didn't exist. Remove it and try and canonicalise the directory. */
943 pstrcpy(tmp_fname
, fname
);
944 p
= strrchr_m(tmp_fname
, '/');
947 fstrcpy(last_component
, p
);
949 fstrcpy(last_component
, tmp_fname
);
950 pstrcpy(tmp_fname
, ".");
953 #ifdef REALPATH_TAKES_NULL
954 resolved_name
= SMB_VFS_REALPATH(conn
,tmp_fname
,NULL
);
956 resolved_name
= SMB_VFS_REALPATH(conn
,tmp_fname
,resolved_name_buf
);
958 if (!resolved_name
) {
959 DEBUG(3,("reduce_name: couldn't get realpath for %s\n", fname
));
963 pstrcpy(tmp_fname
, resolved_name
);
964 pstrcat(tmp_fname
, "/");
965 pstrcat(tmp_fname
, last_component
);
966 #ifdef REALPATH_TAKES_NULL
967 SAFE_FREE(resolved_name
);
968 resolved_name
= SMB_STRDUP(tmp_fname
);
969 if (!resolved_name
) {
970 DEBUG(0,("reduce_name: malloc fail for %s\n", tmp_fname
));
976 safe_strcpy(resolved_name_buf
, tmp_fname
, PATH_MAX
);
978 pstrcpy(resolved_name_buf
, tmp_fname
);
980 resolved_name
= resolved_name_buf
;
985 DEBUG(1,("reduce_name: couldn't get realpath for %s\n", fname
));
986 /* Don't restore the saved errno. We need to return the error that
987 realpath caused here as it was not one of the cases we handle. JRA. */
992 DEBUG(10,("reduce_name realpath [%s] -> [%s]\n", fname
, resolved_name
));
994 if (*resolved_name
!= '/') {
995 DEBUG(0,("reduce_name: realpath doesn't return absolute paths !\n"));
996 if (free_resolved_name
)
997 SAFE_FREE(resolved_name
);
1002 /* Check for widelinks allowed. */
1003 if (!lp_widelinks(SNUM(conn
)) && (strncmp(conn
->connectpath
, resolved_name
, con_path_len
) != 0)) {
1004 DEBUG(2, ("reduce_name: Bad access attempt: %s is a symlink outside the share path", fname
));
1005 if (free_resolved_name
)
1006 SAFE_FREE(resolved_name
);
1011 /* Check if we are allowing users to follow symlinks */
1012 /* Patch from David Clerc <David.Clerc@cui.unige.ch>
1013 University of Geneva */
1016 if (!lp_symlinks(SNUM(conn
))) {
1017 SMB_STRUCT_STAT statbuf
;
1018 if ( (SMB_VFS_LSTAT(conn
,fname
,&statbuf
) != -1) &&
1019 (S_ISLNK(statbuf
.st_mode
)) ) {
1020 if (free_resolved_name
)
1021 SAFE_FREE(resolved_name
);
1022 DEBUG(3,("reduce_name: denied: file path name %s is a symlink\n",resolved_name
));
1029 DEBUG(3,("reduce_name: %s reduced to %s\n", fname
, resolved_name
));
1030 if (free_resolved_name
)
1031 SAFE_FREE(resolved_name
);
1032 errno
= saved_errno
;