minix/minix/lib/libpuffs/read.c
David van Moolenbroek ba736c7968 libpuffs: clean up, unbreak
- move MINIX3-specific files into minix/lib/libpuffs;
- resynchronize the remaining files with NetBSD code;
- remove a few unnecessary changes;
- put remaining MINIX3-specific changes in __minix blocks;
- sort out the source files being linked at all.

The result is that libpuffs now successfully links against FUSE
file system programs again.  It can successfully mount, perform
some of the most basic operations, and unmount the file system.

Change-Id: Ieac220f7ad8c4d1fa293abda81967e8045be0bb4
2015-09-23 12:05:03 +00:00

162 lines
4 KiB
C

/* Created (MFS based):
* February 2010 (Evgeniy Ivanov)
*/
#include "fs.h"
#include <stddef.h>
#include <dirent.h>
#include <sys/param.h>
#define GETDENTS_BUFSIZ 4096
static char getdents_buf[GETDENTS_BUFSIZ];
#define RW_BUFSIZ (128 * 1024)
static char rw_buf[RW_BUFSIZ];
/*===========================================================================*
* fs_read *
*===========================================================================*/
ssize_t fs_read(ino_t ino_nr, struct fsdriver_data *data, size_t bytes,
off_t pos, int call)
{
int r;
size_t bytes_left, bytes_done;
struct puffs_node *pn;
PUFFS_MAKECRED(pcr, &global_kcred);
if ((pn = puffs_pn_nodewalk(global_pu, find_inode_cb, &ino_nr)) == NULL) {
lpuffs_debug("walk failed...\n");
return(EINVAL);
}
if (bytes > sizeof(rw_buf))
bytes = sizeof(rw_buf);
bytes_left = bytes;
if (global_pu->pu_ops.puffs_node_read == NULL)
return(EINVAL);
r = global_pu->pu_ops.puffs_node_read(global_pu, pn, (uint8_t *)rw_buf,
pos, &bytes_left, pcr, 0);
if (r) {
lpuffs_debug("puffs_node_read failed\n");
return(EINVAL);
}
bytes_done = bytes - bytes_left;
if (bytes_done > 0) {
if ((r = fsdriver_copyout(data, 0, rw_buf, bytes_done)) != OK)
return r;
update_timens(pn, ATIME, NULL);
}
return (ssize_t)bytes_done;
}
/*===========================================================================*
* fs_write *
*===========================================================================*/
ssize_t fs_write(ino_t ino_nr, struct fsdriver_data *data, size_t bytes,
off_t pos, int call)
{
int r;
size_t bytes_left;
struct puffs_node *pn;
struct vattr va;
struct timespec cur_time;
PUFFS_MAKECRED(pcr, &global_kcred);
if ((pn = puffs_pn_nodewalk(global_pu, find_inode_cb, &ino_nr)) == NULL) {
lpuffs_debug("walk failed...\n");
return(EINVAL);
}
if (bytes > sizeof(rw_buf))
bytes = sizeof(rw_buf);
bytes_left = bytes;
/* At first try to change vattr */
if (global_pu->pu_ops.puffs_node_setattr == NULL)
return(EINVAL);
(void)clock_time(&cur_time);
puffs_vattr_null(&va);
if ((u_quad_t)(pos + bytes_left) > pn->pn_va.va_size)
va.va_size = bytes_left + pos;
va.va_ctime = va.va_mtime = cur_time;
va.va_atime = pn->pn_va.va_atime;
r = global_pu->pu_ops.puffs_node_setattr(global_pu, pn, &va, pcr);
if (r) return(EINVAL);
if ((r = fsdriver_copyin(data, 0, rw_buf, bytes)) != OK)
return r;
if (global_pu->pu_ops.puffs_node_write == NULL)
return(EINVAL);
r = global_pu->pu_ops.puffs_node_write(global_pu, pn, (uint8_t *)rw_buf,
pos, &bytes_left, pcr, 0);
if (r != OK) return(EINVAL);
return (ssize_t)(bytes - bytes_left);
}
/*===========================================================================*
* fs_getdents *
*===========================================================================*/
ssize_t fs_getdents(ino_t ino_nr, struct fsdriver_data *data, size_t bytes,
off_t *pos)
{
int r;
register struct puffs_node *pn;
size_t buf_left, written;
struct dirent *dent;
int eofflag = 0;
PUFFS_MAKECRED(pcr, &global_kcred);
if ((pn = puffs_pn_nodewalk(global_pu, find_inode_cb, &ino_nr)) == NULL) {
lpuffs_debug("walk failed...\n");
return(EINVAL);
}
if (bytes > sizeof(getdents_buf))
bytes = sizeof(getdents_buf);
memset(getdents_buf, 0, sizeof(getdents_buf)); /* Avoid leaking any data */
buf_left = bytes;
dent = (struct dirent*) getdents_buf;
r = global_pu->pu_ops.puffs_node_readdir(global_pu, pn, dent, pos,
&buf_left, pcr, &eofflag, 0, 0);
if (r) {
lpuffs_debug("puffs_node_readdir returned error\n");
return(EINVAL);
}
assert(buf_left <= bytes);
written = bytes - buf_left;
if (written == 0 && !eofflag) {
lpuffs_debug("The user's buffer is too small\n");
return(EINVAL);
}
if (written) {
if ((r = fsdriver_copyout(data, 0, getdents_buf, written)) != OK)
return r;
}
update_timens(pn, ATIME, NULL);
/* The puffs readdir call has already updated the position. */
return written;
}