few edits
[Samba.git] / source / smbd / vfs-wrap.c
blobb7ec5c10247f4c10612f18e4e4c0f6b519834c20
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 Wrap disk only vfs functions to sidestep dodgy compilers.
5 Copyright (C) Tim Potter 1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "includes.h"
24 /* We don't want to have NULL function pointers lying around. Someone
25 is sure to try and execute them. These stubs are used to prevent
26 this possibility. */
28 int vfswrap_dummy_connect(connection_struct *conn, const char *service, const char *user)
30 return 0; /* Return >= 0 for success */
33 void vfswrap_dummy_disconnect(connection_struct *conn)
37 /* Disk operations */
39 SMB_BIG_UINT vfswrap_disk_free(connection_struct *conn, const char *path, BOOL small_query, SMB_BIG_UINT *bsize,
40 SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
42 SMB_BIG_UINT result;
44 result = sys_disk_free(path, small_query, bsize, dfree, dsize);
45 return result;
48 /* Directory operations */
50 DIR *vfswrap_opendir(connection_struct *conn, const char *fname)
52 DIR *result;
54 START_PROFILE(syscall_opendir);
56 result = opendir(fname);
57 END_PROFILE(syscall_opendir);
58 return result;
61 struct dirent *vfswrap_readdir(connection_struct *conn, DIR *dirp)
63 struct dirent *result;
65 START_PROFILE(syscall_readdir);
67 result = readdir(dirp);
68 END_PROFILE(syscall_readdir);
69 return result;
72 int vfswrap_mkdir(connection_struct *conn, const char *path, mode_t mode)
74 int result;
75 BOOL has_dacl = False;
77 START_PROFILE(syscall_mkdir);
79 if (lp_inherit_acls(SNUM(conn)) && (has_dacl = directory_has_default_acl(conn, parent_dirname(path))))
80 mode = 0777;
82 result = mkdir(path, mode);
84 if (result == 0 && !has_dacl) {
86 * We need to do this as the default behavior of POSIX ACLs
87 * is to set the mask to be the requested group permission
88 * bits, not the group permission bits to be the requested
89 * group permission bits. This is not what we want, as it will
90 * mess up any inherited ACL bits that were set. JRA.
92 int saved_errno = errno; /* We may get ENOSYS */
93 if (conn->vfs_ops.chmod_acl != NULL) {
94 if ((conn->vfs_ops.chmod_acl(conn, path, mode) == -1) && (errno == ENOSYS))
95 errno = saved_errno;
99 END_PROFILE(syscall_mkdir);
100 return result;
103 int vfswrap_rmdir(connection_struct *conn, const char *path)
105 int result;
107 START_PROFILE(syscall_rmdir);
109 result = rmdir(path);
110 END_PROFILE(syscall_rmdir);
111 return result;
114 int vfswrap_closedir(connection_struct *conn, DIR *dirp)
116 int result;
118 START_PROFILE(syscall_closedir);
120 result = closedir(dirp);
121 END_PROFILE(syscall_closedir);
122 return result;
125 /* File operations */
127 int vfswrap_open(connection_struct *conn, const char *fname, int flags, mode_t mode)
129 int result;
131 START_PROFILE(syscall_open);
133 result = sys_open(fname, flags, mode);
134 END_PROFILE(syscall_open);
135 return result;
138 int vfswrap_close(files_struct *fsp, int fd)
140 int result;
142 START_PROFILE(syscall_close);
144 result = close(fd);
145 END_PROFILE(syscall_close);
146 return result;
149 ssize_t vfswrap_read(files_struct *fsp, int fd, void *data, size_t n)
151 ssize_t result;
153 START_PROFILE_BYTES(syscall_read, n);
155 result = sys_read(fd, data, n);
156 END_PROFILE(syscall_read);
157 return result;
160 ssize_t vfswrap_write(files_struct *fsp, int fd, const void *data, size_t n)
162 ssize_t result;
164 START_PROFILE_BYTES(syscall_write, n);
166 result = sys_write(fd, data, n);
167 END_PROFILE(syscall_write);
168 return result;
171 ssize_t vfswrap_sendfile(int tofd, struct files_struct *fsp, int fromfd, const DATA_BLOB *hdr,
172 SMB_OFF_T offset, size_t n)
174 ssize_t result;
176 START_PROFILE_BYTES(syscall_sendfile, n);
177 result = sys_sendfile(tofd, fromfd, hdr, offset, n);
178 END_PROFILE(syscall_sendfile);
179 return result;
182 SMB_OFF_T vfswrap_lseek(files_struct *fsp, int filedes, SMB_OFF_T offset, int whence)
184 SMB_OFF_T result = 0;
186 START_PROFILE(syscall_lseek);
188 /* Cope with 'stat' file opens. */
189 if (filedes != -1)
190 result = sys_lseek(filedes, offset, whence);
193 * We want to maintain the fiction that we can seek
194 * on a fifo for file system purposes. This allows
195 * people to set up UNIX fifo's that feed data to Windows
196 * applications. JRA.
199 if((result == -1) && (errno == ESPIPE)) {
200 result = 0;
201 errno = 0;
204 END_PROFILE(syscall_lseek);
205 return result;
208 /*********************************************************
209 For rename across filesystems Patch from Warren Birnbaum
210 <warrenb@hpcvscdp.cv.hp.com>
211 **********************************************************/
213 static int copy_reg(const char *source, const char *dest)
215 SMB_STRUCT_STAT source_stats;
216 int ifd;
217 int ofd;
219 if (sys_lstat (source, &source_stats) == -1)
220 return -1;
222 if (!S_ISREG (source_stats.st_mode))
223 return -1;
225 if (unlink (dest) && errno != ENOENT)
226 return -1;
228 if((ifd = sys_open (source, O_RDONLY, 0)) < 0)
229 return -1;
231 if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0 ) {
232 int saved_errno = errno;
233 close (ifd);
234 errno = saved_errno;
235 return -1;
238 if (transfer_file(ifd, ofd, (size_t)-1) == -1) {
239 int saved_errno = errno;
240 close (ifd);
241 close (ofd);
242 unlink (dest);
243 errno = saved_errno;
244 return -1;
247 if (close (ifd) == -1) {
248 int saved_errno = errno;
249 close (ofd);
250 errno = saved_errno;
251 return -1;
253 if (close (ofd) == -1)
254 return -1;
257 * chown turns off set[ug]id bits for non-root,
258 * so do the chmod last.
261 /* Try to copy the old file's modtime and access time. */
263 struct utimbuf tv;
265 tv.actime = source_stats.st_atime;
266 tv.modtime = source_stats.st_mtime;
267 utime (dest, &tv);
271 * Try to preserve ownership. For non-root it might fail, but that's ok.
272 * But root probably wants to know, e.g. if NFS disallows it.
275 if ((chown(dest, source_stats.st_uid, source_stats.st_gid) == -1) && (errno != EPERM))
276 return -1;
278 if (chmod (dest, source_stats.st_mode & 07777))
279 return -1;
281 if (unlink (source) == -1)
282 return -1;
284 return 0;
287 int vfswrap_rename(connection_struct *conn, const char *oldname, const char *newname)
289 int result;
291 START_PROFILE(syscall_rename);
292 result = rename(oldname, newname);
293 if (errno == EXDEV) {
294 /* Rename across filesystems needed. */
295 result = copy_reg(oldname, newname);
297 END_PROFILE(syscall_rename);
298 return result;
301 int vfswrap_fsync(files_struct *fsp, int fd)
303 #ifdef HAVE_FSYNC
304 int result;
306 START_PROFILE(syscall_fsync);
307 result = fsync(fd);
308 END_PROFILE(syscall_fsync);
309 return result;
310 #else
311 return 0;
312 #endif
315 int vfswrap_stat(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf)
317 int result;
319 START_PROFILE(syscall_stat);
320 result = sys_stat(fname, sbuf);
321 END_PROFILE(syscall_stat);
322 return result;
325 int vfswrap_fstat(files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf)
327 int result;
329 START_PROFILE(syscall_fstat);
330 result = sys_fstat(fd, sbuf);
331 END_PROFILE(syscall_fstat);
332 return result;
335 int vfswrap_lstat(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf)
337 int result;
339 START_PROFILE(syscall_lstat);
340 result = sys_lstat(path, sbuf);
341 END_PROFILE(syscall_lstat);
342 return result;
345 int vfswrap_unlink(connection_struct *conn, const char *path)
347 int result;
349 START_PROFILE(syscall_unlink);
350 result = unlink(path);
351 END_PROFILE(syscall_unlink);
352 return result;
355 int vfswrap_chmod(connection_struct *conn, const char *path, mode_t mode)
357 int result;
359 START_PROFILE(syscall_chmod);
362 * We need to do this due to the fact that the default POSIX ACL
363 * chmod modifies the ACL *mask* for the group owner, not the
364 * group owner bits directly. JRA.
368 if (conn->vfs_ops.chmod_acl != NULL) {
369 int saved_errno = errno; /* We might get ENOSYS */
370 if ((result = conn->vfs_ops.chmod_acl(conn, path, mode)) == 0) {
371 END_PROFILE(syscall_chmod);
372 return result;
374 /* Error - return the old errno. */
375 errno = saved_errno;
378 result = chmod(path, mode);
379 END_PROFILE(syscall_chmod);
380 return result;
383 int vfswrap_fchmod(files_struct *fsp, int fd, mode_t mode)
385 int result;
386 struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops;
388 START_PROFILE(syscall_fchmod);
391 * We need to do this due to the fact that the default POSIX ACL
392 * chmod modifies the ACL *mask* for the group owner, not the
393 * group owner bits directly. JRA.
396 if (vfs_ops->fchmod_acl != NULL) {
397 int saved_errno = errno; /* We might get ENOSYS */
398 if ((result = vfs_ops->fchmod_acl(fsp, fd, mode)) == 0) {
399 END_PROFILE(syscall_chmod);
400 return result;
402 /* Error - return the old errno. */
403 errno = saved_errno;
406 result = fchmod(fd, mode);
407 END_PROFILE(syscall_fchmod);
408 return result;
411 int vfswrap_chown(connection_struct *conn, const char *path, uid_t uid, gid_t gid)
413 int result;
415 START_PROFILE(syscall_chown);
416 result = sys_chown(path, uid, gid);
417 END_PROFILE(syscall_chown);
418 return result;
421 int vfswrap_fchown(files_struct *fsp, int fd, uid_t uid, gid_t gid)
423 #ifdef HAVE_FCHOWN
424 int result;
426 START_PROFILE(syscall_fchown);
428 result = fchown(fd, uid, gid);
429 END_PROFILE(syscall_fchown);
430 return result;
431 #else
432 errno = ENOSYS;
433 return -1;
434 #endif
437 int vfswrap_chdir(connection_struct *conn, const char *path)
439 int result;
441 START_PROFILE(syscall_chdir);
442 result = chdir(path);
443 END_PROFILE(syscall_chdir);
444 return result;
447 char *vfswrap_getwd(connection_struct *conn, char *path)
449 char *result;
451 START_PROFILE(syscall_getwd);
452 result = sys_getwd(path);
453 END_PROFILE(syscall_getwd);
454 return result;
457 int vfswrap_utime(connection_struct *conn, const char *path, struct utimbuf *times)
459 int result;
461 START_PROFILE(syscall_utime);
462 result = utime(path, times);
463 END_PROFILE(syscall_utime);
464 return result;
467 /*********************************************************************
468 A version of ftruncate that will write the space on disk if strict
469 allocate is set.
470 **********************************************************************/
472 static int strict_allocate_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len)
474 struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops;
475 SMB_STRUCT_STAT st;
476 SMB_OFF_T currpos = vfs_ops->lseek(fsp, fd, 0, SEEK_CUR);
477 unsigned char zero_space[4096];
478 SMB_OFF_T space_to_write;
480 if (currpos == -1)
481 return -1;
483 if (vfs_ops->fstat(fsp, fd, &st) == -1)
484 return -1;
486 #ifdef S_ISFIFO
487 if (S_ISFIFO(st.st_mode))
488 return 0;
489 #endif
491 if (st.st_size == len)
492 return 0;
494 /* Shrink - just ftruncate. */
495 if (st.st_size > len)
496 return sys_ftruncate(fd, len);
498 /* Write out the real space on disk. */
499 if (vfs_ops->lseek(fsp, fd, st.st_size, SEEK_SET) != st.st_size)
500 return -1;
502 space_to_write = len - st.st_size;
504 memset(zero_space, '\0', sizeof(zero_space));
505 while ( space_to_write > 0) {
506 SMB_OFF_T retlen;
507 SMB_OFF_T current_len_to_write = MIN(sizeof(zero_space),space_to_write);
509 retlen = vfs_ops->write(fsp,fsp->fd,(char *)zero_space,current_len_to_write);
510 if (retlen <= 0)
511 return -1;
513 space_to_write -= retlen;
516 /* Seek to where we were */
517 if (vfs_ops->lseek(fsp, fd, currpos, SEEK_SET) != currpos)
518 return -1;
520 return 0;
523 int vfswrap_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len)
525 int result = -1;
526 struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops;
527 SMB_STRUCT_STAT st;
528 char c = 0;
529 SMB_OFF_T currpos;
531 START_PROFILE(syscall_ftruncate);
533 if (lp_strict_allocate(SNUM(fsp->conn))) {
534 result = strict_allocate_ftruncate(fsp, fd, len);
535 END_PROFILE(syscall_ftruncate);
536 return result;
539 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
540 sys_ftruncate if the system supports it. Then I discovered that
541 you can have some filesystems that support ftruncate
542 expansion and some that don't! On Linux fat can't do
543 ftruncate extend but ext2 can. */
545 result = sys_ftruncate(fd, len);
546 if (result == 0)
547 goto done;
549 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
550 extend a file with ftruncate. Provide alternate implementation
551 for this */
552 currpos = vfs_ops->lseek(fsp, fd, 0, SEEK_CUR);
553 if (currpos == -1) {
554 goto done;
557 /* Do an fstat to see if the file is longer than the requested
558 size in which case the ftruncate above should have
559 succeeded or shorter, in which case seek to len - 1 and
560 write 1 byte of zero */
561 if (vfs_ops->fstat(fsp, fd, &st) == -1) {
562 goto done;
565 #ifdef S_ISFIFO
566 if (S_ISFIFO(st.st_mode)) {
567 result = 0;
568 goto done;
570 #endif
572 if (st.st_size == len) {
573 result = 0;
574 goto done;
577 if (st.st_size > len) {
578 /* the sys_ftruncate should have worked */
579 goto done;
582 if (vfs_ops->lseek(fsp, fd, len-1, SEEK_SET) != len -1)
583 goto done;
585 if (vfs_ops->write(fsp, fd, &c, 1)!=1)
586 goto done;
588 /* Seek to where we were */
589 if (vfs_ops->lseek(fsp, fd, currpos, SEEK_SET) != currpos)
590 goto done;
591 result = 0;
593 done:
595 END_PROFILE(syscall_ftruncate);
596 return result;
599 BOOL vfswrap_lock(files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
601 BOOL result;
603 START_PROFILE(syscall_fcntl_lock);
604 result = fcntl_lock(fd, op, offset, count,type);
605 END_PROFILE(syscall_fcntl_lock);
606 return result;
609 int vfswrap_symlink(connection_struct *conn, const char *oldpath, const char *newpath)
611 int result;
613 START_PROFILE(syscall_symlink);
614 result = sys_symlink(oldpath, newpath);
615 END_PROFILE(syscall_symlink);
616 return result;
619 int vfswrap_readlink(connection_struct *conn, const char *path, char *buf, size_t bufsiz)
621 int result;
623 START_PROFILE(syscall_readlink);
624 result = sys_readlink(path, buf, bufsiz);
625 END_PROFILE(syscall_readlink);
626 return result;
629 int vfswrap_link(connection_struct *conn, const char *oldpath, const char *newpath)
631 int result;
633 START_PROFILE(syscall_link);
634 result = sys_link(oldpath, newpath);
635 END_PROFILE(syscall_link);
636 return result;
639 int vfswrap_mknod(connection_struct *conn, const char *pathname, mode_t mode, SMB_DEV_T dev)
641 int result;
643 START_PROFILE(syscall_mknod);
644 result = sys_mknod(pathname, mode, dev);
645 END_PROFILE(syscall_mknod);
646 return result;
649 char *vfswrap_realpath(connection_struct *conn, const char *path, char *resolved_path)
651 char *result;
653 START_PROFILE(syscall_realpath);
654 result = sys_realpath(path, resolved_path);
655 END_PROFILE(syscall_realpath);
656 return result;
659 size_t vfswrap_fget_nt_acl(files_struct *fsp, int fd, SEC_DESC **ppdesc)
661 size_t result;
663 START_PROFILE(fget_nt_acl);
664 result = get_nt_acl(fsp, ppdesc);
665 END_PROFILE(fget_nt_acl);
666 return result;
669 size_t vfswrap_get_nt_acl(files_struct *fsp, const char *name, SEC_DESC **ppdesc)
671 size_t result;
673 START_PROFILE(get_nt_acl);
674 result = get_nt_acl(fsp, ppdesc);
675 END_PROFILE(get_nt_acl);
676 return result;
679 BOOL vfswrap_fset_nt_acl(files_struct *fsp, int fd, uint32 security_info_sent, SEC_DESC *psd)
681 BOOL result;
683 START_PROFILE(fset_nt_acl);
684 result = set_nt_acl(fsp, security_info_sent, psd);
685 END_PROFILE(fset_nt_acl);
686 return result;
689 BOOL vfswrap_set_nt_acl(files_struct *fsp, const char *name, uint32 security_info_sent, SEC_DESC *psd)
691 BOOL result;
693 START_PROFILE(set_nt_acl);
694 result = set_nt_acl(fsp, security_info_sent, psd);
695 END_PROFILE(set_nt_acl);
696 return result;
699 int vfswrap_chmod_acl(connection_struct *conn, const char *name, mode_t mode)
701 int result;
703 START_PROFILE(chmod_acl);
704 result = chmod_acl(conn, name, mode);
705 END_PROFILE(chmod_acl);
706 return result;
709 int vfswrap_fchmod_acl(files_struct *fsp, int fd, mode_t mode)
711 int result;
713 START_PROFILE(fchmod_acl);
714 result = fchmod_acl(fsp, fd, mode);
715 END_PROFILE(fchmod_acl);
716 return result;
719 int vfswrap_sys_acl_get_entry(struct connection_struct *conn, SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
721 return sys_acl_get_entry(theacl, entry_id, entry_p);
724 int vfswrap_sys_acl_get_tag_type(struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
726 return sys_acl_get_tag_type(entry_d, tag_type_p);
729 int vfswrap_sys_acl_get_permset(struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
731 return sys_acl_get_permset(entry_d, permset_p);
734 void * vfswrap_sys_acl_get_qualifier(struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d)
736 return sys_acl_get_qualifier(entry_d);
739 SMB_ACL_T vfswrap_sys_acl_get_file(struct connection_struct *conn, const char *path_p, SMB_ACL_TYPE_T type)
741 return sys_acl_get_file(path_p, type);
744 SMB_ACL_T vfswrap_sys_acl_get_fd(struct files_struct *fsp, int fd)
746 return sys_acl_get_fd(fd);
749 int vfswrap_sys_acl_clear_perms(struct connection_struct *conn, SMB_ACL_PERMSET_T permset)
751 return sys_acl_clear_perms(permset);
754 int vfswrap_sys_acl_add_perm(struct connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
756 return sys_acl_add_perm(permset, perm);
759 char * vfswrap_sys_acl_to_text(struct connection_struct *conn, SMB_ACL_T theacl, ssize_t *plen)
761 return sys_acl_to_text(theacl, plen);
764 SMB_ACL_T vfswrap_sys_acl_init(struct connection_struct *conn, int count)
766 return sys_acl_init(count);
769 int vfswrap_sys_acl_create_entry(struct connection_struct *conn, SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
771 return sys_acl_create_entry(pacl, pentry);
774 int vfswrap_sys_acl_set_tag_type(struct connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
776 return sys_acl_set_tag_type(entry, tagtype);
779 int vfswrap_sys_acl_set_qualifier(struct connection_struct *conn, SMB_ACL_ENTRY_T entry, void *qual)
781 return sys_acl_set_qualifier(entry, qual);
784 int vfswrap_sys_acl_set_permset(struct connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
786 return sys_acl_set_permset(entry, permset);
789 int vfswrap_sys_acl_valid(struct connection_struct *conn, SMB_ACL_T theacl )
791 return sys_acl_valid(theacl );
794 int vfswrap_sys_acl_set_file(struct connection_struct *conn, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
796 return sys_acl_set_file(name, acltype, theacl);
799 int vfswrap_sys_acl_set_fd(struct files_struct *fsp, int fd, SMB_ACL_T theacl)
801 return sys_acl_set_fd(fd, theacl);
804 int vfswrap_sys_acl_delete_def_file(struct connection_struct *conn, const char *path)
806 return sys_acl_delete_def_file(path);
809 int vfswrap_sys_acl_get_perm(struct connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
811 return sys_acl_get_perm(permset, perm);
814 int vfswrap_sys_acl_free_text(struct connection_struct *conn, char *text)
816 return sys_acl_free_text(text);
819 int vfswrap_sys_acl_free_acl(struct connection_struct *conn, SMB_ACL_T posix_acl)
821 return sys_acl_free_acl(posix_acl);
824 int vfswrap_sys_acl_free_qualifier(struct connection_struct *conn, void *qualifier, SMB_ACL_TAG_T tagtype)
826 return sys_acl_free_qualifier(qualifier, tagtype);