r8219: Merge the new open code from HEAD to 3.0. Haven't yet run the torture
[nivanova/samba-autobuild/.git] / source3 / smbd / vfs.c
1 /*
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    VFS initialisation and support functions
5    Copyright (C) Tim Potter 1999
6    Copyright (C) Alexander Bokovoy 2002
7
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.
12
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.
17
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.
21
22    This work was sponsored by Optifacio Software Services, Inc.
23 */
24
25 #include "includes.h"
26
27 #undef DBGC_CLASS
28 #define DBGC_CLASS DBGC_VFS
29
30 struct vfs_init_function_entry {
31         char *name;
32         vfs_op_tuple *vfs_op_tuples;
33         struct vfs_init_function_entry *prev, *next;
34 };
35
36 static struct vfs_init_function_entry *backends = NULL;
37
38 /* Some structures to help us initialise the vfs operations table */
39
40 struct vfs_syminfo {
41         char *name;
42         void *fptr;
43 };
44
45 /* Default vfs hooks.  WARNING: The order of these initialisers is
46    very important.  They must be in the same order as defined in
47    vfs.h.  Change at your own peril. */
48
49 static struct vfs_ops default_vfs = {
50
51         {
52                 /* Disk operations */
53         
54                 vfswrap_dummy_connect,
55                 vfswrap_dummy_disconnect,
56                 vfswrap_disk_free,
57                 vfswrap_get_quota,
58                 vfswrap_set_quota,
59                 vfswrap_get_shadow_copy_data,
60         
61                 /* Directory operations */
62         
63                 vfswrap_opendir,
64                 vfswrap_readdir,
65                 vfswrap_seekdir,
66                 vfswrap_telldir,
67                 vfswrap_rewinddir,
68                 vfswrap_mkdir,
69                 vfswrap_rmdir,
70                 vfswrap_closedir,
71         
72                 /* File operations */
73         
74                 vfswrap_open,
75                 vfswrap_close,
76                 vfswrap_read,
77                 vfswrap_pread,
78                 vfswrap_write,
79                 vfswrap_pwrite,
80                 vfswrap_lseek,
81                 vfswrap_sendfile,
82                 vfswrap_rename,
83                 vfswrap_fsync,
84                 vfswrap_stat,
85                 vfswrap_fstat,
86                 vfswrap_lstat,
87                 vfswrap_unlink,
88                 vfswrap_chmod,
89                 vfswrap_fchmod,
90                 vfswrap_chown,
91                 vfswrap_fchown,
92                 vfswrap_chdir,
93                 vfswrap_getwd,
94                 vfswrap_utime,
95                 vfswrap_ftruncate,
96                 vfswrap_lock,
97                 vfswrap_symlink,
98                 vfswrap_readlink,
99                 vfswrap_link,
100                 vfswrap_mknod,
101                 vfswrap_realpath,
102         
103                 /* Windows ACL operations. */
104                 vfswrap_fget_nt_acl,
105                 vfswrap_get_nt_acl,
106                 vfswrap_fset_nt_acl,
107                 vfswrap_set_nt_acl,
108         
109                 /* POSIX ACL operations. */
110                 vfswrap_chmod_acl,
111                 vfswrap_fchmod_acl,
112
113                 vfswrap_sys_acl_get_entry,
114                 vfswrap_sys_acl_get_tag_type,
115                 vfswrap_sys_acl_get_permset,
116                 vfswrap_sys_acl_get_qualifier,
117                 vfswrap_sys_acl_get_file,
118                 vfswrap_sys_acl_get_fd,
119                 vfswrap_sys_acl_clear_perms,
120                 vfswrap_sys_acl_add_perm,
121                 vfswrap_sys_acl_to_text,
122                 vfswrap_sys_acl_init,
123                 vfswrap_sys_acl_create_entry,
124                 vfswrap_sys_acl_set_tag_type,
125                 vfswrap_sys_acl_set_qualifier,
126                 vfswrap_sys_acl_set_permset,
127                 vfswrap_sys_acl_valid,
128                 vfswrap_sys_acl_set_file,
129                 vfswrap_sys_acl_set_fd,
130                 vfswrap_sys_acl_delete_def_file,
131                 vfswrap_sys_acl_get_perm,
132                 vfswrap_sys_acl_free_text,
133                 vfswrap_sys_acl_free_acl,
134                 vfswrap_sys_acl_free_qualifier,
135
136                 /* EA operations. */
137                 vfswrap_getxattr,
138                 vfswrap_lgetxattr,
139                 vfswrap_fgetxattr,
140                 vfswrap_listxattr,
141                 vfswrap_llistxattr,
142                 vfswrap_flistxattr,
143                 vfswrap_removexattr,
144                 vfswrap_lremovexattr,
145                 vfswrap_fremovexattr,
146                 vfswrap_setxattr,
147                 vfswrap_lsetxattr,
148                 vfswrap_fsetxattr,
149
150                 /* AIO operations. */
151                 vfswrap_aio_read,
152                 vfswrap_aio_write,
153                 vfswrap_aio_return,
154                 vfswrap_aio_cancel,
155                 vfswrap_aio_error,
156                 vfswrap_aio_fsync,
157                 vfswrap_aio_suspend
158         }
159 };
160
161 /****************************************************************************
162     maintain the list of available backends
163 ****************************************************************************/
164
165 static struct vfs_init_function_entry *vfs_find_backend_entry(const char *name)
166 {
167         struct vfs_init_function_entry *entry = backends;
168  
169         while(entry) {
170                 if (strcmp(entry->name, name)==0) return entry;
171                 entry = entry->next;
172         }
173
174         return NULL;
175 }
176
177 NTSTATUS smb_register_vfs(int version, const char *name, vfs_op_tuple *vfs_op_tuples)
178 {
179         struct vfs_init_function_entry *entry = backends;
180
181         if ((version != SMB_VFS_INTERFACE_VERSION)) {
182                 DEBUG(0, ("Failed to register vfs module.\n"
183                           "The module was compiled against SMB_VFS_INTERFACE_VERSION %d,\n"
184                           "current SMB_VFS_INTERFACE_VERSION is %d.\n"
185                           "Please recompile against the current Samba Version!\n",  
186                           version, SMB_VFS_INTERFACE_VERSION));
187                 return NT_STATUS_OBJECT_TYPE_MISMATCH;
188         }
189
190         if (!name || !name[0] || !vfs_op_tuples) {
191                 DEBUG(0,("smb_register_vfs() called with NULL pointer or empty name!\n"));
192                 return NT_STATUS_INVALID_PARAMETER;
193         }
194
195         if (vfs_find_backend_entry(name)) {
196                 DEBUG(0,("VFS module %s already loaded!\n", name));
197                 return NT_STATUS_OBJECT_NAME_COLLISION;
198         }
199
200         entry = SMB_XMALLOC_P(struct vfs_init_function_entry);
201         entry->name = smb_xstrdup(name);
202         entry->vfs_op_tuples = vfs_op_tuples;
203
204         DLIST_ADD(backends, entry);
205         DEBUG(5, ("Successfully added vfs backend '%s'\n", name));
206         return NT_STATUS_OK;
207 }
208
209 /****************************************************************************
210   initialise default vfs hooks
211 ****************************************************************************/
212
213 static void vfs_init_default(connection_struct *conn)
214 {
215         DEBUG(3, ("Initialising default vfs hooks\n"));
216
217         memcpy(&conn->vfs.ops, &default_vfs.ops, sizeof(default_vfs.ops));
218         memcpy(&conn->vfs_opaque.ops, &default_vfs.ops, sizeof(default_vfs.ops));
219 }
220
221 /****************************************************************************
222   initialise custom vfs hooks
223  ****************************************************************************/
224
225 BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object)
226 {
227         vfs_op_tuple *ops;
228         char *module_name = NULL;
229         char *module_param = NULL, *p;
230         int i;
231         vfs_handle_struct *handle;
232         struct vfs_init_function_entry *entry;
233         
234         if (!conn||!vfs_object||!vfs_object[0]) {
235                 DEBUG(0,("vfs_init_custon() called with NULL pointer or emtpy vfs_object!\n"));
236                 return False;
237         }
238
239         if(!backends) {
240                 static_init_vfs;
241         }
242
243         DEBUG(3, ("Initialising custom vfs hooks from [%s]\n", vfs_object));
244
245         module_name = smb_xstrdup(vfs_object);
246
247         p = strchr_m(module_name, ':');
248
249         if (p) {
250                 *p = 0;
251                 module_param = p+1;
252                 trim_char(module_param, ' ', ' ');
253         }
254
255         trim_char(module_name, ' ', ' ');
256
257         /* First, try to load the module with the new module system */
258         if((entry = vfs_find_backend_entry(module_name)) || 
259            (NT_STATUS_IS_OK(smb_probe_module("vfs", module_name)) && 
260                 (entry = vfs_find_backend_entry(module_name)))) {
261
262                 DEBUGADD(5,("Successfully loaded vfs module [%s] with the new modules system\n", vfs_object));
263                 
264                 if ((ops = entry->vfs_op_tuples) == NULL) {
265                         DEBUG(0, ("entry->vfs_op_tuples==NULL for [%s] failed\n", vfs_object));
266                         SAFE_FREE(module_name);
267                         return False;
268                 }
269         } else {
270                 DEBUG(0,("Can't find a vfs module [%s]\n",vfs_object));
271                 SAFE_FREE(module_name);
272                 return False;
273         }
274
275         handle = TALLOC_ZERO_P(conn->mem_ctx,vfs_handle_struct);
276         if (!handle) {
277                 DEBUG(0,("talloc_zero() failed!\n"));
278                 SAFE_FREE(module_name);
279                 return False;
280         }
281         memcpy(&handle->vfs_next, &conn->vfs, sizeof(struct vfs_ops));
282         handle->conn = conn;
283         if (module_param) {
284                 handle->param = talloc_strdup(conn->mem_ctx, module_param);
285         }
286         DLIST_ADD(conn->vfs_handles, handle);
287
288         for(i=0; ops[i].op != NULL; i++) {
289                 DEBUG(5, ("Checking operation #%d (type %d, layer %d)\n", i, ops[i].type, ops[i].layer));
290                 if(ops[i].layer == SMB_VFS_LAYER_OPAQUE) {
291                         /* Check whether this operation was already made opaque by different module */
292                         if(((void**)&conn->vfs_opaque.ops)[ops[i].type] == ((void**)&default_vfs.ops)[ops[i].type]) {
293                                 /* No, it isn't overloaded yet. Overload. */
294                                 DEBUGADD(5, ("Making operation type %d opaque [module %s]\n", ops[i].type, vfs_object));
295                                 ((void**)&conn->vfs_opaque.ops)[ops[i].type] = ops[i].op;
296                                 ((vfs_handle_struct **)&conn->vfs_opaque.handles)[ops[i].type] = handle;
297                         }
298                 }
299                 /* Change current VFS disposition*/
300                 DEBUGADD(5, ("Accepting operation type %d from module %s\n", ops[i].type, vfs_object));
301                 ((void**)&conn->vfs.ops)[ops[i].type] = ops[i].op;
302                 ((vfs_handle_struct **)&conn->vfs.handles)[ops[i].type] = handle;
303         }
304
305         SAFE_FREE(module_name);
306         return True;
307 }
308
309 /*****************************************************************
310  Generic VFS init.
311 ******************************************************************/
312
313 BOOL smbd_vfs_init(connection_struct *conn)
314 {
315         const char **vfs_objects;
316         unsigned int i = 0;
317         int j = 0;
318         
319         /* Normal share - initialise with disk access functions */
320         vfs_init_default(conn);
321         vfs_objects = lp_vfs_objects(SNUM(conn));
322
323         /* Override VFS functions if 'vfs object' was not specified*/
324         if (!vfs_objects || !vfs_objects[0])
325                 return True;
326         
327         for (i=0; vfs_objects[i] ;) {
328                 i++;
329         }
330
331         for (j=i-1; j >= 0; j--) {
332                 if (!vfs_init_custom(conn, vfs_objects[j])) {
333                         DEBUG(0, ("smbd_vfs_init: vfs_init_custom failed for %s\n", vfs_objects[j]));
334                         return False;
335                 }
336         }
337         return True;
338 }
339
340 /*******************************************************************
341  Check if directory exists.
342 ********************************************************************/
343
344 BOOL vfs_directory_exist(connection_struct *conn, const char *dname, SMB_STRUCT_STAT *st)
345 {
346         SMB_STRUCT_STAT st2;
347         BOOL ret;
348
349         if (!st)
350                 st = &st2;
351
352         if (SMB_VFS_STAT(conn,dname,st) != 0)
353                 return(False);
354
355         ret = S_ISDIR(st->st_mode);
356         if(!ret)
357                 errno = ENOTDIR;
358
359         return ret;
360 }
361
362 /*******************************************************************
363  vfs mkdir wrapper 
364 ********************************************************************/
365
366 int vfs_MkDir(connection_struct *conn, const char *name, mode_t mode)
367 {
368         int ret;
369         SMB_STRUCT_STAT sbuf;
370
371         if(!(ret=SMB_VFS_MKDIR(conn, name, mode))) {
372
373                 inherit_access_acl(conn, name, mode);
374
375                 /*
376                  * Check if high bits should have been set,
377                  * then (if bits are missing): add them.
378                  * Consider bits automagically set by UNIX, i.e. SGID bit from parent dir.
379                  */
380                 if(mode & ~(S_IRWXU|S_IRWXG|S_IRWXO) &&
381                                 !SMB_VFS_STAT(conn,name,&sbuf) && (mode & ~sbuf.st_mode))
382                         SMB_VFS_CHMOD(conn,name,sbuf.st_mode | (mode & ~sbuf.st_mode));
383         }
384         return ret;
385 }
386
387 /*******************************************************************
388  Check if an object exists in the vfs.
389 ********************************************************************/
390
391 BOOL vfs_object_exist(connection_struct *conn,const char *fname,SMB_STRUCT_STAT *sbuf)
392 {
393         SMB_STRUCT_STAT st;
394
395         if (!sbuf)
396                 sbuf = &st;
397
398         ZERO_STRUCTP(sbuf);
399
400         if (SMB_VFS_STAT(conn,fname,sbuf) == -1)
401                 return(False);
402         return True;
403 }
404
405 /*******************************************************************
406  Check if a file exists in the vfs.
407 ********************************************************************/
408
409 BOOL vfs_file_exist(connection_struct *conn, const char *fname,SMB_STRUCT_STAT *sbuf)
410 {
411         SMB_STRUCT_STAT st;
412
413         if (!sbuf)
414                 sbuf = &st;
415
416         ZERO_STRUCTP(sbuf);
417
418         if (SMB_VFS_STAT(conn,fname,sbuf) == -1)
419                 return False;
420         return(S_ISREG(sbuf->st_mode));
421 }
422
423 /****************************************************************************
424  Read data from fsp on the vfs. (note: EINTR re-read differs from vfs_write_data)
425 ****************************************************************************/
426
427 ssize_t vfs_read_data(files_struct *fsp, char *buf, size_t byte_count)
428 {
429         size_t total=0;
430
431         while (total < byte_count)
432         {
433                 ssize_t ret = SMB_VFS_READ(fsp, fsp->fh->fd, buf + total,
434                                         byte_count - total);
435
436                 if (ret == 0) return total;
437                 if (ret == -1) {
438                         if (errno == EINTR)
439                                 continue;
440                         else
441                                 return -1;
442                 }
443                 total += ret;
444         }
445         return (ssize_t)total;
446 }
447
448 ssize_t vfs_pread_data(files_struct *fsp, char *buf,
449                 size_t byte_count, SMB_OFF_T offset)
450 {
451         size_t total=0;
452
453         while (total < byte_count)
454         {
455                 ssize_t ret = SMB_VFS_PREAD(fsp, fsp->fh->fd, buf + total,
456                                         byte_count - total, offset + total);
457
458                 if (ret == 0) return total;
459                 if (ret == -1) {
460                         if (errno == EINTR)
461                                 continue;
462                         else
463                                 return -1;
464                 }
465                 total += ret;
466         }
467         return (ssize_t)total;
468 }
469
470 /****************************************************************************
471  Write data to a fd on the vfs.
472 ****************************************************************************/
473
474 ssize_t vfs_write_data(files_struct *fsp,const char *buffer,size_t N)
475 {
476         size_t total=0;
477         ssize_t ret;
478
479         while (total < N) {
480                 ret = SMB_VFS_WRITE(fsp,fsp->fh->fd,buffer + total,N - total);
481
482                 if (ret == -1)
483                         return -1;
484                 if (ret == 0)
485                         return total;
486
487                 total += ret;
488         }
489         return (ssize_t)total;
490 }
491
492 ssize_t vfs_pwrite_data(files_struct *fsp,const char *buffer,
493                 size_t N, SMB_OFF_T offset)
494 {
495         size_t total=0;
496         ssize_t ret;
497
498         while (total < N) {
499                 ret = SMB_VFS_PWRITE(fsp, fsp->fh->fd, buffer + total,
500                                 N - total, offset + total);
501
502                 if (ret == -1)
503                         return -1;
504                 if (ret == 0)
505                         return total;
506
507                 total += ret;
508         }
509         return (ssize_t)total;
510 }
511 /****************************************************************************
512  An allocate file space call using the vfs interface.
513  Allocates space for a file from a filedescriptor.
514  Returns 0 on success, -1 on failure.
515 ****************************************************************************/
516
517 int vfs_allocate_file_space(files_struct *fsp, SMB_BIG_UINT len)
518 {
519         int ret;
520         SMB_STRUCT_STAT st;
521         connection_struct *conn = fsp->conn;
522         SMB_BIG_UINT space_avail;
523         SMB_BIG_UINT bsize,dfree,dsize;
524
525         release_level_2_oplocks_on_change(fsp);
526
527         /*
528          * Actually try and commit the space on disk....
529          */
530
531         DEBUG(10,("vfs_allocate_file_space: file %s, len %.0f\n", fsp->fsp_name, (double)len ));
532
533         if (((SMB_OFF_T)len) < 0) {
534                 DEBUG(0,("vfs_allocate_file_space: %s negative len requested.\n", fsp->fsp_name ));
535                 return -1;
536         }
537
538         ret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st);
539         if (ret == -1)
540                 return ret;
541
542         if (len == (SMB_BIG_UINT)st.st_size)
543                 return 0;
544
545         if (len < (SMB_BIG_UINT)st.st_size) {
546                 /* Shrink - use ftruncate. */
547
548                 DEBUG(10,("vfs_allocate_file_space: file %s, shrink. Current size %.0f\n",
549                                 fsp->fsp_name, (double)st.st_size ));
550
551                 flush_write_cache(fsp, SIZECHANGE_FLUSH);
552                 if ((ret = SMB_VFS_FTRUNCATE(fsp, fsp->fh->fd, (SMB_OFF_T)len)) != -1) {
553                         set_filelen_write_cache(fsp, len);
554                 }
555                 return ret;
556         }
557
558         /* Grow - we need to test if we have enough space. */
559
560         if (!lp_strict_allocate(SNUM(fsp->conn)))
561                 return 0;
562
563         len -= st.st_size;
564         len /= 1024; /* Len is now number of 1k blocks needed. */
565         space_avail = SMB_VFS_DISK_FREE(conn,fsp->fsp_name,False,&bsize,&dfree,&dsize);
566         if (space_avail == (SMB_BIG_UINT)-1) {
567                 return -1;
568         }
569
570         DEBUG(10,("vfs_allocate_file_space: file %s, grow. Current size %.0f, needed blocks = %.0f, space avail = %.0f\n",
571                         fsp->fsp_name, (double)st.st_size, (double)len, (double)space_avail ));
572
573         if (len > space_avail) {
574                 errno = ENOSPC;
575                 return -1;
576         }
577
578         return 0;
579 }
580
581 /****************************************************************************
582  A vfs set_filelen call.
583  set the length of a file from a filedescriptor.
584  Returns 0 on success, -1 on failure.
585 ****************************************************************************/
586
587 int vfs_set_filelen(files_struct *fsp, SMB_OFF_T len)
588 {
589         int ret;
590
591         release_level_2_oplocks_on_change(fsp);
592         DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n", fsp->fsp_name, (double)len));
593         flush_write_cache(fsp, SIZECHANGE_FLUSH);
594         if ((ret = SMB_VFS_FTRUNCATE(fsp, fsp->fh->fd, len)) != -1)
595                 set_filelen_write_cache(fsp, len);
596
597         return ret;
598 }
599
600 /****************************************************************************
601  A vfs fill sparse call.
602  Writes zeros from the end of file to len, if len is greater than EOF.
603  Used only by strict_sync.
604  Returns 0 on success, -1 on failure.
605 ****************************************************************************/
606
607 static char *sparse_buf;
608 #define SPARSE_BUF_WRITE_SIZE (32*1024)
609
610 int vfs_fill_sparse(files_struct *fsp, SMB_OFF_T len)
611 {
612         int ret;
613         SMB_STRUCT_STAT st;
614         SMB_OFF_T offset;
615         size_t total;
616         size_t num_to_write;
617         ssize_t pwrite_ret;
618
619         release_level_2_oplocks_on_change(fsp);
620         ret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st);
621         if (ret == -1) {
622                 return ret;
623         }
624
625         if (len <= st.st_size) {
626                 return 0;
627         }
628
629         DEBUG(10,("vfs_fill_sparse: write zeros in file %s from len %.0f to len %.0f (%.0f bytes)\n",
630                 fsp->fsp_name, (double)st.st_size, (double)len, (double)(len - st.st_size)));
631
632         flush_write_cache(fsp, SIZECHANGE_FLUSH);
633
634         if (!sparse_buf) {
635                 sparse_buf = SMB_CALLOC_ARRAY(char, SPARSE_BUF_WRITE_SIZE);
636                 if (!sparse_buf) {
637                         errno = ENOMEM;
638                         return -1;
639                 }
640         }
641
642         offset = st.st_size;
643         num_to_write = len - st.st_size;
644         total = 0;
645
646         while (total < num_to_write) {
647                 size_t curr_write_size = MIN(SPARSE_BUF_WRITE_SIZE, (num_to_write - total));
648
649                 pwrite_ret = SMB_VFS_PWRITE(fsp, fsp->fh->fd, sparse_buf, curr_write_size, offset + total);
650                 if (pwrite_ret == -1) {
651                         DEBUG(10,("vfs_fill_sparse: SMB_VFS_PWRITE for file %s failed with error %s\n",
652                                 fsp->fsp_name, strerror(errno) ));
653                         return -1;
654                 }
655                 if (pwrite_ret == 0) {
656                         return 0;
657                 }
658
659                 total += pwrite_ret;
660         }
661
662         set_filelen_write_cache(fsp, len);
663         return 0;
664 }
665
666 /****************************************************************************
667  Transfer some data (n bytes) between two file_struct's.
668 ****************************************************************************/
669
670 static files_struct *in_fsp;
671 static files_struct *out_fsp;
672
673 static ssize_t read_fn(int fd, void *buf, size_t len)
674 {
675         return SMB_VFS_READ(in_fsp, fd, buf, len);
676 }
677
678 static ssize_t write_fn(int fd, const void *buf, size_t len)
679 {
680         return SMB_VFS_WRITE(out_fsp, fd, buf, len);
681 }
682
683 SMB_OFF_T vfs_transfer_file(files_struct *in, files_struct *out, SMB_OFF_T n)
684 {
685         in_fsp = in;
686         out_fsp = out;
687
688         return transfer_file_internal(in_fsp->fh->fd, out_fsp->fh->fd, n, read_fn, write_fn);
689 }
690
691 /*******************************************************************
692  A vfs_readdir wrapper which just returns the file name.
693 ********************************************************************/
694
695 char *vfs_readdirname(connection_struct *conn, void *p)
696 {
697         SMB_STRUCT_DIRENT *ptr= NULL;
698         char *dname;
699
700         if (!p)
701                 return(NULL);
702
703         ptr = SMB_VFS_READDIR(conn,p);
704         if (!ptr)
705                 return(NULL);
706
707         dname = ptr->d_name;
708
709 #ifdef NEXT2
710         if (telldir(p) < 0)
711                 return(NULL);
712 #endif
713
714 #ifdef HAVE_BROKEN_READDIR
715         /* using /usr/ucb/cc is BAD */
716         dname = dname - 2;
717 #endif
718
719         return(dname);
720 }
721
722 /*******************************************************************
723  A wrapper for vfs_chdir().
724 ********************************************************************/
725
726 int vfs_ChDir(connection_struct *conn, const char *path)
727 {
728         int res;
729         static pstring LastDir="";
730
731         if (strcsequal(path,"."))
732                 return(0);
733
734         if (*path == '/' && strcsequal(LastDir,path))
735                 return(0);
736
737         DEBUG(4,("vfs_ChDir to %s\n",path));
738
739         res = SMB_VFS_CHDIR(conn,path);
740         if (!res)
741                 pstrcpy(LastDir,path);
742         return(res);
743 }
744
745 /* number of list structures for a caching GetWd function. */
746 #define MAX_GETWDCACHE (50)
747
748 static struct {
749         SMB_DEV_T dev; /* These *must* be compatible with the types returned in a stat() call. */
750         SMB_INO_T inode; /* These *must* be compatible with the types returned in a stat() call. */
751         char *dos_path; /* The pathname in DOS format. */
752         BOOL valid;
753 } ino_list[MAX_GETWDCACHE];
754
755 extern BOOL use_getwd_cache;
756
757 /****************************************************************************
758  Prompte a ptr (to make it recently used)
759 ****************************************************************************/
760
761 static void array_promote(char *array,int elsize,int element)
762 {
763         char *p;
764         if (element == 0)
765                 return;
766
767         p = (char *)SMB_MALLOC(elsize);
768
769         if (!p) {
770                 DEBUG(5,("array_promote: malloc fail\n"));
771                 return;
772         }
773
774         memcpy(p,array + element * elsize, elsize);
775         memmove(array + elsize,array,elsize*element);
776         memcpy(array,p,elsize);
777         SAFE_FREE(p);
778 }
779
780 /*******************************************************************
781  Return the absolute current directory path - given a UNIX pathname.
782  Note that this path is returned in DOS format, not UNIX
783  format. Note this can be called with conn == NULL.
784 ********************************************************************/
785
786 char *vfs_GetWd(connection_struct *conn, char *path)
787 {
788         pstring s;
789         static BOOL getwd_cache_init = False;
790         SMB_STRUCT_STAT st, st2;
791         int i;
792
793         *s = 0;
794
795         if (!use_getwd_cache)
796                 return(SMB_VFS_GETWD(conn,path));
797
798         /* init the cache */
799         if (!getwd_cache_init) {
800                 getwd_cache_init = True;
801                 for (i=0;i<MAX_GETWDCACHE;i++) {
802                         string_set(&ino_list[i].dos_path,"");
803                         ino_list[i].valid = False;
804                 }
805         }
806
807         /*  Get the inode of the current directory, if this doesn't work we're
808                 in trouble :-) */
809
810         if (SMB_VFS_STAT(conn, ".",&st) == -1) {
811                 /* Known to fail for root: the directory may be
812                  * NFS-mounted and exported with root_squash (so has no root access). */
813                 DEBUG(1,("vfs_GetWd: couldn't stat \".\" path=%s error %s (NFS problem ?)\n", path, strerror(errno) ));
814                 return(SMB_VFS_GETWD(conn,path));
815         }
816
817
818         for (i=0; i<MAX_GETWDCACHE; i++) {
819                 if (ino_list[i].valid) {
820
821                         /*  If we have found an entry with a matching inode and dev number
822                                 then find the inode number for the directory in the cached string.
823                                 If this agrees with that returned by the stat for the current
824                                 directory then all is o.k. (but make sure it is a directory all
825                                 the same...) */
826
827                         if (st.st_ino == ino_list[i].inode && st.st_dev == ino_list[i].dev) {
828                                 if (SMB_VFS_STAT(conn,ino_list[i].dos_path,&st2) == 0) {
829                                         if (st.st_ino == st2.st_ino && st.st_dev == st2.st_dev &&
830                                                         (st2.st_mode & S_IFMT) == S_IFDIR) {
831                                                 pstrcpy (path, ino_list[i].dos_path);
832
833                                                 /* promote it for future use */
834                                                 array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i);
835                                                 return (path);
836                                         } else {
837                                                 /*  If the inode is different then something's changed,
838                                                         scrub the entry and start from scratch. */
839                                                 ino_list[i].valid = False;
840                                         }
841                                 }
842                         }
843                 }
844         }
845
846         /*  We don't have the information to hand so rely on traditional methods.
847                 The very slow getcwd, which spawns a process on some systems, or the
848                 not quite so bad getwd. */
849
850         if (!SMB_VFS_GETWD(conn,s)) {
851                 DEBUG(0,("vfs_GetWd: SMB_VFS_GETWD call failed, errno %s\n",strerror(errno)));
852                 return (NULL);
853         }
854
855         pstrcpy(path,s);
856
857         DEBUG(5,("vfs_GetWd %s, inode %.0f, dev %.0f\n",s,(double)st.st_ino,(double)st.st_dev));
858
859         /* add it to the cache */
860         i = MAX_GETWDCACHE - 1;
861         string_set(&ino_list[i].dos_path,s);
862         ino_list[i].dev = st.st_dev;
863         ino_list[i].inode = st.st_ino;
864         ino_list[i].valid = True;
865
866         /* put it at the top of the list */
867         array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i);
868
869         return (path);
870 }
871
872 BOOL canonicalize_path(connection_struct *conn, pstring path)
873 {
874 #ifdef REALPATH_TAKES_NULL
875         char *resolved_name = SMB_VFS_REALPATH(conn,path,NULL);
876         if (!resolved_name) {
877                 return False;
878         }
879         pstrcpy(path, resolved_name);
880         SAFE_FREE(resolved_name);
881         return True;
882 #else
883 #ifdef PATH_MAX
884         char resolved_name_buf[PATH_MAX+1];
885 #else
886         pstring resolved_name_buf;
887 #endif
888         char *resolved_name = SMB_VFS_REALPATH(conn,path,resolved_name_buf);
889         if (!resolved_name) {
890                 return False;
891         }
892         pstrcpy(path, resolved_name);
893         return True;
894 #endif /* REALPATH_TAKES_NULL */
895 }
896
897 /*******************************************************************
898  Reduce a file name, removing .. elements and checking that
899  it is below dir in the heirachy. This uses realpath.
900 ********************************************************************/
901
902 BOOL reduce_name(connection_struct *conn, const pstring fname)
903 {
904 #ifdef REALPATH_TAKES_NULL
905         BOOL free_resolved_name = True;
906 #else
907 #ifdef PATH_MAX
908         char resolved_name_buf[PATH_MAX+1];
909 #else
910         pstring resolved_name_buf;
911 #endif
912         BOOL free_resolved_name = False;
913 #endif
914         char *resolved_name = NULL;
915         size_t con_path_len = strlen(conn->connectpath);
916         char *p = NULL;
917         int saved_errno = errno;
918
919         DEBUG(3,("reduce_name [%s] [%s]\n", fname, conn->connectpath));
920
921 #ifdef REALPATH_TAKES_NULL
922         resolved_name = SMB_VFS_REALPATH(conn,fname,NULL);
923 #else
924         resolved_name = SMB_VFS_REALPATH(conn,fname,resolved_name_buf);
925 #endif
926
927         if (!resolved_name) {
928                 switch (errno) {
929                         case ENOTDIR:
930                                 DEBUG(3,("reduce_name: Component not a directory in getting realpath for %s\n", fname));
931                                 errno = saved_errno;
932                                 return False;
933                         case ENOENT:
934                         {
935                                 pstring tmp_fname;
936                                 fstring last_component;
937                                 /* Last component didn't exist. Remove it and try and canonicalise the directory. */
938
939                                 pstrcpy(tmp_fname, fname);
940                                 p = strrchr_m(tmp_fname, '/');
941                                 if (p) {
942                                         *p++ = '\0';
943                                         fstrcpy(last_component, p);
944                                 } else {
945                                         fstrcpy(last_component, tmp_fname);
946                                         pstrcpy(tmp_fname, ".");
947                                 }
948
949 #ifdef REALPATH_TAKES_NULL
950                                 resolved_name = SMB_VFS_REALPATH(conn,tmp_fname,NULL);
951 #else
952                                 resolved_name = SMB_VFS_REALPATH(conn,tmp_fname,resolved_name_buf);
953 #endif
954                                 if (!resolved_name) {
955                                         DEBUG(3,("reduce_name: couldn't get realpath for %s\n", fname));
956                                         errno = saved_errno;
957                                         return False;
958                                 }
959                                 pstrcpy(tmp_fname, resolved_name);
960                                 pstrcat(tmp_fname, "/");
961                                 pstrcat(tmp_fname, last_component);
962 #ifdef REALPATH_TAKES_NULL
963                                 SAFE_FREE(resolved_name);
964                                 resolved_name = SMB_STRDUP(tmp_fname);
965                                 if (!resolved_name) {
966                                         DEBUG(0,("reduce_name: malloc fail for %s\n", tmp_fname));
967                                         errno = saved_errno;
968                                         return False;
969                                 }
970 #else
971 #ifdef PATH_MAX
972                                 safe_strcpy(resolved_name_buf, tmp_fname, PATH_MAX);
973 #else
974                                 pstrcpy(resolved_name_buf, tmp_fname);
975 #endif
976                                 resolved_name = resolved_name_buf;
977 #endif
978                                 break;
979                         }
980                         default:
981                                 DEBUG(1,("reduce_name: couldn't get realpath for %s\n", fname));
982                                 /* Don't restore the saved errno. We need to return the error that
983                                    realpath caused here as it was not one of the cases we handle. JRA. */
984                                 return False;
985                 }
986         }
987
988         DEBUG(10,("reduce_name realpath [%s] -> [%s]\n", fname, resolved_name));
989
990         if (*resolved_name != '/') {
991                 DEBUG(0,("reduce_name: realpath doesn't return absolute paths !\n"));
992                 if (free_resolved_name)
993                         SAFE_FREE(resolved_name);
994                 errno = saved_errno;
995                 return False;
996         }
997
998         /* Check for widelinks allowed. */
999         if (!lp_widelinks(SNUM(conn)) && (strncmp(conn->connectpath, resolved_name, con_path_len) != 0)) {
1000                 DEBUG(2, ("reduce_name: Bad access attempt: %s is a symlink outside the share path", fname));
1001                 if (free_resolved_name)
1002                         SAFE_FREE(resolved_name);
1003                 errno = EACCES;
1004                 return False;
1005         }
1006
1007         /* Check if we are allowing users to follow symlinks */
1008         /* Patch from David Clerc <David.Clerc@cui.unige.ch>
1009                 University of Geneva */
1010                                                                                                                                                     
1011 #ifdef S_ISLNK
1012         if (!lp_symlinks(SNUM(conn))) {
1013                 SMB_STRUCT_STAT statbuf;
1014                 if ( (SMB_VFS_LSTAT(conn,fname,&statbuf) != -1) &&
1015                                 (S_ISLNK(statbuf.st_mode)) ) {
1016                         if (free_resolved_name)
1017                                 SAFE_FREE(resolved_name);
1018                         DEBUG(3,("reduce_name: denied: file path name %s is a symlink\n",resolved_name));
1019                         errno = EACCES;
1020                         return False;
1021                 }
1022         }
1023 #endif
1024
1025         DEBUG(3,("reduce_name: %s reduced to %s\n", fname, resolved_name));
1026         if (free_resolved_name)
1027                 SAFE_FREE(resolved_name);
1028         errno = saved_errno;
1029         return(True);
1030 }