コード例 #1
0
static NTSTATUS fsctl_qar_seek_fill(TALLOC_CTX *mem_ctx,
				    struct files_struct *fsp,
				    off_t curr_off,
				    off_t max_off,
				    DATA_BLOB *qar_array_blob)
{
	NTSTATUS status = NT_STATUS_NOT_SUPPORTED;

#ifdef HAVE_LSEEK_HOLE_DATA
	while (curr_off <= max_off) {
		off_t data_off;
		off_t hole_off;
		struct file_alloced_range_buf qar_buf;

		/* seek next data */
		data_off = SMB_VFS_LSEEK(fsp, curr_off, SEEK_DATA);
		if ((data_off == -1) && (errno == ENXIO)) {
			/* no data from curr_off to EOF */
			break;
		} else if (data_off == -1) {
			status = map_nt_error_from_unix_common(errno);
			DEBUG(1, ("lseek data failed: %s\n", strerror(errno)));
			return status;
		}

		if (data_off > max_off) {
			/* found something, but passed range of interest */
			break;
		}

		hole_off = SMB_VFS_LSEEK(fsp, data_off, SEEK_HOLE);
		if (hole_off == -1) {
			status = map_nt_error_from_unix_common(errno);
			DEBUG(1, ("lseek hole failed: %s\n", strerror(errno)));
			return status;
		}

		if (hole_off <= data_off) {
			DEBUG(1, ("lseek inconsistent: hole %lu at or before "
				  "data %lu\n", (unsigned long)hole_off,
				  (unsigned long)data_off));
			return NT_STATUS_INTERNAL_ERROR;
		}

		qar_buf.file_off = data_off;
		/* + 1 to convert maximum offset to length */
		qar_buf.len = MIN(hole_off, max_off + 1) - data_off;

		status = fsctl_qar_buf_push(mem_ctx, &qar_buf, qar_array_blob);
		if (!NT_STATUS_IS_OK(status)) {
			return NT_STATUS_NO_MEMORY;
		}

		curr_off = hole_off;
	}
	status = NT_STATUS_OK;
#endif

	return status;
}
コード例 #2
0
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;
}
コード例 #3
0
ファイル: cmd_vfs.c プロジェクト: Nymphetaminer/dsl-n55u
static NTSTATUS cmd_lseek(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
{
	int fd, offset, whence;
	SMB_OFF_T pos;

	if (argc != 4) {
		printf("Usage: lseek <fd> <offset> <whence>\n...where whence is 1 => SEEK_SET, 2 => SEEK_CUR, 3 => SEEK_END\n");
		return NT_STATUS_OK;
	}

	fd = atoi(argv[1]);
	offset = atoi(argv[2]);
	whence = atoi(argv[3]);
	switch (whence) {
		case 1:		whence = SEEK_SET; break;
		case 2:		whence = SEEK_CUR; break;
		default:	whence = SEEK_END;
	}

	pos = SMB_VFS_LSEEK(vfs->files[fd], fd, offset, whence);
	if (pos == (SMB_OFF_T)-1) {
		printf("lseek: error=%d (%s)\n", errno, strerror(errno));
		return NT_STATUS_UNSUCCESSFUL;
	}

	printf("lseek: ok\n");
	return NT_STATUS_OK;
}
コード例 #4
0
ファイル: vfs_cacheprime.c プロジェクト: AllardJ/Tomato
static ssize_t cprime_read(
                vfs_handle_struct * handle,
                files_struct *      fsp,
                int                 fd,
                void *              data,
                size_t              count)
{
        SMB_OFF_T offset;

        offset = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR);
        if (offset >= 0 && g_readbuf)  {
                prime_cache(handle, fsp, fd, offset, count);
                SMB_VFS_LSEEK(fsp, fd, offset, SEEK_SET);
        }

        return SMB_VFS_NEXT_READ(handle, fsp, fd, data, count);
}
コード例 #5
0
ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, int fd, void *data,
			size_t n, SMB_OFF_T offset)
{
	ssize_t result;

#if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
	START_PROFILE_BYTES(syscall_pread, n);
	result = sys_pread(fd, data, n, offset);
	END_PROFILE(syscall_pread);
 
	if (result == -1 && errno == ESPIPE) {
		/* Maintain the fiction that pipes can be seeked (sought?) on. */
		result = SMB_VFS_READ(fsp, fd, data, n);
		fsp->fh->pos = 0;
	}

#else /* HAVE_PREAD */
	SMB_OFF_T   curr;
	int lerrno;
   
	curr = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR);
	if (curr == -1 && errno == ESPIPE) {
		/* Maintain the fiction that pipes can be seeked (sought?) on. */
		result = SMB_VFS_READ(fsp, fd, data, n);
		fsp->fh->pos = 0;
		return result;
	}

	if (SMB_VFS_LSEEK(fsp, fd, offset, SEEK_SET) == -1) {
		return -1;
	}

	errno = 0;
	result = SMB_VFS_READ(fsp, fd, data, n);
	lerrno = errno;

	SMB_VFS_LSEEK(fsp, fd, curr, SEEK_SET);
	errno = lerrno;

#endif /* HAVE_PREAD */

	return result;
}
コード例 #6
0
ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, int fd, const void *data,
			size_t n, SMB_OFF_T offset)
{
	ssize_t result;

#if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
	START_PROFILE_BYTES(syscall_pwrite, n);
	result = sys_pwrite(fd, data, n, offset);
	END_PROFILE(syscall_pwrite);

	if (result == -1 && errno == ESPIPE) {
		/* Maintain the fiction that pipes can be sought on. */
		result = SMB_VFS_WRITE(fsp, fd, data, n);
	}

#else /* HAVE_PWRITE */
	SMB_OFF_T   curr;
	int         lerrno;

	curr = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR);
	if (curr == -1) {
		return -1;
	}

	if (SMB_VFS_LSEEK(fsp, fd, offset, SEEK_SET) == -1) {
		return -1;
	}

	result = SMB_VFS_WRITE(fsp, fd, data, n);
	lerrno = errno;

	SMB_VFS_LSEEK(fsp, fd, curr, SEEK_SET);
	errno = lerrno;

#endif /* HAVE_PWRITE */

	return result;
}
コード例 #7
0
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;
}