Fix an error where the SK Offset was truncated to 16 bits. Variables needed
[Samba/gbeck.git] / source / smbd / vfs-wrap.c
blobbae304096cefcf88be82e1b8500eb8c161665e20
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 #undef DBGC_CLASS
24 #define DBGC_CLASS DBGC_VFS
27 /* Check for NULL pointer parameters in vfswrap_* functions */
29 /* We don't want to have NULL function pointers lying around. Someone
30 is sure to try and execute them. These stubs are used to prevent
31 this possibility. */
33 int vfswrap_dummy_connect(connection_struct *conn, const char *service, const char *user)
35 return 0; /* Return >= 0 for success */
38 void vfswrap_dummy_disconnect(connection_struct *conn)
42 /* Disk operations */
44 SMB_BIG_UINT vfswrap_disk_free(connection_struct *conn, const char *path, BOOL small_query, SMB_BIG_UINT *bsize,
45 SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
47 SMB_BIG_UINT result;
49 result = sys_disk_free(path, small_query, bsize, dfree, dsize);
50 return result;
53 /* Directory operations */
55 DIR *vfswrap_opendir(connection_struct *conn, const char *fname)
57 DIR *result;
59 START_PROFILE(syscall_opendir);
60 result = opendir(fname);
61 END_PROFILE(syscall_opendir);
62 return result;
65 struct dirent *vfswrap_readdir(connection_struct *conn, DIR *dirp)
67 struct dirent *result;
69 START_PROFILE(syscall_readdir);
70 result = readdir(dirp);
71 END_PROFILE(syscall_readdir);
72 return result;
75 int vfswrap_mkdir(connection_struct *conn, const char *path, mode_t mode)
77 int result;
78 BOOL has_dacl = False;
80 START_PROFILE(syscall_mkdir);
82 if (lp_inherit_acls(SNUM(conn)) && (has_dacl = directory_has_default_acl(conn, parent_dirname(path))))
83 mode = 0777;
85 result = mkdir(path, mode);
87 if (result == 0 && !has_dacl) {
89 * We need to do this as the default behavior of POSIX ACLs
90 * is to set the mask to be the requested group permission
91 * bits, not the group permission bits to be the requested
92 * group permission bits. This is not what we want, as it will
93 * mess up any inherited ACL bits that were set. JRA.
95 int saved_errno = errno; /* We may get ENOSYS */
96 if (conn->vfs_ops.chmod_acl != NULL) {
97 if ((conn->vfs_ops.chmod_acl(conn, path, mode) == -1) && (errno == ENOSYS))
98 errno = saved_errno;
102 END_PROFILE(syscall_mkdir);
103 return result;
106 int vfswrap_rmdir(connection_struct *conn, const char *path)
108 int result;
110 START_PROFILE(syscall_rmdir);
111 result = rmdir(path);
112 END_PROFILE(syscall_rmdir);
113 return result;
116 int vfswrap_closedir(connection_struct *conn, DIR *dirp)
118 int result;
120 START_PROFILE(syscall_closedir);
121 result = closedir(dirp);
122 END_PROFILE(syscall_closedir);
123 return result;
126 /* File operations */
128 int vfswrap_open(connection_struct *conn, const char *fname, int flags, mode_t mode)
130 int result;
132 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);
154 result = sys_read(fd, data, n);
155 END_PROFILE(syscall_read);
156 return result;
159 ssize_t vfswrap_write(files_struct *fsp, int fd, const void *data, size_t n)
161 ssize_t result;
163 START_PROFILE_BYTES(syscall_write, n);
164 result = sys_write(fd, data, n);
165 END_PROFILE(syscall_write);
166 return result;
169 SMB_OFF_T vfswrap_lseek(files_struct *fsp, int filedes, SMB_OFF_T offset, int whence)
171 SMB_OFF_T result = 0;
173 START_PROFILE(syscall_lseek);
175 /* Cope with 'stat' file opens. */
176 if (filedes != -1)
177 result = sys_lseek(filedes, offset, whence);
180 * We want to maintain the fiction that we can seek
181 * on a fifo for file system purposes. This allows
182 * people to set up UNIX fifo's that feed data to Windows
183 * applications. JRA.
186 if((result == -1) && (errno == ESPIPE)) {
187 result = 0;
188 errno = 0;
191 END_PROFILE(syscall_lseek);
192 return result;
195 ssize_t vfswrap_sendfile(int tofd, struct files_struct *fsp, int fromfd, const DATA_BLOB *hdr,
196 SMB_OFF_T offset, size_t n)
198 ssize_t result;
200 START_PROFILE_BYTES(syscall_sendfile, n);
201 result = sys_sendfile(tofd, fromfd, hdr, offset, n);
202 END_PROFILE(syscall_sendfile);
203 return result;
206 int vfswrap_rename(connection_struct *conn, const char *old, const char *new)
208 int result;
210 START_PROFILE(syscall_rename);
211 result = rename(old, new);
212 END_PROFILE(syscall_rename);
213 return result;
216 int vfswrap_fsync(files_struct *fsp, int fd)
218 #ifdef HAVE_FSYNC
219 int result;
221 START_PROFILE(syscall_fsync);
223 result = fsync(fd);
224 END_PROFILE(syscall_fsync);
225 return result;
226 #else
227 return 0;
228 #endif
231 int vfswrap_stat(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf)
233 int result;
235 START_PROFILE(syscall_stat);
236 result = sys_stat(fname, sbuf);
237 END_PROFILE(syscall_stat);
238 return result;
241 int vfswrap_fstat(files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf)
243 int result;
245 START_PROFILE(syscall_fstat);
246 result = sys_fstat(fd, sbuf);
247 END_PROFILE(syscall_fstat);
248 return result;
251 int vfswrap_lstat(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf)
253 int result;
255 START_PROFILE(syscall_lstat);
256 result = sys_lstat(path, sbuf);
257 END_PROFILE(syscall_lstat);
258 return result;
261 int vfswrap_unlink(connection_struct *conn, const char *path)
263 int result;
265 START_PROFILE(syscall_unlink);
266 result = unlink(path);
267 END_PROFILE(syscall_unlink);
268 return result;
271 int vfswrap_chmod(connection_struct *conn, const char *path, mode_t mode)
273 int result;
275 START_PROFILE(syscall_chmod);
278 * We need to do this due to the fact that the default POSIX ACL
279 * chmod modifies the ACL *mask* for the group owner, not the
280 * group owner bits directly. JRA.
284 if (conn->vfs_ops.chmod_acl != NULL) {
285 int saved_errno = errno; /* We might get ENOSYS */
286 if ((result = conn->vfs_ops.chmod_acl(conn, path, mode)) == 0) {
287 END_PROFILE(syscall_chmod);
288 return result;
290 /* Error - return the old errno. */
291 errno = saved_errno;
294 result = chmod(path, mode);
295 END_PROFILE(syscall_chmod);
296 return result;
299 int vfswrap_fchmod(files_struct *fsp, int fd, mode_t mode)
301 int result;
302 struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops;
304 START_PROFILE(syscall_fchmod);
307 * We need to do this due to the fact that the default POSIX ACL
308 * chmod modifies the ACL *mask* for the group owner, not the
309 * group owner bits directly. JRA.
312 if (vfs_ops->fchmod_acl != NULL) {
313 int saved_errno = errno; /* We might get ENOSYS */
314 if ((result = vfs_ops->fchmod_acl(fsp, fd, mode)) == 0) {
315 END_PROFILE(syscall_chmod);
316 return result;
318 /* Error - return the old errno. */
319 errno = saved_errno;
322 result = fchmod(fd, mode);
323 END_PROFILE(syscall_fchmod);
324 return result;
327 int vfswrap_chown(connection_struct *conn, const char *path, uid_t uid, gid_t gid)
329 int result;
331 START_PROFILE(syscall_chown);
332 result = sys_chown(path, uid, gid);
333 END_PROFILE(syscall_chown);
334 return result;
337 int vfswrap_fchown(files_struct *fsp, int fd, uid_t uid, gid_t gid)
339 int result;
341 START_PROFILE(syscall_fchown);
343 result = fchown(fd, uid, gid);
344 END_PROFILE(syscall_fchown);
345 return result;
348 int vfswrap_chdir(connection_struct *conn, const char *path)
350 int result;
352 START_PROFILE(syscall_chdir);
353 result = chdir(path);
354 END_PROFILE(syscall_chdir);
355 return result;
358 char *vfswrap_getwd(connection_struct *conn, char *path)
360 char *result;
362 START_PROFILE(syscall_getwd);
363 result = sys_getwd(path);
364 END_PROFILE(syscall_getwd);
365 return result;
368 int vfswrap_utime(connection_struct *conn, const char *path, struct utimbuf *times)
370 int result;
372 START_PROFILE(syscall_utime);
373 result = utime(path, times);
374 END_PROFILE(syscall_utime);
375 return result;
378 /*********************************************************************
379 A version of ftruncate that will write the space on disk if strict
380 allocate is set.
381 **********************************************************************/
383 static int strict_allocate_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len)
385 struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops;
386 SMB_STRUCT_STAT st;
387 SMB_OFF_T currpos = vfs_ops->lseek(fsp, fd, 0, SEEK_CUR);
388 unsigned char zero_space[4096];
389 SMB_OFF_T space_to_write;
391 if (currpos == -1)
392 return -1;
394 if (vfs_ops->fstat(fsp, fd, &st) == -1)
395 return -1;
397 space_to_write = len - st.st_size;
399 #ifdef S_ISFIFO
400 if (S_ISFIFO(st.st_mode))
401 return 0;
402 #endif
404 if (st.st_size == len)
405 return 0;
407 /* Shrink - just ftruncate. */
408 if (st.st_size > len)
409 return sys_ftruncate(fd, len);
411 /* Write out the real space on disk. */
412 if (vfs_ops->lseek(fsp, fd, st.st_size, SEEK_SET) != st.st_size)
413 return -1;
415 space_to_write = len - st.st_size;
417 memset(zero_space, '\0', sizeof(zero_space));
418 while ( space_to_write > 0) {
419 SMB_OFF_T retlen;
420 SMB_OFF_T current_len_to_write = MIN(sizeof(zero_space),space_to_write);
422 retlen = vfs_ops->write(fsp,fsp->fd,(char *)zero_space,current_len_to_write);
423 if (retlen <= 0)
424 return -1;
426 space_to_write -= retlen;
429 /* Seek to where we were */
430 if (vfs_ops->lseek(fsp, fd, currpos, SEEK_SET) != currpos)
431 return -1;
433 return 0;
436 int vfswrap_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len)
438 int result = -1;
439 struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops;
440 SMB_STRUCT_STAT st;
441 char c = 0;
442 SMB_OFF_T currpos;
444 START_PROFILE(syscall_ftruncate);
446 if (lp_strict_allocate(SNUM(fsp->conn))) {
447 result = strict_allocate_ftruncate(fsp, fd, len);
448 END_PROFILE(syscall_ftruncate);
449 return result;
452 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
453 sys_ftruncate if the system supports it. Then I discovered that
454 you can have some filesystems that support ftruncate
455 expansion and some that don't! On Linux fat can't do
456 ftruncate extend but ext2 can. */
458 result = sys_ftruncate(fd, len);
459 if (result == 0)
460 goto done;
462 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
463 extend a file with ftruncate. Provide alternate implementation
464 for this */
465 currpos = vfs_ops->lseek(fsp, fd, 0, SEEK_CUR);
466 if (currpos == -1) {
467 goto done;
470 /* Do an fstat to see if the file is longer than the requested
471 size in which case the ftruncate above should have
472 succeeded or shorter, in which case seek to len - 1 and
473 write 1 byte of zero */
474 if (vfs_ops->fstat(fsp, fd, &st) == -1) {
475 goto done;
478 #ifdef S_ISFIFO
479 if (S_ISFIFO(st.st_mode)) {
480 result = 0;
481 goto done;
483 #endif
485 if (st.st_size == len) {
486 result = 0;
487 goto done;
490 if (st.st_size > len) {
491 /* the sys_ftruncate should have worked */
492 goto done;
495 if (vfs_ops->lseek(fsp, fd, len-1, SEEK_SET) != len -1)
496 goto done;
498 if (vfs_ops->write(fsp, fd, &c, 1)!=1)
499 goto done;
501 /* Seek to where we were */
502 if (vfs_ops->lseek(fsp, fd, currpos, SEEK_SET) != currpos)
503 goto done;
504 result = 0;
506 done:
508 END_PROFILE(syscall_ftruncate);
509 return result;
512 BOOL vfswrap_lock(files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
514 BOOL result;
516 START_PROFILE(syscall_fcntl_lock);
518 result = fcntl_lock(fd, op, offset, count,type);
519 END_PROFILE(syscall_fcntl_lock);
520 return result;
523 int vfswrap_symlink(connection_struct *conn, const char *oldpath, const char *newpath)
525 int result;
527 START_PROFILE(syscall_symlink);
528 result = sys_symlink(oldpath, newpath);
529 END_PROFILE(syscall_symlink);
530 return result;
533 int vfswrap_readlink(connection_struct *conn, const char *path, char *buf, size_t bufsiz)
535 int result;
537 START_PROFILE(syscall_readlink);
538 result = sys_readlink(path, buf, bufsiz);
539 END_PROFILE(syscall_readlink);
540 return result;
543 int vfswrap_link(connection_struct *conn, const char *oldpath, const char *newpath)
545 int result;
547 START_PROFILE(syscall_link);
548 result = sys_link(oldpath, newpath);
549 END_PROFILE(syscall_link);
550 return result;
553 int vfswrap_mknod(connection_struct *conn, const char *pathname, mode_t mode, SMB_DEV_T dev)
555 int result;
557 START_PROFILE(syscall_mknod);
558 result = sys_mknod(pathname, mode, dev);
559 END_PROFILE(syscall_mknod);
560 return result;
563 char *vfswrap_realpath(connection_struct *conn, const char *path, char *resolved_path)
565 char *result;
567 START_PROFILE(syscall_realpath);
568 result = sys_realpath(path, resolved_path);
569 END_PROFILE(syscall_realpath);
570 return result;
573 size_t vfswrap_fget_nt_acl(files_struct *fsp, int fd, SEC_DESC **ppdesc)
575 size_t result;
577 START_PROFILE(fget_nt_acl);
578 result = get_nt_acl(fsp, ppdesc);
579 END_PROFILE(fget_nt_acl);
580 return result;
583 size_t vfswrap_get_nt_acl(files_struct *fsp, const char *name, SEC_DESC **ppdesc)
585 size_t result;
587 START_PROFILE(get_nt_acl);
588 result = get_nt_acl(fsp, ppdesc);
589 END_PROFILE(get_nt_acl);
590 return result;
593 BOOL vfswrap_fset_nt_acl(files_struct *fsp, int fd, uint32 security_info_sent, SEC_DESC *psd)
595 BOOL result;
597 START_PROFILE(fset_nt_acl);
598 result = set_nt_acl(fsp, security_info_sent, psd);
599 END_PROFILE(fset_nt_acl);
600 return result;
603 BOOL vfswrap_set_nt_acl(files_struct *fsp, const char *name, uint32 security_info_sent, SEC_DESC *psd)
605 BOOL result;
607 START_PROFILE(set_nt_acl);
608 result = set_nt_acl(fsp, security_info_sent, psd);
609 END_PROFILE(set_nt_acl);
610 return result;
613 int vfswrap_chmod_acl(connection_struct *conn, const char *name, mode_t mode)
615 int result;
617 START_PROFILE(chmod_acl);
618 result = chmod_acl(conn, name, mode);
619 END_PROFILE(chmod_acl);
620 return result;
623 int vfswrap_fchmod_acl(files_struct *fsp, int fd, mode_t mode)
625 int result;
627 START_PROFILE(fchmod_acl);
628 result = fchmod_acl(fsp, fd, mode);
629 END_PROFILE(fchmod_acl);
630 return result;
633 int vfswrap_sys_acl_get_entry(struct connection_struct *conn, SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
635 return sys_acl_get_entry(theacl, entry_id, entry_p);
638 int vfswrap_sys_acl_get_tag_type(struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
640 return sys_acl_get_tag_type(entry_d, tag_type_p);
643 int vfswrap_sys_acl_get_permset(struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
645 return sys_acl_get_permset(entry_d, permset_p);
648 void * vfswrap_sys_acl_get_qualifier(struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d)
650 return sys_acl_get_qualifier(entry_d);
653 SMB_ACL_T vfswrap_sys_acl_get_file(struct connection_struct *conn, const char *path_p, SMB_ACL_TYPE_T type)
655 return sys_acl_get_file(path_p, type);
658 SMB_ACL_T vfswrap_sys_acl_get_fd(struct files_struct *fsp, int fd)
660 return sys_acl_get_fd(fd);
663 int vfswrap_sys_acl_clear_perms(struct connection_struct *conn, SMB_ACL_PERMSET_T permset)
665 return sys_acl_clear_perms(permset);
668 int vfswrap_sys_acl_add_perm(struct connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
670 return sys_acl_add_perm(permset, perm);
673 char * vfswrap_sys_acl_to_text(struct connection_struct *conn, SMB_ACL_T theacl, ssize_t *plen)
675 return sys_acl_to_text(theacl, plen);
678 SMB_ACL_T vfswrap_sys_acl_init(struct connection_struct *conn, int count)
680 return sys_acl_init(count);
683 int vfswrap_sys_acl_create_entry(struct connection_struct *conn, SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
685 return sys_acl_create_entry(pacl, pentry);
688 int vfswrap_sys_acl_set_tag_type(struct connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
690 return sys_acl_set_tag_type(entry, tagtype);
693 int vfswrap_sys_acl_set_qualifier(struct connection_struct *conn, SMB_ACL_ENTRY_T entry, void *qual)
695 return sys_acl_set_qualifier(entry, qual);
698 int vfswrap_sys_acl_set_permset(struct connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
700 return sys_acl_set_permset(entry, permset);
703 int vfswrap_sys_acl_valid(struct connection_struct *conn, SMB_ACL_T theacl )
705 return sys_acl_valid(theacl );
708 int vfswrap_sys_acl_set_file(struct connection_struct *conn, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
710 return sys_acl_set_file(name, acltype, theacl);
713 int vfswrap_sys_acl_set_fd(struct files_struct *fsp, int fd, SMB_ACL_T theacl)
715 return sys_acl_set_fd(fd, theacl);
718 int vfswrap_sys_acl_delete_def_file(struct connection_struct *conn, const char *path)
720 return sys_acl_delete_def_file(path);
723 int vfswrap_sys_acl_get_perm(struct connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
725 return sys_acl_get_perm(permset, perm);
728 int vfswrap_sys_acl_free_text(struct connection_struct *conn, char *text)
730 return sys_acl_free_text(text);
733 int vfswrap_sys_acl_free_acl(struct connection_struct *conn, SMB_ACL_T posix_acl)
735 return sys_acl_free_acl(posix_acl);
738 int vfswrap_sys_acl_free_qualifier(struct connection_struct *conn, void *qualifier, SMB_ACL_TAG_T tagtype)
740 return sys_acl_free_qualifier(qualifier, tagtype);