1/*
2   Unix SMB/CIFS implementation.
3   Wrap disk only vfs functions to sidestep dodgy compilers.
4   Copyright (C) Tim Potter 1998
5
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.
10
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.
15
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.
19*/
20
21#include "includes.h"
22
23#undef DBGC_CLASS
24#define DBGC_CLASS DBGC_VFS
25
26
27/* Check for NULL pointer parameters in vfswrap_* functions */
28
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. */
32
33#ifdef MAX_USB_ACCESS
34extern CON_STATISTIC *con_st;
35extern int binary_semaphore_post (int semid);
36extern int binary_semaphore_wait (int semid);
37#endif
38
39int vfswrap_dummy_connect(vfs_handle_struct *handle, connection_struct *conn, const char *service, const char *user)
40{
41    return 0;    /* Return >= 0 for success */
42}
43
44void vfswrap_dummy_disconnect(vfs_handle_struct *handle, connection_struct *conn)
45{
46
47}
48
49/* Disk operations */
50
51SMB_BIG_UINT vfswrap_disk_free(vfs_handle_struct *handle, connection_struct *conn, const char *path, BOOL small_query, SMB_BIG_UINT *bsize,
52			       SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
53{
54	SMB_BIG_UINT result;
55
56	result = sys_disk_free(path, small_query, bsize, dfree, dsize);
57	return result;
58}
59
60int vfswrap_get_quota(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
61{
62#ifdef HAVE_SYS_QUOTAS
63	int result;
64
65	START_PROFILE(syscall_get_quota);
66	result = sys_get_quota(conn->connectpath, qtype, id, qt);
67	END_PROFILE(syscall_get_quota);
68	return result;
69#else
70	errno = ENOSYS;
71	return -1;
72#endif
73}
74
75int vfswrap_set_quota(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
76{
77#ifdef HAVE_SYS_QUOTAS
78	int result;
79
80	START_PROFILE(syscall_set_quota);
81	result = sys_set_quota(conn->connectpath, qtype, id, qt);
82	END_PROFILE(syscall_set_quota);
83	return result;
84#else
85	errno = ENOSYS;
86	return -1;
87#endif
88}
89
90int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle, struct files_struct *fsp, SHADOW_COPY_DATA *shadow_copy_data, BOOL labels)
91{
92	errno = ENOSYS;
93	return -1;  /* Not implemented. */
94}
95
96/* Directory operations */
97
98DIR *vfswrap_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname)
99{
100	DIR *result;
101
102	START_PROFILE(syscall_opendir);
103	result = sys_opendir(fname);
104	END_PROFILE(syscall_opendir);
105	return result;
106}
107
108SMB_STRUCT_DIRENT *vfswrap_readdir(vfs_handle_struct *handle, connection_struct *conn, DIR *dirp)
109{
110	SMB_STRUCT_DIRENT *result;
111
112	START_PROFILE(syscall_readdir);
113	result = sys_readdir(dirp);
114	END_PROFILE(syscall_readdir);
115	return result;
116}
117
118void vfswrap_seekdir(vfs_handle_struct *handle, connection_struct *conn, DIR *dirp, long offset)
119{
120	START_PROFILE(syscall_seekdir);
121	sys_seekdir(dirp, offset);
122	END_PROFILE(syscall_seekdir);
123}
124
125long vfswrap_telldir(vfs_handle_struct *handle, connection_struct *conn, DIR *dirp)
126{
127	long result;
128	START_PROFILE(syscall_telldir);
129	result = sys_telldir(dirp);
130	END_PROFILE(syscall_telldir);
131	return result;
132}
133
134void vfswrap_rewinddir(vfs_handle_struct *handle, connection_struct *conn, DIR *dirp)
135{
136	START_PROFILE(syscall_rewinddir);
137	sys_rewinddir(dirp);
138	END_PROFILE(syscall_rewinddir);
139}
140
141int vfswrap_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode)
142{
143	int result;
144	BOOL has_dacl = False;
145
146	START_PROFILE(syscall_mkdir);
147
148	if (lp_inherit_acls(SNUM(conn)) && (has_dacl = directory_has_default_acl(conn, parent_dirname(path))))
149		mode = 0777;
150
151	result = mkdir(path, mode);
152
153	if (result == 0 && !has_dacl) {
154		/*
155		 * We need to do this as the default behavior of POSIX ACLs
156		 * is to set the mask to be the requested group permission
157		 * bits, not the group permission bits to be the requested
158		 * group permission bits. This is not what we want, as it will
159		 * mess up any inherited ACL bits that were set. JRA.
160		 */
161		int saved_errno = errno; /* We may get ENOSYS */
162		if ((SMB_VFS_CHMOD_ACL(conn, path, mode) == -1) && (errno == ENOSYS))
163			errno = saved_errno;
164	}
165
166	END_PROFILE(syscall_mkdir);
167	return result;
168}
169
170int vfswrap_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path)
171{
172	int result;
173
174	START_PROFILE(syscall_rmdir);
175	result = rmdir(path);
176	END_PROFILE(syscall_rmdir);
177	return result;
178}
179
180int vfswrap_closedir(vfs_handle_struct *handle, connection_struct *conn, DIR *dirp)
181{
182	int result;
183
184	START_PROFILE(syscall_closedir);
185	result = sys_closedir(dirp);
186	END_PROFILE(syscall_closedir);
187	return result;
188}
189
190/* File operations */
191
192int vfswrap_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode)
193{
194	int result;
195
196	/* Foxconn added start pling 07/12/2012 */
197	/* Do connection count check first */
198#if 0 //def MAX_USB_ACCESS  // pling removed 07/18/2012, In Win7, copy a folder with more than 15 files may have problems
199	if(con_st != NULL)
200	{
201		if ( ( con_st->num ) >= MAX_CON_NUM)
202			return -1;
203	}
204	//cprintf("*******%s(%d):con_st->num=%d\n", __FUNCTION__, __LINE__, con_st->num);
205#endif
206	/* Foxconn added end pling 07/12/2012 */
207
208	START_PROFILE(syscall_open);
209	result = sys_open(fname, flags, mode);
210	END_PROFILE(syscall_open);
211
212	/* Foxconn modified start pling 07/12/2012 */
213	/* Increment counter if open is successful */
214#if 0 //def MAX_USB_ACCESS  // pling removed 07/18/2012, In Win7, copy a folder with more than 15 files may have problems
215	if (result != -1 && con_st != NULL)
216	{
217		binary_semaphore_wait (con_st->sem_id);
218		++(con_st->num);
219		binary_semaphore_post (con_st->sem_id);
220	}
221#endif
222	/* Foxconn modified end pling 07/12/2012 */
223
224	return result;
225}
226
227int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp, int fd)
228{
229	int result;
230
231	START_PROFILE(syscall_close);
232
233	result = close(fd);
234	END_PROFILE(syscall_close);
235
236#if 0 //def MAX_USB_ACCESS  // pling removed 07/18/2012, In Win7, copy a folder with more than 15 files may have problems
237	/* Foxconn modified start pling 07/12/2012 */
238	/* Increment counter if close is successful */
239	//if(con_st != NULL)
240	if (result != -1 && con_st != NULL)
241	/* Foxconn modified end pling 07/12/2012 */
242    {
243        binary_semaphore_wait (con_st->sem_id);
244        --(con_st->num);
245        binary_semaphore_post (con_st->sem_id);
246    }
247    //cprintf("*******%s(%d):con_st->num=%d\n", __FUNCTION__, __LINE__, con_st->num);
248#endif
249
250	return result;
251}
252
253ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, int fd, void *data, size_t n)
254{
255	ssize_t result;
256
257	START_PROFILE_BYTES(syscall_read, n);
258	result = sys_read(fd, data, n);
259	END_PROFILE(syscall_read);
260	return result;
261}
262
263/* Foxconn modified start pling 11/18/2009 */
264//ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, int fd, void *data,
265//			size_t n, SMB_OFF_T offset)
266ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, int fd, void *data,
267			size_t n, SMB_BIG_UINT offset)
268/* Foxconn modified end pling 11/18/2009 */
269{
270	ssize_t result;
271
272#if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
273	START_PROFILE_BYTES(syscall_pread, n);
274	result = sys_pread(fd, data, n, offset);
275	END_PROFILE(syscall_pread);
276
277	if (result == -1 && errno == ESPIPE) {
278		/* Maintain the fiction that pipes can be seeked (sought?) on. */
279		result = SMB_VFS_READ(fsp, fd, data, n);
280		fsp->pos = 0;
281	}
282
283#else /* HAVE_PREAD */
284	SMB_OFF_T   curr;
285	int lerrno;
286
287	curr = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR);
288	if (curr == -1 && errno == ESPIPE) {
289		/* Maintain the fiction that pipes can be seeked (sought?) on. */
290		result = SMB_VFS_READ(fsp, fd, data, n);
291		fsp->pos = 0;
292		return result;
293	}
294
295	if (SMB_VFS_LSEEK(fsp, fd, offset, SEEK_SET) == -1) {
296		return -1;
297	}
298
299	errno = 0;
300	result = SMB_VFS_READ(fsp, fd, data, n);
301	lerrno = errno;
302
303	SMB_VFS_LSEEK(fsp, fd, curr, SEEK_SET);
304	errno = lerrno;
305
306#endif /* HAVE_PREAD */
307
308	return result;
309}
310
311ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, int fd, const void *data, size_t n)
312{
313	ssize_t result;
314
315	START_PROFILE_BYTES(syscall_write, n);
316	result = sys_write(fd, data, n);
317	END_PROFILE(syscall_write);
318	return result;
319}
320
321/* Foxconn modified start pling 11/18/2009 */
322//ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, int fd, const void *data,
323//			size_t n, SMB_OFF_T offset)
324ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, int fd, const void *data,
325			size_t n, SMB_BIG_UINT offset)
326/* Foxconn modified end pling 11/18/2009 */
327{
328	ssize_t result;
329
330#if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
331	START_PROFILE_BYTES(syscall_pwrite, n);
332	result = sys_pwrite(fd, data, n, offset);
333	END_PROFILE(syscall_pwrite);
334
335	if (result == -1 && errno == ESPIPE) {
336		/* Maintain the fiction that pipes can be sought on. */
337		result = SMB_VFS_WRITE(fsp, fd, data, n);
338	}
339
340#else /* HAVE_PWRITE */
341	SMB_OFF_T   curr;
342	int         lerrno;
343
344	curr = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR);
345	if (curr == -1) {
346		return -1;
347	}
348
349	if (SMB_VFS_LSEEK(fsp, fd, offset, SEEK_SET) == -1) {
350		return -1;
351	}
352
353	result = SMB_VFS_WRITE(fsp, fd, data, n);
354	lerrno = errno;
355
356	SMB_VFS_LSEEK(fsp, fd, curr, SEEK_SET);
357	errno = lerrno;
358
359#endif /* HAVE_PWRITE */
360
361	return result;
362}
363
364/* Foxconn modified start pling 11/18/2009 */
365//SMB_OFF_T vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, int filedes, SMB_OFF_T offset, int whence)
366SMB_BIG_UINT vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, int filedes, SMB_BIG_UINT offset, int whence)
367/* Foxconn modified end pling 11/18/2009 */
368{
369	//SMB_OFF_T result = 0;
370	SMB_BIG_UINT result = 0;
371
372	START_PROFILE(syscall_lseek);
373
374	/* Cope with 'stat' file opens. */
375	if (filedes != -1)
376		result = sys_lseek(filedes, offset, whence);
377
378	/*
379	 * We want to maintain the fiction that we can seek
380	 * on a fifo for file system purposes. This allows
381	 * people to set up UNIX fifo's that feed data to Windows
382	 * applications. JRA.
383	 */
384
385	if((result == -1) && (errno == ESPIPE)) {
386		result = 0;
387		errno = 0;
388	}
389
390	END_PROFILE(syscall_lseek);
391	return result;
392}
393
394ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fsp, int fromfd, const DATA_BLOB *hdr,
395			SMB_OFF_T offset, size_t n)
396{
397	ssize_t result;
398
399	START_PROFILE_BYTES(syscall_sendfile, n);
400	result = sys_sendfile(tofd, fromfd, hdr, offset, n);
401	END_PROFILE(syscall_sendfile);
402	return result;
403}
404
405/*********************************************************
406 For rename across filesystems Patch from Warren Birnbaum
407 <warrenb@hpcvscdp.cv.hp.com>
408**********************************************************/
409
410static int copy_reg(const char *source, const char *dest)
411{
412	SMB_STRUCT_STAT source_stats;
413	int saved_errno;
414	int ifd = -1;
415	int ofd = -1;
416
417	if (sys_lstat (source, &source_stats) == -1)
418		return -1;
419
420	if (!S_ISREG (source_stats.st_mode))
421		return -1;
422
423	if((ifd = sys_open (source, O_RDONLY, 0)) < 0)
424		return -1;
425
426	if (unlink (dest) && errno != ENOENT)
427		return -1;
428
429#ifdef O_NOFOLLOW
430	if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0600)) < 0 )
431#else
432	if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC , 0600)) < 0 )
433#endif
434		goto err;
435
436	if (transfer_file(ifd, ofd, (size_t)-1) == -1)
437		goto err;
438
439	/*
440	 * Try to preserve ownership.  For non-root it might fail, but that's ok.
441	 * But root probably wants to know, e.g. if NFS disallows it.
442	 */
443
444#ifdef HAVE_FCHOWN
445	if ((fchown(ofd, source_stats.st_uid, source_stats.st_gid) == -1) && (errno != EPERM))
446#else
447	if ((chown(dest, source_stats.st_uid, source_stats.st_gid) == -1) && (errno != EPERM))
448#endif
449		goto err;
450
451	/*
452	 * fchown turns off set[ug]id bits for non-root,
453	 * so do the chmod last.
454	 */
455
456#if defined(HAVE_FCHMOD)
457	if (fchmod (ofd, source_stats.st_mode & 07777))
458#else
459	if (chmod (dest, source_stats.st_mode & 07777))
460#endif
461		goto err;
462
463	if (close (ifd) == -1)
464		goto err;
465
466	if (close (ofd) == -1)
467		return -1;
468
469	/* Try to copy the old file's modtime and access time.  */
470	{
471		struct utimbuf tv;
472
473		tv.actime = source_stats.st_atime;
474		tv.modtime = source_stats.st_mtime;
475		utime(dest, &tv);
476	}
477
478	if (unlink (source) == -1)
479		return -1;
480
481	return 0;
482
483  err:
484
485	saved_errno = errno;
486	if (ifd != -1)
487		close(ifd);
488	if (ofd != -1)
489		close(ofd);
490	errno = saved_errno;
491	return -1;
492}
493
494int vfswrap_rename(vfs_handle_struct *handle, connection_struct *conn, const char *old, const char *new)
495{
496	int result;
497
498	START_PROFILE(syscall_rename);
499	result = rename(old, new);
500	if (errno == EXDEV) {
501		/* Rename across filesystems needed. */
502		result = copy_reg(old, new);
503	}
504
505	END_PROFILE(syscall_rename);
506	return result;
507}
508
509int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp, int fd)
510{
511#ifdef HAVE_FSYNC
512	int result;
513
514	START_PROFILE(syscall_fsync);
515	result = fsync(fd);
516	END_PROFILE(syscall_fsync);
517	return result;
518#else
519	return 0;
520#endif
521}
522
523int vfswrap_stat(vfs_handle_struct *handle, connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf)
524{
525	int result;
526
527	START_PROFILE(syscall_stat);
528	result = sys_stat(fname, sbuf);
529	END_PROFILE(syscall_stat);
530
531	return result;
532}
533
534int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf)
535{
536	int result;
537
538	START_PROFILE(syscall_fstat);
539	result = sys_fstat(fd, sbuf);
540	END_PROFILE(syscall_fstat);
541	return result;
542}
543
544int vfswrap_lstat(vfs_handle_struct *handle, connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf)
545{
546	int result;
547
548	START_PROFILE(syscall_lstat);
549	result = sys_lstat(path, sbuf);
550	END_PROFILE(syscall_lstat);
551	return result;
552}
553
554int vfswrap_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path)
555{
556	int result;
557
558	START_PROFILE(syscall_unlink);
559	result = unlink(path);
560	END_PROFILE(syscall_unlink);
561	return result;
562}
563
564int vfswrap_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode)
565{
566	int result;
567
568	START_PROFILE(syscall_chmod);
569
570	/*
571	 * We need to do this due to the fact that the default POSIX ACL
572	 * chmod modifies the ACL *mask* for the group owner, not the
573	 * group owner bits directly. JRA.
574	 */
575
576
577	{
578		int saved_errno = errno; /* We might get ENOSYS */
579		if ((result = SMB_VFS_CHMOD_ACL(conn, path, mode)) == 0) {
580			END_PROFILE(syscall_chmod);
581			return result;
582		}
583		/* Error - return the old errno. */
584		errno = saved_errno;
585	}
586
587	result = chmod(path, mode);
588	END_PROFILE(syscall_chmod);
589	return result;
590}
591
592int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode)
593{
594	int result;
595
596	START_PROFILE(syscall_fchmod);
597
598	/*
599	 * We need to do this due to the fact that the default POSIX ACL
600	 * chmod modifies the ACL *mask* for the group owner, not the
601	 * group owner bits directly. JRA.
602	 */
603
604	{
605		int saved_errno = errno; /* We might get ENOSYS */
606		if ((result = SMB_VFS_FCHMOD_ACL(fsp, fd, mode)) == 0) {
607			END_PROFILE(syscall_chmod);
608			return result;
609		}
610		/* Error - return the old errno. */
611		errno = saved_errno;
612	}
613
614#if defined(HAVE_FCHMOD)
615	result = fchmod(fd, mode);
616#else
617	result = -1;
618	errno = ENOSYS;
619#endif
620
621	END_PROFILE(syscall_fchmod);
622	return result;
623}
624
625int vfswrap_chown(vfs_handle_struct *handle, connection_struct *conn, const char *path, uid_t uid, gid_t gid)
626{
627	int result;
628
629	START_PROFILE(syscall_chown);
630	result = sys_chown(path, uid, gid);
631	END_PROFILE(syscall_chown);
632	return result;
633}
634
635int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, int fd, uid_t uid, gid_t gid)
636{
637#ifdef HAVE_FCHOWN
638	int result;
639
640	START_PROFILE(syscall_fchown);
641	result = fchown(fd, uid, gid);
642	END_PROFILE(syscall_fchown);
643	return result;
644#else
645	errno = ENOSYS;
646	return -1;
647#endif
648}
649
650int vfswrap_chdir(vfs_handle_struct *handle, connection_struct *conn, const char *path)
651{
652	int result;
653
654	START_PROFILE(syscall_chdir);
655	result = chdir(path);
656	END_PROFILE(syscall_chdir);
657	return result;
658}
659
660char *vfswrap_getwd(vfs_handle_struct *handle, connection_struct *conn, char *path)
661{
662	char *result;
663
664	START_PROFILE(syscall_getwd);
665	result = sys_getwd(path);
666	END_PROFILE(syscall_getwd);
667	return result;
668}
669
670int vfswrap_utime(vfs_handle_struct *handle, connection_struct *conn, const char *path, struct utimbuf *times)
671{
672	int result;
673
674	START_PROFILE(syscall_utime);
675	result = utime(path, times);
676	END_PROFILE(syscall_utime);
677	return result;
678}
679
680/*********************************************************************
681 A version of ftruncate that will write the space on disk if strict
682 allocate is set.
683**********************************************************************/
684
685static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T len)
686{
687	SMB_STRUCT_STAT st;
688	SMB_OFF_T currpos = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR);
689	unsigned char zero_space[4096];
690	SMB_OFF_T space_to_write;
691
692	if (currpos == -1)
693		return -1;
694
695	if (SMB_VFS_FSTAT(fsp, fd, &st) == -1)
696		return -1;
697
698	space_to_write = len - st.st_size;
699
700#ifdef S_ISFIFO
701	if (S_ISFIFO(st.st_mode))
702		return 0;
703#endif
704
705	if (st.st_size == len)
706		return 0;
707
708	/* Shrink - just ftruncate. */
709	if (st.st_size > len)
710		return sys_ftruncate(fd, len);
711
712	/* Write out the real space on disk. */
713	if (SMB_VFS_LSEEK(fsp, fd, st.st_size, SEEK_SET) != st.st_size)
714		return -1;
715
716	space_to_write = len - st.st_size;
717
718	memset(zero_space, '\0', sizeof(zero_space));
719	while ( space_to_write > 0) {
720		SMB_OFF_T retlen;
721		SMB_OFF_T current_len_to_write = MIN(sizeof(zero_space),space_to_write);
722
723		retlen = SMB_VFS_WRITE(fsp,fsp->fd,(char *)zero_space,current_len_to_write);
724		if (retlen <= 0)
725			return -1;
726
727		space_to_write -= retlen;
728	}
729
730	/* Seek to where we were */
731	if (SMB_VFS_LSEEK(fsp, fd, currpos, SEEK_SET) != currpos)
732		return -1;
733
734	return 0;
735}
736
737int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T len)
738{
739	int result = -1;
740	SMB_STRUCT_STAT st;
741	char c = 0;
742	SMB_OFF_T currpos;
743
744	START_PROFILE(syscall_ftruncate);
745
746	if (lp_strict_allocate(SNUM(fsp->conn))) {
747		result = strict_allocate_ftruncate(handle, fsp, fd, len);
748		END_PROFILE(syscall_ftruncate);
749		return result;
750	}
751
752	/* we used to just check HAVE_FTRUNCATE_EXTEND and only use
753	   sys_ftruncate if the system supports it. Then I discovered that
754	   you can have some filesystems that support ftruncate
755	   expansion and some that don't! On Linux fat can't do
756	   ftruncate extend but ext2 can. */
757
758	result = sys_ftruncate(fd, len);
759	if (result == 0)
760		goto done;
761
762	/* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
763	   extend a file with ftruncate. Provide alternate implementation
764	   for this */
765	currpos = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR);
766	if (currpos == -1) {
767		goto done;
768	}
769
770	/* Do an fstat to see if the file is longer than the requested
771	   size in which case the ftruncate above should have
772	   succeeded or shorter, in which case seek to len - 1 and
773	   write 1 byte of zero */
774	if (SMB_VFS_FSTAT(fsp, fd, &st) == -1) {
775		goto done;
776	}
777
778#ifdef S_ISFIFO
779	if (S_ISFIFO(st.st_mode)) {
780		result = 0;
781		goto done;
782	}
783#endif
784
785	if (st.st_size == len) {
786		result = 0;
787		goto done;
788	}
789
790	if (st.st_size > len) {
791		/* the sys_ftruncate should have worked */
792		goto done;
793	}
794
795	if (SMB_VFS_LSEEK(fsp, fd, len-1, SEEK_SET) != len -1)
796		goto done;
797
798	if (SMB_VFS_WRITE(fsp, fd, &c, 1)!=1)
799		goto done;
800
801	/* Seek to where we were */
802	if (SMB_VFS_LSEEK(fsp, fd, currpos, SEEK_SET) != currpos)
803		goto done;
804	result = 0;
805
806  done:
807
808	END_PROFILE(syscall_ftruncate);
809	return result;
810}
811
812BOOL vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
813{
814	BOOL result;
815
816	START_PROFILE(syscall_fcntl_lock);
817	result =  fcntl_lock(fd, op, offset, count,type);
818	END_PROFILE(syscall_fcntl_lock);
819	return result;
820}
821
822int vfswrap_symlink(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath)
823{
824	int result;
825
826	START_PROFILE(syscall_symlink);
827	result = sys_symlink(oldpath, newpath);
828	END_PROFILE(syscall_symlink);
829	return result;
830}
831
832int vfswrap_readlink(vfs_handle_struct *handle, connection_struct *conn, const char *path, char *buf, size_t bufsiz)
833{
834	int result;
835
836	START_PROFILE(syscall_readlink);
837	result = sys_readlink(path, buf, bufsiz);
838	END_PROFILE(syscall_readlink);
839	return result;
840}
841
842int vfswrap_link(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath)
843{
844	int result;
845
846	START_PROFILE(syscall_link);
847	result = sys_link(oldpath, newpath);
848	END_PROFILE(syscall_link);
849	return result;
850}
851
852int vfswrap_mknod(vfs_handle_struct *handle, connection_struct *conn, const char *pathname, mode_t mode, SMB_DEV_T dev)
853{
854	int result;
855
856	START_PROFILE(syscall_mknod);
857	result = sys_mknod(pathname, mode, dev);
858	END_PROFILE(syscall_mknod);
859	return result;
860}
861
862char *vfswrap_realpath(vfs_handle_struct *handle, connection_struct *conn, const char *path, char *resolved_path)
863{
864	char *result;
865
866	START_PROFILE(syscall_realpath);
867	result = sys_realpath(path, resolved_path);
868	END_PROFILE(syscall_realpath);
869	return result;
870}
871
872size_t vfswrap_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info, SEC_DESC **ppdesc)
873{
874	size_t result;
875
876	START_PROFILE(fget_nt_acl);
877	result = get_nt_acl(fsp, security_info, ppdesc);
878	END_PROFILE(fget_nt_acl);
879	return result;
880}
881
882size_t vfswrap_get_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info, SEC_DESC **ppdesc)
883{
884	size_t result;
885
886	START_PROFILE(get_nt_acl);
887	result = get_nt_acl(fsp, security_info, ppdesc);
888	END_PROFILE(get_nt_acl);
889	return result;
890}
891
892BOOL vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info_sent, SEC_DESC *psd)
893{
894	BOOL result;
895
896	START_PROFILE(fset_nt_acl);
897	result = set_nt_acl(fsp, security_info_sent, psd);
898	END_PROFILE(fset_nt_acl);
899	return result;
900}
901
902BOOL vfswrap_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info_sent, SEC_DESC *psd)
903{
904	BOOL result;
905
906	START_PROFILE(set_nt_acl);
907	result = set_nt_acl(fsp, security_info_sent, psd);
908	END_PROFILE(set_nt_acl);
909	return result;
910}
911
912int vfswrap_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, const char *name, mode_t mode)
913{
914#ifdef HAVE_NO_ACL
915	errno = ENOSYS;
916	return -1;
917#else
918	int result;
919
920	START_PROFILE(chmod_acl);
921	result = chmod_acl(conn, name, mode);
922	END_PROFILE(chmod_acl);
923	return result;
924#endif
925}
926
927int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode)
928{
929#ifdef HAVE_NO_ACL
930	errno = ENOSYS;
931	return -1;
932#else
933	int result;
934
935	START_PROFILE(fchmod_acl);
936	result = fchmod_acl(fsp, fd, mode);
937	END_PROFILE(fchmod_acl);
938	return result;
939#endif
940}
941
942int vfswrap_sys_acl_get_entry(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
943{
944	return sys_acl_get_entry(theacl, entry_id, entry_p);
945}
946
947int vfswrap_sys_acl_get_tag_type(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
948{
949	return sys_acl_get_tag_type(entry_d, tag_type_p);
950}
951
952int vfswrap_sys_acl_get_permset(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
953{
954	return sys_acl_get_permset(entry_d, permset_p);
955}
956
957void * vfswrap_sys_acl_get_qualifier(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry_d)
958{
959	return sys_acl_get_qualifier(entry_d);
960}
961
962SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle, connection_struct *conn, const char *path_p, SMB_ACL_TYPE_T type)
963{
964	return sys_acl_get_file(path_p, type);
965}
966
967SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp, int fd)
968{
969	return sys_acl_get_fd(fd);
970}
971
972int vfswrap_sys_acl_clear_perms(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_PERMSET_T permset)
973{
974	return sys_acl_clear_perms(permset);
975}
976
977int vfswrap_sys_acl_add_perm(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
978{
979	return sys_acl_add_perm(permset, perm);
980}
981
982char * vfswrap_sys_acl_to_text(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T theacl, ssize_t *plen)
983{
984	return sys_acl_to_text(theacl, plen);
985}
986
987SMB_ACL_T vfswrap_sys_acl_init(vfs_handle_struct *handle, connection_struct *conn, int count)
988{
989	return sys_acl_init(count);
990}
991
992int vfswrap_sys_acl_create_entry(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
993{
994	return sys_acl_create_entry(pacl, pentry);
995}
996
997int vfswrap_sys_acl_set_tag_type(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
998{
999	return sys_acl_set_tag_type(entry, tagtype);
1000}
1001
1002int vfswrap_sys_acl_set_qualifier(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry, void *qual)
1003{
1004	return sys_acl_set_qualifier(entry, qual);
1005}
1006
1007int vfswrap_sys_acl_set_permset(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
1008{
1009	return sys_acl_set_permset(entry, permset);
1010}
1011
1012int vfswrap_sys_acl_valid(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T theacl )
1013{
1014	return sys_acl_valid(theacl );
1015}
1016
1017int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, connection_struct *conn, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
1018{
1019	return sys_acl_set_file(name, acltype, theacl);
1020}
1021
1022int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_ACL_T theacl)
1023{
1024	return sys_acl_set_fd(fd, theacl);
1025}
1026
1027int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, connection_struct *conn, const char *path)
1028{
1029	return sys_acl_delete_def_file(path);
1030}
1031
1032int vfswrap_sys_acl_get_perm(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
1033{
1034	return sys_acl_get_perm(permset, perm);
1035}
1036
1037int vfswrap_sys_acl_free_text(vfs_handle_struct *handle, connection_struct *conn, char *text)
1038{
1039	return sys_acl_free_text(text);
1040}
1041
1042int vfswrap_sys_acl_free_acl(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T posix_acl)
1043{
1044	return sys_acl_free_acl(posix_acl);
1045}
1046
1047int vfswrap_sys_acl_free_qualifier(vfs_handle_struct *handle, connection_struct *conn, void *qualifier, SMB_ACL_TAG_T tagtype)
1048{
1049	return sys_acl_free_qualifier(qualifier, tagtype);
1050}
1051
1052/****************************************************************
1053 Extended attribute operations.
1054*****************************************************************/
1055
1056ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,struct connection_struct *conn,const char *path, const char *name, void *value, size_t size)
1057{
1058	return sys_getxattr(path, name, value, size);
1059}
1060
1061ssize_t vfswrap_lgetxattr(struct vfs_handle_struct *handle,struct connection_struct *conn,const char *path, const char *name, void *value, size_t size)
1062{
1063	return sys_lgetxattr(path, name, value, size);
1064}
1065
1066ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, void *value, size_t size)
1067{
1068	return sys_fgetxattr(fd, name, value, size);
1069}
1070
1071ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size)
1072{
1073	return sys_listxattr(path, list, size);
1074}
1075
1076ssize_t vfswrap_llistxattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size)
1077{
1078	return sys_llistxattr(path, list, size);
1079}
1080
1081ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, char *list, size_t size)
1082{
1083	return sys_flistxattr(fd, list, size);
1084}
1085
1086int vfswrap_removexattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name)
1087{
1088	return sys_removexattr(path, name);
1089}
1090
1091int vfswrap_lremovexattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name)
1092{
1093	return sys_lremovexattr(path, name);
1094}
1095
1096int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name)
1097{
1098	return sys_fremovexattr(fd, name);
1099}
1100
1101int vfswrap_setxattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags)
1102{
1103	return sys_setxattr(path, name, value, size, flags);
1104}
1105
1106int vfswrap_lsetxattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags)
1107{
1108	return sys_lsetxattr(path, name, value, size, flags);
1109}
1110
1111int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, const void *value, size_t size, int flags)
1112{
1113	return sys_fsetxattr(fd, name, value, size, flags);
1114}
1115