asmlinkage int sys_ftruncate64(unsigned int fd, unsigned int high, unsigned int low) { if ((int)high < 0) return -EINVAL; return sys_ftruncate(fd, ((long) high << 32) | low); }
asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned long low) { if ((int)high < 0) return -EINVAL; else return sys_ftruncate(fd, (high << 32) | low); }
static int fd_truncate(struct lwp *l, int fd, struct flock *flp, register_t *retval) { file_t *fp; off_t start, length; vnode_t *vp; struct vattr vattr; int error; struct sys_ftruncate_args ft; /* * We only support truncating the file. */ if ((fp = fd_getfile(fd)) == NULL) return EBADF; vp = fp->f_data; if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) { fd_putfile(fd); return ESPIPE; } if ((error = VOP_GETATTR(vp, &vattr, l->l_cred)) != 0) { fd_putfile(fd); return error; } length = vattr.va_size; switch (flp->l_whence) { case SEEK_CUR: start = fp->f_offset + flp->l_start; break; case SEEK_END: start = flp->l_start + length; break; case SEEK_SET: start = flp->l_start; break; default: fd_putfile(fd); return EINVAL; } if (start + flp->l_len < length) { /* We don't support free'ing in the middle of the file */ fd_putfile(fd); return EINVAL; } SCARG(&ft, fd) = fd; SCARG(&ft, length) = start; error = sys_ftruncate(l, &ft, retval); fd_putfile(fd); return error; }
int compat_43_netbsd32_oftruncate(struct lwp *l, const struct compat_43_netbsd32_oftruncate_args *uap, register_t *retval) { /* { syscallarg(int) fd; syscallarg(netbsd32_long) length; } */ struct sys_ftruncate_args ua; NETBSD32TO64_UAP(fd); NETBSD32TO64_UAP(length); return (sys_ftruncate(l, &ua, retval)); }
static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T len) { SMB_STRUCT_STAT st; SMB_OFF_T currpos = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR); unsigned char zero_space[4096]; SMB_OFF_T space_to_write; if (currpos == -1) return -1; if (SMB_VFS_FSTAT(fsp, fd, &st) == -1) return -1; space_to_write = len - st.st_size; #ifdef S_ISFIFO if (S_ISFIFO(st.st_mode)) return 0; #endif if (st.st_size == len) return 0; /* Shrink - just ftruncate. */ if (st.st_size > len) return sys_ftruncate(fd, len); /* Write out the real space on disk. */ if (SMB_VFS_LSEEK(fsp, fd, st.st_size, SEEK_SET) != st.st_size) return -1; space_to_write = len - st.st_size; memset(zero_space, '\0', sizeof(zero_space)); while ( space_to_write > 0) { SMB_OFF_T retlen; SMB_OFF_T current_len_to_write = MIN(sizeof(zero_space),space_to_write); retlen = SMB_VFS_WRITE(fsp,fsp->fh->fd,(char *)zero_space,current_len_to_write); if (retlen <= 0) return -1; space_to_write -= retlen; } /* Seek to where we were */ if (SMB_VFS_LSEEK(fsp, fd, currpos, SEEK_SET) != currpos) return -1; return 0; }
int linux32_sys_ftruncate64(struct lwp *l, const struct linux32_sys_ftruncate64_args *uap, register_t *retval) { /* { syscallarg(unsigned int) fd; syscallarg(off_t) length; } */ struct sys_ftruncate_args ua; /* Linux doesn't have the 'pad' pseudo-parameter */ NETBSD32TO64_UAP(fd); SCARG(&ua, PAD) = 0; SCARG(&ua, length) = ((off_t)SCARG(uap, lenhi) << 32) + SCARG(uap, lenlo); return sys_ftruncate(l, &ua, retval); }
int linux_sys_ftruncate64(struct lwp *l, const struct linux_sys_ftruncate64_args *uap, register_t *retval) { /* { syscallarg(unsigned int) fd; syscallarg(off_t) length; } */ struct sys_ftruncate_args ta; /* Linux doesn't have the 'pad' pseudo-parameter */ SCARG(&ta, fd) = SCARG(uap, fd); SCARG(&ta, pad) = 0; SCARG(&ta, length) = SCARG(uap, length); return sys_ftruncate(l, &ta, retval); }
/* ARGSUSED */ int compat_43_sys_ftruncate(struct lwp *l, const struct compat_43_sys_ftruncate_args *uap, register_t *retval) { /* { syscallarg(int) fd; syscallarg(long) length; } */ struct sys_ftruncate_args /* { syscallarg(int) fd; syscallarg(int) pad; syscallarg(off_t) length; } */ nuap; SCARG(&nuap, fd) = SCARG(uap, fd); SCARG(&nuap, length) = SCARG(uap, length); return (sys_ftruncate(l, &nuap, retval)); }
asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long offset_low, unsigned long offset_high) { return sys_ftruncate(fd, ((loff_t) offset_high << 32) | offset_low); }
long compat_sys_ftruncate64(unsigned int fd, u32 dummy, u32 low, u32 high) { return sys_ftruncate(fd, ((loff_t)high << 32) | low); }
asmlinkage int compat_sys_ftruncate64(unsigned int fd, u32 reg4, unsigned long high, unsigned long low) { return sys_ftruncate(fd, (high << 32) | low); }
int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T len) { int result = -1; SMB_STRUCT_STAT st; char c = 0; SMB_OFF_T currpos; START_PROFILE(syscall_ftruncate); if (lp_strict_allocate(SNUM(fsp->conn))) { result = strict_allocate_ftruncate(handle, fsp, fd, len); END_PROFILE(syscall_ftruncate); return result; } /* we used to just check HAVE_FTRUNCATE_EXTEND and only use sys_ftruncate if the system supports it. Then I discovered that you can have some filesystems that support ftruncate expansion and some that don't! On Linux fat can't do ftruncate extend but ext2 can. */ result = sys_ftruncate(fd, len); if (result == 0) goto done; /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot extend a file with ftruncate. Provide alternate implementation for this */ currpos = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR); if (currpos == -1) { goto done; } /* Do an fstat to see if the file is longer than the requested size in which case the ftruncate above should have succeeded or shorter, in which case seek to len - 1 and write 1 byte of zero */ if (SMB_VFS_FSTAT(fsp, fd, &st) == -1) { goto done; } #ifdef S_ISFIFO if (S_ISFIFO(st.st_mode)) { result = 0; goto done; } #endif if (st.st_size == len) { result = 0; goto done; } if (st.st_size > len) { /* the sys_ftruncate should have worked */ goto done; } if (SMB_VFS_LSEEK(fsp, fd, len-1, SEEK_SET) != len -1) goto done; if (SMB_VFS_WRITE(fsp, fd, &c, 1)!=1) goto done; /* Seek to where we were */ if (SMB_VFS_LSEEK(fsp, fd, currpos, SEEK_SET) != currpos) goto done; result = 0; done: END_PROFILE(syscall_ftruncate); return result; }
long compat_sys_ftruncate(int fd, u32 length) { /* sign extend length */ return sys_ftruncate(fd, (int)length); }
int svr4_fcntl(int fd, unsigned int cmd, unsigned long arg) { int rval; switch (cmd) { case 0: /* F_DUPFD */ case 1: /* F_GETFD */ case 2: /* F_SETFD */ return sys_fcntl(fd, cmd, arg); case 3: /* F_GETFL */ rval = sys_fcntl(fd, cmd, arg); return map_flags(rval, fl_linux_to_svr4); case 4: /* F_SETFL */ arg = map_flags(arg, fl_svr4_to_linux); return sys_fcntl(fd, cmd, arg); case 14: /* F_GETLK SVR4 */ cmd = 5; /*FALLTHROUGH*/ case 5: /* F_GETLK */ case 6: /* F_SETLK */ case 7: /* F_SETLKW */ return svr4_fcntl_flock(fd, cmd, arg); case 10: /* F_ALLOCSP */ /* Extend allocation for specified portion of file. */ return 0; case 11: /* F_FREESP */ /* Free a portion of a file. */ return 0; /* * These are intended to support the Xenix chsize() and * rdchk() system calls. I don't know if these may be * generated by applications or not. */ case 0x6000: /* F_CHSIZE */ return sys_ftruncate(fd, arg); case 0x6001: /* F_RDCHK */ { mm_segment_t fs; int nbytes; fs = get_fs(); set_fs(get_ds()); rval = sys_ioctl(fd, FIONREAD, &nbytes); set_fs(fs); if (rval < 0) return rval; return (nbytes ? 1 : 0); } case 8: /* F_CHKFL */ /*FALLTHROUGH*/ /* * These are made from the Xenix locking() system call. * According to available documentation these would * never be generated by an application - only by the * kernel Xenix support. */ case 0x6300: /* F_LK_UNLCK */ case 0x7200: /* F_LK_LOCK */ case 0x6200: /* F_LK_NBLCK */ case 0x7100: /* F_LK_RLCK */ case 0x6100: /* F_LK_NBRLCK */ /*FALLTHROUGH*/ default: abi_trace(ABI_TRACE_API, "unsupported fcntl 0x%x, arg 0x%lx\n", cmd, arg); return -EINVAL; } }
long compat_sys_ftruncate(int fd, u32 length) { return sys_ftruncate(fd, (int)length); }
COMPAT_SYSCALL_DEFINE4(ftruncate64, unsigned int, fd, u32, dummy, u32, low, u32, high) { return sys_ftruncate(fd, ((loff_t)high << 32) | low); }