179 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			179 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* Created (MFS based):
 | |
|  *   February 2010 (Evgeniy Ivanov)
 | |
|  */
 | |
| 
 | |
| #include "fs.h"
 | |
| #include <stddef.h>
 | |
| #include <string.h>
 | |
| #include <stdlib.h>
 | |
| #include <dirent.h>
 | |
| #include <minix/com.h>
 | |
| #include <minix/u64.h>
 | |
| #include <minix/vfsif.h>
 | |
| #include <assert.h>
 | |
| #include <sys/param.h>
 | |
| 
 | |
| #include "puffs.h"
 | |
| #include "puffs_priv.h"
 | |
| 
 | |
| 
 | |
| #define GETDENTS_BUFSIZ  4096
 | |
| static char getdents_buf[GETDENTS_BUFSIZ];
 | |
| 
 | |
| #define RW_BUFSIZ	(128 << 10)
 | |
| static char rw_buf[RW_BUFSIZ];
 | |
| 
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				fs_readwrite				     *
 | |
|  *===========================================================================*/
 | |
| int fs_readwrite(void)
 | |
| {
 | |
|   int r = OK, rw_flag;
 | |
|   cp_grant_id_t gid;
 | |
|   off_t pos;
 | |
|   size_t nrbytes, bytes_left, bytes_done = 0;
 | |
|   struct puffs_node *pn;
 | |
|   struct vattr va;
 | |
|   PUFFS_MAKECRED(pcr, &global_kcred);
 | |
| 
 | |
|   if ((pn = puffs_pn_nodewalk(global_pu, 0, &fs_m_in.REQ_INODE_NR)) == NULL) {
 | |
|   	lpuffs_debug("walk failed...\n");
 | |
|         return(EINVAL);
 | |
|   }
 | |
| 
 | |
|   /* Get the values from the request message */
 | |
|   rw_flag = (fs_m_in.m_type == REQ_READ ? READING : WRITING);
 | |
|   gid = (cp_grant_id_t) fs_m_in.REQ_GRANT;
 | |
|   pos = (off_t) fs_m_in.REQ_SEEK_POS;
 | |
|   nrbytes = bytes_left = (size_t) fs_m_in.REQ_NBYTES;
 | |
| 
 | |
|   if (nrbytes > RW_BUFSIZ)
 | |
| 	nrbytes = bytes_left = RW_BUFSIZ;
 | |
| 
 | |
|   memset(getdents_buf, '\0', GETDENTS_BUFSIZ);  /* Avoid leaking any data */
 | |
| 
 | |
|   if (rw_flag == READING) {
 | |
| 	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 = nrbytes - bytes_left;
 | |
| 	if (bytes_done) {
 | |
| 		r = sys_safecopyto(VFS_PROC_NR, gid, (vir_bytes) 0,
 | |
| 				   (vir_bytes) rw_buf, bytes_done);
 | |
| 		update_timens(pn, ATIME, NULL);
 | |
| 	}
 | |
|   } else if (rw_flag == WRITING) {
 | |
| 	/* At first try to change vattr */
 | |
| 	if (global_pu->pu_ops.puffs_node_setattr == NULL)
 | |
| 		return(EINVAL);
 | |
| 
 | |
| 	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 = clock_timespec();
 | |
| 	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);
 | |
| 
 | |
| 	r = sys_safecopyfrom(VFS_PROC_NR, gid, (vir_bytes) 0,
 | |
| 			     (vir_bytes) rw_buf, nrbytes);
 | |
| 	if (r != OK) return(EINVAL);
 | |
| 
 | |
| 	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);
 | |
| 	bytes_done = nrbytes - bytes_left;
 | |
|   }
 | |
| 
 | |
|   if (r != OK) return(EINVAL);
 | |
| 
 | |
|   fs_m_out.RES_SEEK_POS = pos + bytes_done;
 | |
|   fs_m_out.RES_NBYTES = bytes_done;
 | |
| 
 | |
|   return(r);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				fs_breadwrite				     *
 | |
|  *===========================================================================*/
 | |
| int fs_breadwrite(void)
 | |
| {
 | |
|   /* We do not support breads/writes */
 | |
|   panic("bread write requested, but FS doesn't support it!\n");
 | |
|   return(OK);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				fs_getdents				     *
 | |
|  *===========================================================================*/
 | |
| int fs_getdents(void)
 | |
| {
 | |
|   int r;
 | |
|   register struct puffs_node *pn;
 | |
|   pino_t ino;
 | |
|   cp_grant_id_t gid;
 | |
|   size_t size, buf_left;
 | |
|   off_t pos;
 | |
|   struct dirent *dent;
 | |
|   int eofflag = 0;
 | |
|   size_t written;
 | |
|   PUFFS_MAKECRED(pcr, &global_kcred);
 | |
| 
 | |
|   ino = (pino_t) fs_m_in.REQ_INODE_NR;
 | |
|   gid = (cp_grant_id_t) fs_m_in.REQ_GRANT;
 | |
|   size = buf_left = (size_t) fs_m_in.REQ_MEM_SIZE;
 | |
|   pos = (off_t) fs_m_in.REQ_SEEK_POS;
 | |
| 
 | |
|   if ((pn = puffs_pn_nodewalk(global_pu, 0, &ino)) == NULL) {
 | |
| 	lpuffs_debug("walk failed...\n");
 | |
|         return(EINVAL);
 | |
|   }
 | |
| 
 | |
|   if (GETDENTS_BUFSIZ < size)
 | |
| 	  size = buf_left = GETDENTS_BUFSIZ;
 | |
|   memset(getdents_buf, '\0', GETDENTS_BUFSIZ);  /* Avoid leaking any data */
 | |
| 
 | |
|   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 <= size);
 | |
|   written = size - buf_left;
 | |
| 
 | |
|   if (written == 0 && !eofflag) {
 | |
| 	lpuffs_debug("The user's buffer is too small\n");
 | |
| 	return(EINVAL);
 | |
|   }
 | |
| 
 | |
|   if (written) {
 | |
| 	r = sys_safecopyto(VFS_PROC_NR, gid, (vir_bytes) 0,
 | |
| 			     (vir_bytes) getdents_buf, written);
 | |
| 	if (r != OK) return(r);
 | |
|   }
 | |
| 
 | |
|   update_timens(pn, ATIME, NULL);
 | |
| 
 | |
|   fs_m_out.RES_NBYTES = written;
 | |
|   fs_m_out.RES_SEEK_POS = pos;
 | |
| 
 | |
|   return(OK);
 | |
| }
 | 
