r15283: Oh yeah. The build farm doesn't do much with head. OK, here is the patch...
[samba.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 static_decl_vfs;
31
32 struct vfs_init_function_entry {
33         char *name;
34         vfs_op_tuple *vfs_op_tuples;
35         struct vfs_init_function_entry *prev, *next;
36 };
37
38 static struct vfs_init_function_entry *backends = NULL;
39
40 /* Some structures to help us initialise the vfs operations table */
41
42 struct vfs_syminfo {
43         char *name;
44         void *fptr;
45 };
46
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. */
50
51 static struct vfs_ops default_vfs = {
52
53         {
54                 /* Disk operations */
55         
56                 vfswrap_dummy_connect,
57                 vfswrap_dummy_disconnect,
58                 vfswrap_disk_free,
59                 vfswrap_get_quota,
60                 vfswrap_set_quota,
61                 vfswrap_get_shadow_copy_data,
62                 vfswrap_statvfs,
63         
64                 /* Directory operations */
65         
66                 vfswrap_opendir,
67                 vfswrap_readdir,
68                 vfswrap_seekdir,
69                 vfswrap_telldir,
70                 vfswrap_rewinddir,
71                 vfswrap_mkdir,
72                 vfswrap_rmdir,
73                 vfswrap_closedir,
74         
75                 /* File operations */
76         
77                 vfswrap_open,
78                 vfswrap_close,
79                 vfswrap_read,
80                 vfswrap_pread,
81                 vfswrap_write,
82                 vfswrap_pwrite,
83                 vfswrap_lseek,
84                 vfswrap_sendfile,
85                 vfswrap_rename,
86                 vfswrap_fsync,
87                 vfswrap_stat,
88                 vfswrap_fstat,
89                 vfswrap_lstat,
90                 vfswrap_unlink,
91                 vfswrap_chmod,
92                 vfswrap_fchmod,
93                 vfswrap_chown,
94                 vfswrap_fchown,
95                 vfswrap_chdir,
96                 vfswrap_getwd,
97                 vfswrap_utime,
98                 vfswrap_ftruncate,
99                 vfswrap_lock,
100                 vfswrap_getlock,
101                 vfswrap_symlink,
102                 vfswrap_readlink,
103                 vfswrap_link,
104                 vfswrap_mknod,
105                 vfswrap_realpath,
106         
107                 /* Windows ACL operations. */
108                 vfswrap_fget_nt_acl,
109                 vfswrap_get_nt_acl,
110                 vfswrap_fset_nt_acl,
111                 vfswrap_set_nt_acl,
112         
113                 /* POSIX ACL operations. */
114                 vfswrap_chmod_acl,
115                 vfswrap_fchmod_acl,
116
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,
139
140                 /* EA operations. */
141                 vfswrap_getxattr,
142                 vfswrap_lgetxattr,
143                 vfswrap_fgetxattr,
144                 vfswrap_listxattr,
145                 vfswrap_llistxattr,
146                 vfswrap_flistxattr,
147                 vfswrap_removexattr,
148                 vfswrap_lremovexattr,
149                 vfswrap_fremovexattr,
150                 vfswrap_setxattr,
151                 vfswrap_lsetxattr,
152                 vfswrap_fsetxattr,
153
154                 /* AIO operations. */
155                 vfswrap_aio_read,
156                 vfswrap_aio_write,
157                 vfswrap_aio_return,
158                 vfswrap_aio_cancel,
159                 vfswrap_aio_error,
160                 vfswrap_aio_fsync,
161                 vfswrap_aio_suspend
162         }
163 };
164
165 /****************************************************************************
166     maintain the list of available backends
167 ****************************************************************************/
168
169 static struct vfs_init_function_entry *vfs_find_backend_entry(const char *name)
170 {
171         struct vfs_init_function_entry *entry = backends;
172  
173         while(entry) {
174                 if (strcmp(entry->name, name)==0) return entry;
175                 entry = entry->next;
176         }
177
178         return NULL;
179 }
180
181 NTSTATUS smb_register_vfs(int version, const char *name, vfs_op_tuple *vfs_op_tuples)
182 {
183         struct vfs_init_function_entry *entry = backends;
184
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;
192         }
193
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;
197         }
198
199         if (vfs_find_backend_entry(name)) {
200                 DEBUG(0,("VFS module %s already loaded!\n", name));
201                 return NT_STATUS_OBJECT_NAME_COLLISION;
202         }
203
204         entry = SMB_XMALLOC_P(struct vfs_init_function_entry);
205         entry->name = smb_xstrdup(name);
206         entry->vfs_op_tuples = vfs_op_tuples;
207
208         DLIST_ADD(backends, entry);
209         DEBUG(5, ("Successfully added vfs backend '%s'\n", name));
210         return NT_STATUS_OK;
211 }
212
213 /****************************************************************************
214   initialise default vfs hooks
215 ****************************************************************************/
216
217 static void vfs_init_default(connection_struct *conn)
218 {
219         DEBUG(3, ("Initialising default vfs hooks\n"));
220
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));
223 }
224
225 /****************************************************************************
226   initialise custom vfs hooks
227  ****************************************************************************/
228
229 BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object)
230 {
231         vfs_op_tuple *ops;
232         char *module_name = NULL;
233         char *module_param = NULL, *p;
234         int i;
235         vfs_handle_struct *handle;
236         struct vfs_init_function_entry *entry;
237         
238         if (!conn||!vfs_object||!vfs_object[0]) {
239                 DEBUG(0,("vfs_init_custon() called with NULL pointer or emtpy vfs_object!\n"));
240                 return False;
241         }
242
243         if(!backends) {
244                 static_init_vfs;
245         }
246
247         DEBUG(3, ("Initialising custom vfs hooks from [%s]\n", vfs_object));
248
249         module_name = smb_xstrdup(vfs_object);
250
251         p = strchr_m(module_name, ':');
252
253         if (p) {
254                 *p = 0;
255                 module_param = p+1;
256                 trim_char(module_param, ' ', ' ');
257         }
258
259         trim_char(module_name, ' ', ' ');
260
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)))) {
265
266                 DEBUGADD(5,("Successfully loaded vfs module [%s] with the new modules system\n", vfs_object));
267                 
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);
271                         return False;
272                 }
273         } else {
274                 DEBUG(0,("Can't find a vfs module [%s]\n",vfs_object));
275                 SAFE_FREE(module_name);
276                 return False;
277         }
278
279         handle = TALLOC_ZERO_P(conn->mem_ctx,vfs_handle_struct);
280         if (!handle) {
281                 DEBUG(0,("talloc_zero() failed!\n"));
282                 SAFE_FREE(module_name);
283                 return False;
284         }
285         memcpy(&handle->vfs_next, &conn->vfs, sizeof(struct vfs_ops));
286         handle->conn = conn;
287         if (module_param) {
288                 handle->param = talloc_strdup(conn->mem_ctx, module_param);
289         }
290         DLIST_ADD(conn->vfs_handles, handle);
291
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;
301                         }
302                 }
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;
307         }
308
309         SAFE_FREE(module_name);
310         return True;
311 }
312
313 /*****************************************************************
314  Generic VFS init.
315 ******************************************************************/
316
317 BOOL smbd_vfs_init(connection_struct *conn)
318 {
319         const char **vfs_objects;
320         unsigned int i = 0;
321         int j = 0;
322         
323         /* Normal share - initialise with disk access functions */
324         vfs_init_default(conn);
325         vfs_objects = lp_vfs_objects(SNUM(conn));
326
327         /* Override VFS functions if 'vfs object' was not specified*/
328         if (!vfs_objects || !vfs_objects[0])
329                 return True;
330         
331         for (i=0; vfs_objects[i] ;) {
332                 i++;
333         }
334
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]));
338                         return False;
339                 }
340         }
341         return True;
342 }
343
344 /*******************************************************************
345  Check if directory exists.
346 ********************************************************************/
347
348 BOOL vfs_directory_exist(connection_struct *conn, const char *dname, SMB_STRUCT_STAT *st)
349 {
350         SMB_STRUCT_STAT st2;
351         BOOL ret;
352
353         if (!st)
354                 st = &st2;
355
356         if (SMB_VFS_STAT(conn,dname,st) != 0)
357                 return(False);
358
359         ret = S_ISDIR(st->st_mode);
360         if(!ret)
361                 errno = ENOTDIR;
362
363         return ret;
364 }
365
366 /*******************************************************************
367  vfs mkdir wrapper 
368 ********************************************************************/
369
370 int vfs_MkDir(connection_struct *conn, const char *name, mode_t mode)
371 {
372         int ret;
373         SMB_STRUCT_STAT sbuf;
374
375         if(!(ret=SMB_VFS_MKDIR(conn, name, mode))) {
376
377                 inherit_access_acl(conn, name, mode);
378
379                 /*
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.
383                  */
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));
387         }
388         return ret;
389 }
390
391 /*******************************************************************
392  Check if an object exists in the vfs.
393 ********************************************************************/
394
395 BOOL vfs_object_exist(connection_struct *conn,const char *fname,SMB_STRUCT_STAT *sbuf)
396 {
397         SMB_STRUCT_STAT st;
398
399         if (!sbuf)
400                 sbuf = &st;
401
402         ZERO_STRUCTP(sbuf);
403
404         if (SMB_VFS_STAT(conn,fname,sbuf) == -1)
405                 return(False);
406         return True;
407 }
408
409 /*******************************************************************
410  Check if a file exists in the vfs.
411 ********************************************************************/
412
413 BOOL vfs_file_exist(connection_struct *conn, const char *fname,SMB_STRUCT_STAT *sbuf)
414 {
415         SMB_STRUCT_STAT st;
416
417         if (!sbuf)
418                 sbuf = &st;
419
420         ZERO_STRUCTP(sbuf);
421
422         if (SMB_VFS_STAT(conn,fname,sbuf) == -1)
423                 return False;
424         return(S_ISREG(sbuf->st_mode));
425 }
426
427 /****************************************************************************
428  Read data from fsp on the vfs. (note: EINTR re-read differs from vfs_write_data)
429 ****************************************************************************/
430
431 ssize_t vfs_read_data(files_struct *fsp, char *buf, size_t byte_count)
432 {
433         size_t total=0;
434
435         while (total < byte_count)
436         {
437                 ssize_t ret = SMB_VFS_READ(fsp, fsp->fh->fd, buf + total,
438                                         byte_count - total);
439
440                 if (ret == 0) return total;
441                 if (ret == -1) {
442                         if (errno == EINTR)
443                                 continue;
444                         else
445                                 return -1;
446                 }
447                 total += ret;
448         }
449         return (ssize_t)total;
450 }
451
452 ssize_t vfs_pread_data(files_struct *fsp, char *buf,
453                 size_t byte_count, SMB_OFF_T offset)
454 {
455         size_t total=0;
456
457         while (total < byte_count)
458         {
459                 ssize_t ret = SMB_VFS_PREAD(fsp, fsp->fh->fd, buf + total,
460                                         byte_count - total, offset + total);
461
462                 if (ret == 0) return total;
463                 if (ret == -1) {
464                         if (errno == EINTR)
465                                 continue;
466                         else
467                                 return -1;
468                 }
469                 total += ret;
470         }
471         return (ssize_t)total;
472 }
473
474 /****************************************************************************
475  Write data to a fd on the vfs.
476 ****************************************************************************/
477
478 ssize_t vfs_write_data(files_struct *fsp,const char *buffer,size_t N)
479 {
480         size_t total=0;
481         ssize_t ret;
482
483         while (total < N) {
484                 ret = SMB_VFS_WRITE(fsp,fsp->fh->fd,buffer + total,N - total);
485
486                 if (ret == -1)
487                         return -1;
488                 if (ret == 0)
489                         return total;
490
491                 total += ret;
492         }
493         return (ssize_t)total;
494 }
495
496 ssize_t vfs_pwrite_data(files_struct *fsp,const char *buffer,
497                 size_t N, SMB_OFF_T offset)
498 {
499         size_t total=0;
500         ssize_t ret;
501
502         while (total < N) {
503                 ret = SMB_VFS_PWRITE(fsp, fsp->fh->fd, buffer + total,
504                                 N - total, offset + total);
505
506                 if (ret == -1)
507                         return -1;
508                 if (ret == 0)
509                         return total;
510
511                 total += ret;
512         }
513         return (ssize_t)total;
514 }
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 ****************************************************************************/
520
521 int vfs_allocate_file_space(files_struct *fsp, SMB_BIG_UINT len)
522 {
523         int ret;
524         SMB_STRUCT_STAT st;
525         connection_struct *conn = fsp->conn;
526         SMB_BIG_UINT space_avail;
527         SMB_BIG_UINT bsize,dfree,dsize;
528
529         release_level_2_oplocks_on_change(fsp);
530
531         /*
532          * Actually try and commit the space on disk....
533          */
534
535         DEBUG(10,("vfs_allocate_file_space: file %s, len %.0f\n", fsp->fsp_name, (double)len ));
536
537         if (((SMB_OFF_T)len) < 0) {
538                 DEBUG(0,("vfs_allocate_file_space: %s negative len requested.\n", fsp->fsp_name ));
539                 return -1;
540         }
541
542         ret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st);
543         if (ret == -1)
544                 return ret;
545
546         if (len == (SMB_BIG_UINT)st.st_size)
547                 return 0;
548
549         if (len < (SMB_BIG_UINT)st.st_size) {
550                 /* Shrink - use ftruncate. */
551
552                 DEBUG(10,("vfs_allocate_file_space: file %s, shrink. Current size %.0f\n",
553                                 fsp->fsp_name, (double)st.st_size ));
554
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);
558                 }
559                 return ret;
560         }
561
562         /* Grow - we need to test if we have enough space. */
563
564         if (!lp_strict_allocate(SNUM(fsp->conn)))
565                 return 0;
566
567         len -= st.st_size;
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) {
571                 return -1;
572         }
573
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 ));
576
577         if (len > space_avail) {
578                 errno = ENOSPC;
579                 return -1;
580         }
581
582         return 0;
583 }
584
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 ****************************************************************************/
590
591 int vfs_set_filelen(files_struct *fsp, SMB_OFF_T len)
592 {
593         int ret;
594
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);
600
601         return ret;
602 }
603
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 ****************************************************************************/
610
611 static char *sparse_buf;
612 #define SPARSE_BUF_WRITE_SIZE (32*1024)
613
614 int vfs_fill_sparse(files_struct *fsp, SMB_OFF_T len)
615 {
616         int ret;
617         SMB_STRUCT_STAT st;
618         SMB_OFF_T offset;
619         size_t total;
620         size_t num_to_write;
621         ssize_t pwrite_ret;
622
623         release_level_2_oplocks_on_change(fsp);
624         ret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st);
625         if (ret == -1) {
626                 return ret;
627         }
628
629         if (len <= st.st_size) {
630                 return 0;
631         }
632
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)));
635
636         flush_write_cache(fsp, SIZECHANGE_FLUSH);
637
638         if (!sparse_buf) {
639                 sparse_buf = SMB_CALLOC_ARRAY(char, SPARSE_BUF_WRITE_SIZE);
640                 if (!sparse_buf) {
641                         errno = ENOMEM;
642                         return -1;
643                 }
644         }
645
646         offset = st.st_size;
647         num_to_write = len - st.st_size;
648         total = 0;
649
650         while (total < num_to_write) {
651                 size_t curr_write_size = MIN(SPARSE_BUF_WRITE_SIZE, (num_to_write - total));
652
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) ));
657                         return -1;
658                 }
659                 if (pwrite_ret == 0) {
660                         return 0;
661                 }
662
663                 total += pwrite_ret;
664         }
665
666         set_filelen_write_cache(fsp, len);
667         return 0;
668 }
669
670 /****************************************************************************
671  Transfer some data (n bytes) between two file_struct's.
672 ****************************************************************************/
673
674 static files_struct *in_fsp;
675 static files_struct *out_fsp;
676
677 static ssize_t read_fn(int fd, void *buf, size_t len)
678 {
679         return SMB_VFS_READ(in_fsp, fd, buf, len);
680 }
681
682 static ssize_t write_fn(int fd, const void *buf, size_t len)
683 {
684         return SMB_VFS_WRITE(out_fsp, fd, buf, len);
685 }
686
687 SMB_OFF_T vfs_transfer_file(files_struct *in, files_struct *out, SMB_OFF_T n)
688 {
689         in_fsp = in;
690         out_fsp = out;
691
692         return transfer_file_internal(in_fsp->fh->fd, out_fsp->fh->fd, n, read_fn, write_fn);
693 }
694
695 /*******************************************************************
696  A vfs_readdir wrapper which just returns the file name.
697 ********************************************************************/
698
699 char *vfs_readdirname(connection_struct *conn, void *p)
700 {
701         SMB_STRUCT_DIRENT *ptr= NULL;
702         char *dname;
703
704         if (!p)
705                 return(NULL);
706
707         ptr = SMB_VFS_READDIR(conn,p);
708         if (!ptr)
709                 return(NULL);
710
711         dname = ptr->d_name;
712
713 #ifdef NEXT2
714         if (telldir(p) < 0)
715                 return(NULL);
716 #endif
717
718 #ifdef HAVE_BROKEN_READDIR_NAME
719         /* using /usr/ucb/cc is BAD */
720         dname = dname - 2;
721 #endif
722
723         return(dname);
724 }
725
726 /*******************************************************************
727  A wrapper for vfs_chdir().
728 ********************************************************************/
729
730 int vfs_ChDir(connection_struct *conn, const char *path)
731 {
732         int res;
733         static pstring LastDir="";
734
735         if (strcsequal(path,"."))
736                 return(0);
737
738         if (*path == '/' && strcsequal(LastDir,path))
739                 return(0);
740
741         DEBUG(4,("vfs_ChDir to %s\n",path));
742
743         res = SMB_VFS_CHDIR(conn,path);
744         if (!res)
745                 pstrcpy(LastDir,path);
746         return(res);
747 }
748
749 /* number of list structures for a caching GetWd function. */
750 #define MAX_GETWDCACHE (50)
751
752 static struct {
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. */
756         BOOL valid;
757 } ino_list[MAX_GETWDCACHE];
758
759 extern BOOL use_getwd_cache;
760
761 /****************************************************************************
762  Prompte a ptr (to make it recently used)
763 ****************************************************************************/
764
765 static void array_promote(char *array,int elsize,int element)
766 {
767         char *p;
768         if (element == 0)
769                 return;
770
771         p = (char *)SMB_MALLOC(elsize);
772
773         if (!p) {
774                 DEBUG(5,("array_promote: malloc fail\n"));
775                 return;
776         }
777
778         memcpy(p,array + element * elsize, elsize);
779         memmove(array + elsize,array,elsize*element);
780         memcpy(array,p,elsize);
781         SAFE_FREE(p);
782 }
783
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 ********************************************************************/
789
790 char *vfs_GetWd(connection_struct *conn, char *path)
791 {
792         pstring s;
793         static BOOL getwd_cache_init = False;
794         SMB_STRUCT_STAT st, st2;
795         int i;
796
797         *s = 0;
798
799         if (!use_getwd_cache)
800                 return(SMB_VFS_GETWD(conn,path));
801
802         /* init the cache */
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;
808                 }
809         }
810
811         /*  Get the inode of the current directory, if this doesn't work we're
812                 in trouble :-) */
813
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));
819         }
820
821
822         for (i=0; i<MAX_GETWDCACHE; i++) {
823                 if (ino_list[i].valid) {
824
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
829                                 the same...) */
830
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);
836
837                                                 /* promote it for future use */
838                                                 array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i);
839                                                 return (path);
840                                         } else {
841                                                 /*  If the inode is different then something's changed,
842                                                         scrub the entry and start from scratch. */
843                                                 ino_list[i].valid = False;
844                                         }
845                                 }
846                         }
847                 }
848         }
849
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. */
853
854         if (!SMB_VFS_GETWD(conn,s)) {
855                 DEBUG(0,("vfs_GetWd: SMB_VFS_GETWD call failed, errno %s\n",strerror(errno)));
856                 return (NULL);
857         }
858
859         pstrcpy(path,s);
860
861         DEBUG(5,("vfs_GetWd %s, inode %.0f, dev %.0f\n",s,(double)st.st_ino,(double)st.st_dev));
862
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;
869
870         /* put it at the top of the list */
871         array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i);
872
873         return (path);
874 }
875
876 BOOL canonicalize_path(connection_struct *conn, pstring path)
877 {
878 #ifdef REALPATH_TAKES_NULL
879         char *resolved_name = SMB_VFS_REALPATH(conn,path,NULL);
880         if (!resolved_name) {
881                 return False;
882         }
883         pstrcpy(path, resolved_name);
884         SAFE_FREE(resolved_name);
885         return True;
886 #else
887 #ifdef PATH_MAX
888         char resolved_name_buf[PATH_MAX+1];
889 #else
890         pstring resolved_name_buf;
891 #endif
892         char *resolved_name = SMB_VFS_REALPATH(conn,path,resolved_name_buf);
893         if (!resolved_name) {
894                 return False;
895         }
896         pstrcpy(path, resolved_name);
897         return True;
898 #endif /* REALPATH_TAKES_NULL */
899 }
900
901 /*******************************************************************
902  Reduce a file name, removing .. elements and checking that
903  it is below dir in the heirachy. This uses realpath.
904 ********************************************************************/
905
906 BOOL reduce_name(connection_struct *conn, const pstring fname)
907 {
908 #ifdef REALPATH_TAKES_NULL
909         BOOL free_resolved_name = True;
910 #else
911 #ifdef PATH_MAX
912         char resolved_name_buf[PATH_MAX+1];
913 #else
914         pstring resolved_name_buf;
915 #endif
916         BOOL free_resolved_name = False;
917 #endif
918         char *resolved_name = NULL;
919         size_t con_path_len = strlen(conn->connectpath);
920         char *p = NULL;
921         int saved_errno = errno;
922
923         DEBUG(3,("reduce_name [%s] [%s]\n", fname, conn->connectpath));
924
925 #ifdef REALPATH_TAKES_NULL
926         resolved_name = SMB_VFS_REALPATH(conn,fname,NULL);
927 #else
928         resolved_name = SMB_VFS_REALPATH(conn,fname,resolved_name_buf);
929 #endif
930
931         if (!resolved_name) {
932                 switch (errno) {
933                         case ENOTDIR:
934                                 DEBUG(3,("reduce_name: Component not a directory in getting realpath for %s\n", fname));
935                                 errno = saved_errno;
936                                 return False;
937                         case ENOENT:
938                         {
939                                 pstring tmp_fname;
940                                 fstring last_component;
941                                 /* Last component didn't exist. Remove it and try and canonicalise the directory. */
942
943                                 pstrcpy(tmp_fname, fname);
944                                 p = strrchr_m(tmp_fname, '/');
945                                 if (p) {
946                                         *p++ = '\0';
947                                         fstrcpy(last_component, p);
948                                 } else {
949                                         fstrcpy(last_component, tmp_fname);
950                                         pstrcpy(tmp_fname, ".");
951                                 }
952
953 #ifdef REALPATH_TAKES_NULL
954                                 resolved_name = SMB_VFS_REALPATH(conn,tmp_fname,NULL);
955 #else
956                                 resolved_name = SMB_VFS_REALPATH(conn,tmp_fname,resolved_name_buf);
957 #endif
958                                 if (!resolved_name) {
959                                         DEBUG(3,("reduce_name: couldn't get realpath for %s\n", fname));
960                                         errno = saved_errno;
961                                         return False;
962                                 }
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));
971                                         errno = saved_errno;
972                                         return False;
973                                 }
974 #else
975 #ifdef PATH_MAX
976                                 safe_strcpy(resolved_name_buf, tmp_fname, PATH_MAX);
977 #else
978                                 pstrcpy(resolved_name_buf, tmp_fname);
979 #endif
980                                 resolved_name = resolved_name_buf;
981 #endif
982                                 break;
983                         }
984                         default:
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. */
988                                 return False;
989                 }
990         }
991
992         DEBUG(10,("reduce_name realpath [%s] -> [%s]\n", fname, resolved_name));
993
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);
998                 errno = saved_errno;
999                 return False;
1000         }
1001
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);
1007                 errno = EACCES;
1008                 return False;
1009         }
1010
1011         /* Check if we are allowing users to follow symlinks */
1012         /* Patch from David Clerc <David.Clerc@cui.unige.ch>
1013                 University of Geneva */
1014                                                                                                                                                     
1015 #ifdef S_ISLNK
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));
1023                         errno = EACCES;
1024                         return False;
1025                 }
1026         }
1027 #endif
1028
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;
1033         return(True);
1034 }