Fairly large change to printing code.
[Samba.git] / source / smbd / vfs-wrap.c
blob394086dc075502adf57e9c9a4f72946589501d6c
1 /*
2 Unix SMB/CIFS implementation.
3 Wrap disk only vfs functions to sidestep dodgy compilers.
4 Copyright (C) Tim Potter 1998
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "includes.h"
23 /* Check for NULL pointer parameters in vfswrap_* functions */
25 /* We don't want to have NULL function pointers lying around. Someone
26 is sure to try and execute them. These stubs are used to prevent
27 this possibility. */
29 int vfswrap_dummy_connect(connection_struct *conn, const char *service, const char *user)
31 return 0; /* Return >= 0 for success */
34 void vfswrap_dummy_disconnect(connection_struct *conn)
38 /* Disk operations */
40 SMB_BIG_UINT vfswrap_disk_free(connection_struct *conn, const char *path, BOOL small_query, SMB_BIG_UINT *bsize,
41 SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
43 SMB_BIG_UINT result;
45 result = sys_disk_free(path, small_query, bsize, dfree, dsize);
46 return result;
49 /* Directory operations */
51 DIR *vfswrap_opendir(connection_struct *conn, const char *fname)
53 DIR *result;
55 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);
66 result = readdir(dirp);
67 END_PROFILE(syscall_readdir);
68 return result;
71 int vfswrap_mkdir(connection_struct *conn, const char *path, mode_t mode)
73 int result;
74 BOOL has_dacl = False;
76 START_PROFILE(syscall_mkdir);
78 if (lp_inherit_acls(SNUM(conn)) && (has_dacl = directory_has_default_acl(conn, parent_dirname(path))))
79 mode = 0777;
81 result = mkdir(path, mode);
83 if (result == 0 && !has_dacl) {
85 * We need to do this as the default behavior of POSIX ACLs
86 * is to set the mask to be the requested group permission
87 * bits, not the group permission bits to be the requested
88 * group permission bits. This is not what we want, as it will
89 * mess up any inherited ACL bits that were set. JRA.
91 int saved_errno = errno; /* We may get ENOSYS */
92 if (conn->vfs_ops.chmod_acl != NULL) {
93 if ((conn->vfs_ops.chmod_acl(conn, path, mode) == -1) && (errno == ENOSYS))
94 errno = saved_errno;
98 END_PROFILE(syscall_mkdir);
99 return result;
102 int vfswrap_rmdir(connection_struct *conn, const char *path)
104 int result;
106 START_PROFILE(syscall_rmdir);
107 result = rmdir(path);
108 END_PROFILE(syscall_rmdir);
109 return result;
112 int vfswrap_closedir(connection_struct *conn, DIR *dirp)
114 int result;
116 START_PROFILE(syscall_closedir);
117 result = closedir(dirp);
118 END_PROFILE(syscall_closedir);
119 return result;
122 /* File operations */
124 int vfswrap_open(connection_struct *conn, const char *fname, int flags, mode_t mode)
126 int result;
128 START_PROFILE(syscall_open);
129 result = sys_open(fname, flags, mode);
130 END_PROFILE(syscall_open);
131 return result;
134 int vfswrap_close(files_struct *fsp, int fd)
136 int result;
138 START_PROFILE(syscall_close);
140 result = close(fd);
141 END_PROFILE(syscall_close);
142 return result;
145 ssize_t vfswrap_read(files_struct *fsp, int fd, void *data, size_t n)
147 ssize_t result;
149 START_PROFILE_BYTES(syscall_read, n);
150 result = sys_read(fd, data, n);
151 END_PROFILE(syscall_read);
152 return result;
155 ssize_t vfswrap_write(files_struct *fsp, int fd, const void *data, size_t n)
157 ssize_t result;
159 START_PROFILE_BYTES(syscall_write, n);
160 result = sys_write(fd, data, n);
161 END_PROFILE(syscall_write);
162 return result;
165 SMB_OFF_T vfswrap_lseek(files_struct *fsp, int filedes, SMB_OFF_T offset, int whence)
167 SMB_OFF_T result = 0;
169 START_PROFILE(syscall_lseek);
171 /* Cope with 'stat' file opens. */
172 if (filedes != -1)
173 result = sys_lseek(filedes, offset, whence);
176 * We want to maintain the fiction that we can seek
177 * on a fifo for file system purposes. This allows
178 * people to set up UNIX fifo's that feed data to Windows
179 * applications. JRA.
182 if((result == -1) && (errno == ESPIPE)) {
183 result = 0;
184 errno = 0;
187 END_PROFILE(syscall_lseek);
188 return result;
191 int vfswrap_rename(connection_struct *conn, const char *old, const char *new)
193 int result;
195 START_PROFILE(syscall_rename);
196 result = rename(old, new);
197 END_PROFILE(syscall_rename);
198 return result;
201 int vfswrap_fsync(files_struct *fsp, int fd)
203 #ifdef HAVE_FSYNC
204 int result;
206 START_PROFILE(syscall_fsync);
208 result = fsync(fd);
209 END_PROFILE(syscall_fsync);
210 return result;
211 #else
212 return 0;
213 #endif
216 int vfswrap_stat(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf)
218 int result;
220 START_PROFILE(syscall_stat);
221 result = sys_stat(fname, sbuf);
222 END_PROFILE(syscall_stat);
223 return result;
226 int vfswrap_fstat(files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf)
228 int result;
230 START_PROFILE(syscall_fstat);
231 result = sys_fstat(fd, sbuf);
232 END_PROFILE(syscall_fstat);
233 return result;
236 int vfswrap_lstat(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf)
238 int result;
240 START_PROFILE(syscall_lstat);
241 result = sys_lstat(path, sbuf);
242 END_PROFILE(syscall_lstat);
243 return result;
246 int vfswrap_unlink(connection_struct *conn, const char *path)
248 int result;
250 START_PROFILE(syscall_unlink);
251 result = unlink(path);
252 END_PROFILE(syscall_unlink);
253 return result;
256 int vfswrap_chmod(connection_struct *conn, const char *path, mode_t mode)
258 int result;
260 START_PROFILE(syscall_chmod);
263 * We need to do this due to the fact that the default POSIX ACL
264 * chmod modifies the ACL *mask* for the group owner, not the
265 * group owner bits directly. JRA.
269 if (conn->vfs_ops.chmod_acl != NULL) {
270 int saved_errno = errno; /* We might get ENOSYS */
271 if ((result = conn->vfs_ops.chmod_acl(conn, path, mode)) == 0) {
272 END_PROFILE(syscall_chmod);
273 return result;
275 /* Error - return the old errno. */
276 errno = saved_errno;
279 result = chmod(path, mode);
280 END_PROFILE(syscall_chmod);
281 return result;
284 int vfswrap_fchmod(files_struct *fsp, int fd, mode_t mode)
286 int result;
287 struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops;
289 START_PROFILE(syscall_fchmod);
292 * We need to do this due to the fact that the default POSIX ACL
293 * chmod modifies the ACL *mask* for the group owner, not the
294 * group owner bits directly. JRA.
297 if (vfs_ops->fchmod_acl != NULL) {
298 int saved_errno = errno; /* We might get ENOSYS */
299 if ((result = vfs_ops->fchmod_acl(fsp, fd, mode)) == 0) {
300 END_PROFILE(syscall_chmod);
301 return result;
303 /* Error - return the old errno. */
304 errno = saved_errno;
307 result = fchmod(fd, mode);
308 END_PROFILE(syscall_fchmod);
309 return result;
312 int vfswrap_chown(connection_struct *conn, const char *path, uid_t uid, gid_t gid)
314 int result;
316 START_PROFILE(syscall_chown);
317 result = sys_chown(path, uid, gid);
318 END_PROFILE(syscall_chown);
319 return result;
322 int vfswrap_fchown(files_struct *fsp, int fd, uid_t uid, gid_t gid)
324 int result;
326 START_PROFILE(syscall_fchown);
328 result = fchown(fd, uid, gid);
329 END_PROFILE(syscall_fchown);
330 return result;
333 int vfswrap_chdir(connection_struct *conn, const char *path)
335 int result;
337 START_PROFILE(syscall_chdir);
338 result = chdir(path);
339 END_PROFILE(syscall_chdir);
340 return result;
343 char *vfswrap_getwd(connection_struct *conn, char *path)
345 char *result;
347 START_PROFILE(syscall_getwd);
348 result = sys_getwd(path);
349 END_PROFILE(syscall_getwd);
350 return result;
353 int vfswrap_utime(connection_struct *conn, const char *path, struct utimbuf *times)
355 int result;
357 START_PROFILE(syscall_utime);
358 result = utime(path, times);
359 END_PROFILE(syscall_utime);
360 return result;
363 /*********************************************************************
364 A version of ftruncate that will write the space on disk if strict
365 allocate is set.
366 **********************************************************************/
368 static int strict_allocate_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len)
370 struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops;
371 SMB_STRUCT_STAT st;
372 SMB_OFF_T currpos = vfs_ops->lseek(fsp, fd, 0, SEEK_CUR);
373 unsigned char zero_space[4096];
374 SMB_OFF_T space_to_write;
376 if (currpos == -1)
377 return -1;
379 if (vfs_ops->fstat(fsp, fd, &st) == -1)
380 return -1;
382 space_to_write = len - st.st_size;
384 #ifdef S_ISFIFO
385 if (S_ISFIFO(st.st_mode))
386 return 0;
387 #endif
389 if (st.st_size == len)
390 return 0;
392 /* Shrink - just ftruncate. */
393 if (st.st_size > len)
394 return sys_ftruncate(fd, len);
396 /* Write out the real space on disk. */
397 if (vfs_ops->lseek(fsp, fd, st.st_size, SEEK_SET) != st.st_size)
398 return -1;
400 space_to_write = len - st.st_size;
402 memset(zero_space, '\0', sizeof(zero_space));
403 while ( space_to_write > 0) {
404 SMB_OFF_T retlen;
405 SMB_OFF_T current_len_to_write = MIN(sizeof(zero_space),space_to_write);
407 retlen = vfs_ops->write(fsp,fsp->fd,(char *)zero_space,current_len_to_write);
408 if (retlen <= 0)
409 return -1;
411 space_to_write -= retlen;
414 /* Seek to where we were */
415 if (vfs_ops->lseek(fsp, fd, currpos, SEEK_SET) != currpos)
416 return -1;
418 return 0;
421 int vfswrap_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len)
423 int result = -1;
424 struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops;
425 SMB_STRUCT_STAT st;
426 char c = 0;
427 SMB_OFF_T currpos;
429 START_PROFILE(syscall_ftruncate);
431 if (lp_strict_allocate(SNUM(fsp->conn))) {
432 result = strict_allocate_ftruncate(fsp, fd, len);
433 END_PROFILE(syscall_ftruncate);
434 return result;
437 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
438 sys_ftruncate if the system supports it. Then I discovered that
439 you can have some filesystems that support ftruncate
440 expansion and some that don't! On Linux fat can't do
441 ftruncate extend but ext2 can. */
443 result = sys_ftruncate(fd, len);
444 if (result == 0)
445 goto done;
447 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
448 extend a file with ftruncate. Provide alternate implementation
449 for this */
450 currpos = vfs_ops->lseek(fsp, fd, 0, SEEK_CUR);
451 if (currpos == -1) {
452 goto done;
455 /* Do an fstat to see if the file is longer than the requested
456 size in which case the ftruncate above should have
457 succeeded or shorter, in which case seek to len - 1 and
458 write 1 byte of zero */
459 if (vfs_ops->fstat(fsp, fd, &st) == -1) {
460 goto done;
463 #ifdef S_ISFIFO
464 if (S_ISFIFO(st.st_mode)) {
465 result = 0;
466 goto done;
468 #endif
470 if (st.st_size == len) {
471 result = 0;
472 goto done;
475 if (st.st_size > len) {
476 /* the sys_ftruncate should have worked */
477 goto done;
480 if (vfs_ops->lseek(fsp, fd, len-1, SEEK_SET) != len -1)
481 goto done;
483 if (vfs_ops->write(fsp, fd, &c, 1)!=1)
484 goto done;
486 /* Seek to where we were */
487 if (vfs_ops->lseek(fsp, fd, currpos, SEEK_SET) != currpos)
488 goto done;
489 result = 0;
491 done:
493 END_PROFILE(syscall_ftruncate);
494 return result;
497 BOOL vfswrap_lock(files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
499 BOOL result;
501 START_PROFILE(syscall_fcntl_lock);
503 result = fcntl_lock(fd, op, offset, count,type);
504 END_PROFILE(syscall_fcntl_lock);
505 return result;
508 int vfswrap_symlink(connection_struct *conn, const char *oldpath, const char *newpath)
510 int result;
512 START_PROFILE(syscall_symlink);
513 result = sys_symlink(oldpath, newpath);
514 END_PROFILE(syscall_symlink);
515 return result;
518 int vfswrap_readlink(connection_struct *conn, const char *path, char *buf, size_t bufsiz)
520 int result;
522 START_PROFILE(syscall_readlink);
523 result = sys_readlink(path, buf, bufsiz);
524 END_PROFILE(syscall_readlink);
525 return result;
528 int vfswrap_link(connection_struct *conn, const char *oldpath, const char *newpath)
530 int result;
532 START_PROFILE(syscall_link);
533 result = sys_link(oldpath, newpath);
534 END_PROFILE(syscall_link);
535 return result;
538 int vfswrap_mknod(connection_struct *conn, const char *pathname, mode_t mode, SMB_DEV_T dev)
540 int result;
542 START_PROFILE(syscall_mknod);
543 result = sys_mknod(pathname, mode, dev);
544 END_PROFILE(syscall_mknod);
545 return result;
548 char *vfswrap_realpath(connection_struct *conn, const char *path, char *resolved_path)
550 char *result;
552 START_PROFILE(syscall_realpath);
553 result = sys_realpath(path, resolved_path);
554 END_PROFILE(syscall_realpath);
555 return result;
558 size_t vfswrap_fget_nt_acl(files_struct *fsp, int fd, SEC_DESC **ppdesc)
560 size_t result;
562 START_PROFILE(fget_nt_acl);
563 result = get_nt_acl(fsp, ppdesc);
564 END_PROFILE(fget_nt_acl);
565 return result;
568 size_t vfswrap_get_nt_acl(files_struct *fsp, const char *name, SEC_DESC **ppdesc)
570 size_t result;
572 START_PROFILE(get_nt_acl);
573 result = get_nt_acl(fsp, ppdesc);
574 END_PROFILE(get_nt_acl);
575 return result;
578 BOOL vfswrap_fset_nt_acl(files_struct *fsp, int fd, uint32 security_info_sent, SEC_DESC *psd)
580 BOOL result;
582 START_PROFILE(fset_nt_acl);
583 result = set_nt_acl(fsp, security_info_sent, psd);
584 END_PROFILE(fset_nt_acl);
585 return result;
588 BOOL vfswrap_set_nt_acl(files_struct *fsp, const char *name, uint32 security_info_sent, SEC_DESC *psd)
590 BOOL result;
592 START_PROFILE(set_nt_acl);
593 result = set_nt_acl(fsp, security_info_sent, psd);
594 END_PROFILE(set_nt_acl);
595 return result;
598 int vfswrap_chmod_acl(connection_struct *conn, const char *name, mode_t mode)
600 int result;
602 START_PROFILE(chmod_acl);
603 result = chmod_acl(conn, name, mode);
604 END_PROFILE(chmod_acl);
605 return result;
608 int vfswrap_fchmod_acl(files_struct *fsp, int fd, mode_t mode)
610 int result;
612 START_PROFILE(fchmod_acl);
613 result = fchmod_acl(fsp, fd, mode);
614 END_PROFILE(fchmod_acl);
615 return result;
618 int vfswrap_sys_acl_get_entry(struct connection_struct *conn, SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
620 return sys_acl_get_entry(theacl, entry_id, entry_p);
623 int vfswrap_sys_acl_get_tag_type(struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
625 return sys_acl_get_tag_type(entry_d, tag_type_p);
628 int vfswrap_sys_acl_get_permset(struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
630 return sys_acl_get_permset(entry_d, permset_p);
633 void * vfswrap_sys_acl_get_qualifier(struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d)
635 return sys_acl_get_qualifier(entry_d);
638 SMB_ACL_T vfswrap_sys_acl_get_file(struct connection_struct *conn, const char *path_p, SMB_ACL_TYPE_T type)
640 return sys_acl_get_file(path_p, type);
643 SMB_ACL_T vfswrap_sys_acl_get_fd(struct files_struct *fsp, int fd)
645 return sys_acl_get_fd(fd);
648 int vfswrap_sys_acl_clear_perms(struct connection_struct *conn, SMB_ACL_PERMSET_T permset)
650 return sys_acl_clear_perms(permset);
653 int vfswrap_sys_acl_add_perm(struct connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
655 return sys_acl_add_perm(permset, perm);
658 char * vfswrap_sys_acl_to_text(struct connection_struct *conn, SMB_ACL_T theacl, ssize_t *plen)
660 return sys_acl_to_text(theacl, plen);
663 SMB_ACL_T vfswrap_sys_acl_init(struct connection_struct *conn, int count)
665 return sys_acl_init(count);
668 int vfswrap_sys_acl_create_entry(struct connection_struct *conn, SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
670 return sys_acl_create_entry(pacl, pentry);
673 int vfswrap_sys_acl_set_tag_type(struct connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
675 return sys_acl_set_tag_type(entry, tagtype);
678 int vfswrap_sys_acl_set_qualifier(struct connection_struct *conn, SMB_ACL_ENTRY_T entry, void *qual)
680 return sys_acl_set_qualifier(entry, qual);
683 int vfswrap_sys_acl_set_permset(struct connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
685 return sys_acl_set_permset(entry, permset);
688 int vfswrap_sys_acl_valid(struct connection_struct *conn, SMB_ACL_T theacl )
690 return sys_acl_valid(theacl );
693 int vfswrap_sys_acl_set_file(struct connection_struct *conn, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
695 return sys_acl_set_file(name, acltype, theacl);
698 int vfswrap_sys_acl_set_fd(struct files_struct *fsp, int fd, SMB_ACL_T theacl)
700 return sys_acl_set_fd(fd, theacl);
703 int vfswrap_sys_acl_delete_def_file(struct connection_struct *conn, const char *path)
705 return sys_acl_delete_def_file(path);
708 int vfswrap_sys_acl_get_perm(struct connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
710 return sys_acl_get_perm(permset, perm);
713 int vfswrap_sys_acl_free_text(struct connection_struct *conn, char *text)
715 return sys_acl_free_text(text);
718 int vfswrap_sys_acl_free_acl(struct connection_struct *conn, SMB_ACL_T posix_acl)
720 return sys_acl_free_acl(posix_acl);
723 int vfswrap_sys_acl_free_qualifier(struct connection_struct *conn, void *qualifier, SMB_ACL_TAG_T tagtype)
725 return sys_acl_free_qualifier(qualifier, tagtype);