 9221586f37
			
		
	
	
		9221586f37
		
	
	
	
	
		
			
			Using sendrec directly only results in problems. While it is not clear whether using fs_sendrec is the best option, it is at least an improvement. Also remove some legacy cruft.
		
			
				
	
	
		
			1149 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1149 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* This file contains the wrapper functions for issuing a request
 | |
|  * and receiving response from FS processes.
 | |
|  * Each function builds a request message according to the request
 | |
|  * parameter, calls the most low-level fs_sendrec, and copies
 | |
|  * back the response.
 | |
|  */
 | |
| 
 | |
| #include "fs.h"
 | |
| #include <string.h>
 | |
| #include <assert.h>
 | |
| #include <sys/stat.h>
 | |
| #include <sys/statfs.h>
 | |
| #include <sys/statvfs.h>
 | |
| #include <minix/vfsif.h>
 | |
| #include <minix/com.h>
 | |
| #include <minix/const.h>
 | |
| #include <minix/endpoint.h>
 | |
| #include <minix/u64.h>
 | |
| #include <unistd.h>
 | |
| #include <minix/vfsif.h>
 | |
| #include "fproc.h"
 | |
| #include "vmnt.h"
 | |
| #include "vnode.h"
 | |
| #include "param.h"
 | |
| 
 | |
| FORWARD _PROTOTYPE(int fs_sendrec_f, (char *file, int line, endpoint_t fs_e,
 | |
| 				      message *reqm)			);
 | |
| 
 | |
| #define fs_sendrec(e, m) fs_sendrec_f(__FILE__, __LINE__, (e), (m))
 | |
| 
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *			req_breadwrite					     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC int req_breadwrite(
 | |
|   endpoint_t fs_e,
 | |
|   endpoint_t user_e,
 | |
|   dev_t dev,
 | |
|   u64_t pos,
 | |
|   unsigned int num_of_bytes,
 | |
|   char *user_addr,
 | |
|   int rw_flag,
 | |
|   u64_t *new_posp,
 | |
|   unsigned int *cum_iop
 | |
| )
 | |
| {
 | |
|   int r;
 | |
|   cp_grant_id_t grant_id;
 | |
|   message m;
 | |
| 
 | |
|   grant_id = cpf_grant_magic(fs_e, user_e, (vir_bytes) user_addr, num_of_bytes,
 | |
| 			(rw_flag == READING ? CPF_WRITE : CPF_READ));
 | |
|   if(grant_id == -1)
 | |
| 	  panic("req_breadwrite: cpf_grant_magic failed");
 | |
| 
 | |
|   /* Fill in request message */
 | |
|   m.m_type = rw_flag == READING ? REQ_BREAD : REQ_BWRITE;
 | |
|   m.REQ_DEV2 = dev;
 | |
|   m.REQ_GRANT = grant_id;
 | |
|   m.REQ_SEEK_POS_LO = ex64lo(pos);
 | |
|   m.REQ_SEEK_POS_HI = ex64hi(pos);
 | |
|   m.REQ_NBYTES = num_of_bytes;
 | |
| 
 | |
|   /* Send/rec request */
 | |
|   r = fs_sendrec(fs_e, &m);
 | |
|   cpf_revoke(grant_id);
 | |
|   if (r != OK) return(r);
 | |
| 
 | |
|   /* Fill in response structure */
 | |
|   *new_posp = make64(m.RES_SEEK_POS_LO, m.RES_SEEK_POS_HI);
 | |
|   *cum_iop = m.RES_NBYTES;
 | |
| 
 | |
|   return(OK);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				req_chmod	      			     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC int req_chmod(
 | |
|   int fs_e,
 | |
|   ino_t inode_nr,
 | |
|   mode_t rmode,
 | |
|   mode_t *new_modep
 | |
| )
 | |
| {
 | |
|   message m;
 | |
|   int r;
 | |
| 
 | |
|   /* Fill in request message */
 | |
|   m.m_type = REQ_CHMOD;
 | |
|   m.REQ_INODE_NR = inode_nr;
 | |
|   m.REQ_MODE = rmode;
 | |
| 
 | |
|   /* Send/rec request */
 | |
|   r = fs_sendrec(fs_e, &m);
 | |
|   
 | |
|   /* Copy back actual mode. */
 | |
|   *new_modep = m.RES_MODE;
 | |
| 
 | |
|   return(r);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				req_chown          			     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC int req_chown(
 | |
|   endpoint_t fs_e,
 | |
|   ino_t inode_nr,
 | |
|   uid_t newuid,
 | |
|   gid_t newgid,
 | |
|   mode_t *new_modep
 | |
| )
 | |
| {
 | |
|   message m;
 | |
|   int r;
 | |
| 
 | |
|   /* Fill in request message */
 | |
|   m.m_type = REQ_CHOWN;
 | |
|   m.REQ_INODE_NR = inode_nr;
 | |
|   m.REQ_UID = newuid;
 | |
|   m.REQ_GID = newgid;
 | |
| 
 | |
|   /* Send/rec request */
 | |
|   r = fs_sendrec(fs_e, &m);
 | |
| 
 | |
|   /* Return new mode to caller. */
 | |
|   *new_modep = m.RES_MODE;
 | |
| 
 | |
|   return(r);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				req_create				     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC int req_create(
 | |
|   int fs_e,
 | |
|   ino_t inode_nr,
 | |
|   int omode,
 | |
|   uid_t uid,
 | |
|   gid_t gid,
 | |
|   char *path,
 | |
|   node_details_t *res
 | |
| )
 | |
| {
 | |
|   int r;
 | |
|   cp_grant_id_t grant_id;
 | |
|   size_t len;
 | |
|   message m;
 | |
| 
 | |
|   if (path[0] == '/')
 | |
|   	panic("req_create: filename starts with '/'");
 | |
| 
 | |
|   len = strlen(path) + 1;
 | |
|   grant_id = cpf_grant_direct(fs_e, (vir_bytes) path, len, CPF_READ);
 | |
|   if (grant_id == -1)
 | |
| 	panic("req_create: cpf_grant_direct failed");
 | |
| 
 | |
|   /* Fill in request message */
 | |
|   m.m_type	= REQ_CREATE;
 | |
|   m.REQ_INODE_NR = inode_nr;
 | |
|   m.REQ_MODE	= omode;
 | |
|   m.REQ_UID	= uid;
 | |
|   m.REQ_GID	= gid;
 | |
|   m.REQ_GRANT	= grant_id;
 | |
|   m.REQ_PATH_LEN = len;
 | |
| 
 | |
|   /* Send/rec request */
 | |
|   r = fs_sendrec(fs_e, &m);
 | |
|   cpf_revoke(grant_id);
 | |
|   if (r != OK) return(r);
 | |
| 
 | |
|   /* Fill in response structure */
 | |
|   res->fs_e	= m.m_source;
 | |
|   res->inode_nr	= m.RES_INODE_NR;
 | |
|   res->fmode	= m.RES_MODE;
 | |
|   res->fsize	= m.RES_FILE_SIZE_LO;
 | |
|   res->uid	= m.RES_UID;
 | |
|   res->gid	= m.RES_GID;
 | |
|   res->dev	= m.RES_DEV;
 | |
|   
 | |
|   return(OK);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				req_flush	      			     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC int req_flush(endpoint_t fs_e, dev_t dev)
 | |
| {
 | |
|   message m;
 | |
| 
 | |
|   /* Fill in request message */
 | |
|   m.m_type = REQ_FLUSH;
 | |
|   m.REQ_DEV = dev;
 | |
|     
 | |
|   /* Send/rec request */
 | |
|   return fs_sendrec(fs_e, &m);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				req_fstatfs	    			     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC int req_fstatfs(int fs_e, int who_e, char *buf)
 | |
| {
 | |
|   int r;
 | |
|   cp_grant_id_t grant_id;
 | |
|   message m;
 | |
| 
 | |
|   grant_id = cpf_grant_magic(fs_e, who_e, (vir_bytes) buf, sizeof(struct statfs),
 | |
| 			CPF_WRITE);
 | |
|   if(grant_id == -1) 
 | |
| 	  panic("req_fstatfs: cpf_grant_magic failed");
 | |
| 
 | |
|   /* Fill in request message */
 | |
|   m.m_type = REQ_FSTATFS;
 | |
|   m.REQ_GRANT = grant_id;
 | |
| 
 | |
|   /* Send/rec request */
 | |
|   r = fs_sendrec(fs_e, &m);
 | |
|   cpf_revoke(grant_id);
 | |
| 
 | |
|   return(r);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				req_statvfs	    			     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC int req_statvfs(int fs_e, int who_e, char *buf)
 | |
| {
 | |
|   int r;
 | |
|   cp_grant_id_t grant_id;
 | |
|   message m;
 | |
| 
 | |
|   grant_id = cpf_grant_magic(fs_e, who_e, (vir_bytes) buf, sizeof(struct statvfs),
 | |
| 			CPF_WRITE);
 | |
|   if(grant_id == -1) 
 | |
| 	  panic("req_statvfs: cpf_grant_magic failed");
 | |
| 
 | |
|   /* Fill in request message */
 | |
|   m.m_type = REQ_STATVFS;
 | |
|   m.REQ_GRANT = grant_id;
 | |
| 
 | |
|   /* Send/rec request */
 | |
|   r = fs_sendrec(fs_e, &m);
 | |
|   cpf_revoke(grant_id);
 | |
| 
 | |
|   return(r);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				req_ftrunc	     			     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC int req_ftrunc(endpoint_t fs_e, ino_t inode_nr, off_t start, off_t end)
 | |
| {
 | |
|   message m;
 | |
| 
 | |
|   /* Fill in request message */
 | |
|   m.m_type = REQ_FTRUNC;
 | |
|   m.REQ_INODE_NR = inode_nr;
 | |
|   m.REQ_TRC_START_LO = start;
 | |
|   m.REQ_TRC_START_HI = 0;	/* Not used for now, so clear it. */
 | |
|   m.REQ_TRC_END_LO = end;
 | |
|   m.REQ_TRC_END_HI = 0;		/* Not used for now, so clear it. */
 | |
|   
 | |
|   /* Send/rec request */
 | |
|   return fs_sendrec(fs_e, &m);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				req_getdents	     			     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC int req_getdents(
 | |
|   endpoint_t fs_e,
 | |
|   ino_t inode_nr,
 | |
|   u64_t pos,
 | |
|   char *buf,
 | |
|   size_t size,
 | |
|   u64_t *new_pos,
 | |
|   int direct
 | |
| )
 | |
| {
 | |
|   int r;
 | |
|   message m;
 | |
|   cp_grant_id_t grant_id;
 | |
| 
 | |
|   if (direct) {
 | |
| 	grant_id = cpf_grant_direct(fs_e, (vir_bytes) buf, size,
 | |
| 								CPF_WRITE);
 | |
|   } else {
 | |
| 	grant_id = cpf_grant_magic(fs_e, who_e, (vir_bytes) buf, size,
 | |
| 								CPF_WRITE);
 | |
|   }
 | |
| 
 | |
|   if (grant_id < 0)
 | |
|   	panic("req_getdents: cpf_grant_direct/cpf_grant_magic failed: %d",
 | |
| 								grant_id);
 | |
| 
 | |
|   m.m_type = REQ_GETDENTS;
 | |
|   m.REQ_INODE_NR = inode_nr;
 | |
|   m.REQ_GRANT = grant_id;
 | |
|   m.REQ_MEM_SIZE = size;
 | |
|   m.REQ_SEEK_POS_LO = ex64lo(pos);
 | |
|   m.REQ_SEEK_POS_HI = 0;	/* Not used for now, so clear it. */
 | |
|   
 | |
|   r = fs_sendrec(fs_e, &m);
 | |
|   cpf_revoke(grant_id);
 | |
|   
 | |
|   if (r == OK) {
 | |
| 	  *new_pos = cvul64(m.RES_SEEK_POS_LO);
 | |
| 	  r = m.RES_NBYTES;
 | |
|   }
 | |
| 
 | |
|   return(r);
 | |
| }
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				req_inhibread	  			     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC int req_inhibread(endpoint_t fs_e, ino_t inode_nr)
 | |
| {
 | |
|   message m;
 | |
| 
 | |
|   /* Fill in request message */
 | |
|   m.m_type = REQ_INHIBREAD;
 | |
|   m.REQ_INODE_NR = inode_nr;
 | |
|   
 | |
|   /* Send/rec request */
 | |
|   return fs_sendrec(fs_e, &m);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				req_link	       			     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC int req_link(
 | |
|   endpoint_t fs_e,
 | |
|   ino_t link_parent,
 | |
|   char *lastc,
 | |
|   ino_t linked_file
 | |
| )
 | |
| {
 | |
|   int r;
 | |
|   cp_grant_id_t grant_id;
 | |
|   const size_t len = strlen(lastc) + 1;
 | |
|   message m;
 | |
| 
 | |
|   grant_id = cpf_grant_direct(fs_e, (vir_bytes)lastc, len, CPF_READ);
 | |
|   if(grant_id == -1)
 | |
| 	  panic("req_link: cpf_grant_direct failed");
 | |
| 
 | |
|   /* Fill in request message */
 | |
|   m.m_type = REQ_LINK;
 | |
|   m.REQ_INODE_NR = linked_file;
 | |
|   m.REQ_DIR_INO = link_parent;
 | |
|   m.REQ_GRANT = grant_id;
 | |
|   m.REQ_PATH_LEN = len;
 | |
| 
 | |
|   /* Send/rec request */
 | |
|   r = fs_sendrec(fs_e, &m);
 | |
|   cpf_revoke(grant_id);
 | |
|   
 | |
|   return(r);
 | |
| }
 | |
|     
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				req_lookup	                   	     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC int req_lookup(
 | |
|   endpoint_t fs_e,
 | |
|   ino_t dir_ino,
 | |
|   ino_t root_ino,
 | |
|   uid_t uid,
 | |
|   gid_t gid,
 | |
|   int flags,
 | |
|   lookup_res_t *res,
 | |
|   struct fproc *rfp
 | |
| )
 | |
| {
 | |
|   int r;
 | |
|   size_t len;
 | |
|   cp_grant_id_t grant_id=0, grant_id2=0;
 | |
|   message m;
 | |
|   vfs_ucred_t credentials;
 | |
| 
 | |
|   grant_id = cpf_grant_direct(fs_e, (vir_bytes) user_fullpath,
 | |
| 			      sizeof(user_fullpath), CPF_READ | CPF_WRITE);
 | |
|   if(grant_id == -1)
 | |
| 	  panic("req_lookup: cpf_grant_direct failed");
 | |
| 
 | |
|   len = strlen(user_fullpath) + 1;
 | |
| 
 | |
|   m.m_type		= REQ_LOOKUP;
 | |
|   m.REQ_GRANT		= grant_id;
 | |
|   m.REQ_PATH_LEN 	= len;
 | |
|   m.REQ_PATH_SIZE 	= sizeof(user_fullpath);
 | |
|   m.REQ_DIR_INO 	= dir_ino;
 | |
|   m.REQ_ROOT_INO 	= root_ino;
 | |
| 
 | |
|   if(rfp->fp_ngroups > 0) { /* Is the process member of multiple groups? */
 | |
|   	/* In that case the FS has to copy the uid/gid credentials */
 | |
|   	int i;
 | |
| 
 | |
|   	/* Set credentials */
 | |
|   	credentials.vu_uid = rfp->fp_effuid;
 | |
|   	credentials.vu_gid = rfp->fp_effgid;
 | |
|   	credentials.vu_ngroups = rfp->fp_ngroups;
 | |
|   	for (i = 0; i < rfp->fp_ngroups; i++) 
 | |
|   		credentials.vu_sgroups[i] = rfp->fp_sgroups[i];
 | |
| 
 | |
| 	grant_id2 = cpf_grant_direct(fs_e, (vir_bytes) &credentials,
 | |
| 				     sizeof(credentials), CPF_READ);
 | |
| 	if(grant_id2 == -1)
 | |
| 		panic("req_lookup: cpf_grant_direct failed");
 | |
| 
 | |
| 	m.REQ_GRANT2	= grant_id2;
 | |
| 	m.REQ_UCRED_SIZE= sizeof(credentials);
 | |
|   	flags		|= PATH_GET_UCRED;
 | |
|   } else {
 | |
|   	/* When there's only one gid, we can send it directly */
 | |
| 	m.REQ_UID	= uid;
 | |
| 	m.REQ_GID	= gid;
 | |
| 	flags		&= ~PATH_GET_UCRED;
 | |
|   }
 | |
| 
 | |
|   m.REQ_FLAGS		= flags;
 | |
| 
 | |
|   /* Send/rec request */
 | |
|   r = fs_sendrec(fs_e, &m);
 | |
|   cpf_revoke(grant_id);
 | |
|   if(rfp->fp_ngroups > 0) cpf_revoke(grant_id2); 
 | |
| 
 | |
|   /* Fill in response according to the return value */
 | |
|   res->fs_e = m.m_source;
 | |
| 
 | |
|   switch (r) {
 | |
|   case OK:
 | |
| 	  res->inode_nr = m.RES_INODE_NR;
 | |
| 	  res->fmode = m.RES_MODE;
 | |
| 	  res->fsize = m.RES_FILE_SIZE_LO;
 | |
| 	  res->dev = m.RES_DEV;
 | |
| 	  res->uid= m.RES_UID;
 | |
| 	  res->gid= m.RES_GID;
 | |
| 	  break;
 | |
|   case EENTERMOUNT:
 | |
| 	  res->inode_nr = m.RES_INODE_NR;
 | |
| 	  res->char_processed = m.RES_OFFSET;
 | |
| 	  res->symloop = m.RES_SYMLOOP;
 | |
| 	  break;
 | |
|   case ELEAVEMOUNT:
 | |
| 	  res->char_processed = m.RES_OFFSET;
 | |
| 	  res->symloop = m.RES_SYMLOOP;
 | |
| 	  break;
 | |
|   case ESYMLINK:
 | |
| 	  res->char_processed = m.RES_OFFSET;
 | |
| 	  res->symloop = m.RES_SYMLOOP;
 | |
| 	  break;
 | |
|   default:
 | |
| 	  break;
 | |
|   }
 | |
|   
 | |
|   return(r);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				req_mkdir	      			     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC int req_mkdir(
 | |
|   endpoint_t fs_e,
 | |
|   ino_t inode_nr,
 | |
|   char *lastc,
 | |
|   uid_t uid,
 | |
|   gid_t gid,
 | |
|   mode_t dmode
 | |
| )
 | |
| {
 | |
|   int r;
 | |
|   cp_grant_id_t grant_id;
 | |
|   size_t len;
 | |
|   message m;
 | |
|   
 | |
|   len = strlen(lastc) + 1;
 | |
|   grant_id = cpf_grant_direct(fs_e, (vir_bytes)lastc, len, CPF_READ);
 | |
|   if(grant_id == -1)
 | |
| 	  panic("req_mkdir: cpf_grant_direct failed");
 | |
| 
 | |
|   /* Fill in request message */
 | |
|   m.m_type = REQ_MKDIR;
 | |
|   m.REQ_INODE_NR = inode_nr;
 | |
|   m.REQ_MODE = dmode;
 | |
|   m.REQ_UID = uid;
 | |
|   m.REQ_GID = gid;
 | |
|   m.REQ_GRANT = grant_id;
 | |
|   m.REQ_PATH_LEN = len;
 | |
| 
 | |
|   /* Send/rec request */
 | |
|   r = fs_sendrec(fs_e, &m);
 | |
|   cpf_revoke(grant_id);
 | |
| 
 | |
|   return(r);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				req_mknod	      			     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC int req_mknod(
 | |
|   endpoint_t fs_e,
 | |
|   ino_t inode_nr,
 | |
|   char *lastc,
 | |
|   uid_t uid,
 | |
|   gid_t gid,
 | |
|   mode_t dmode,
 | |
|   dev_t dev
 | |
| )
 | |
| {
 | |
|   int r;
 | |
|   size_t len;
 | |
|   cp_grant_id_t grant_id;
 | |
|   message m;
 | |
|   
 | |
|   len = strlen(lastc) + 1;
 | |
|   grant_id = cpf_grant_direct(fs_e, (vir_bytes)lastc, len, CPF_READ);
 | |
|   if(grant_id == -1)
 | |
| 	  panic("req_mknod: cpf_grant_direct failed");
 | |
| 
 | |
|   /* Fill in request message */
 | |
|   m.m_type = REQ_MKNOD;
 | |
|   m.REQ_INODE_NR = inode_nr;
 | |
|   m.REQ_MODE = dmode;
 | |
|   m.REQ_DEV = dev;
 | |
|   m.REQ_UID = uid;
 | |
|   m.REQ_GID = gid;
 | |
|   m.REQ_GRANT = grant_id;
 | |
|   m.REQ_PATH_LEN = len;
 | |
|   
 | |
|   /* Send/rec request */
 | |
|   r = fs_sendrec(fs_e, &m);
 | |
|   cpf_revoke(grant_id);
 | |
|   
 | |
|   return(r);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				req_mountpoint	                 	     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC int req_mountpoint(endpoint_t fs_e, ino_t inode_nr)
 | |
| {
 | |
|   message m;
 | |
| 
 | |
|   /* Fill in request message */
 | |
|   m.m_type = REQ_MOUNTPOINT;
 | |
|   m.REQ_INODE_NR = inode_nr;
 | |
| 
 | |
|   /* Send/rec request */
 | |
|   return fs_sendrec(fs_e, &m);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				req_newnode	      			     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC int req_newnode(
 | |
|   endpoint_t fs_e,
 | |
|   uid_t uid,
 | |
|   gid_t gid,
 | |
|   mode_t dmode,
 | |
|   dev_t dev,
 | |
|   struct node_details *res
 | |
| )
 | |
| {
 | |
|   int r;
 | |
|   message m;
 | |
| 
 | |
|   /* Fill in request message */
 | |
|   m.m_type = REQ_NEWNODE;
 | |
|   m.REQ_MODE = dmode;
 | |
|   m.REQ_DEV = dev;
 | |
|   m.REQ_UID = uid;
 | |
|   m.REQ_GID = gid;
 | |
| 
 | |
|   /* Send/rec request */
 | |
|   r = fs_sendrec(fs_e, &m);
 | |
| 
 | |
|   res->fs_e	= m.m_source;
 | |
|   res->inode_nr = m.RES_INODE_NR;
 | |
|   res->fmode	= m.RES_MODE;
 | |
|   res->fsize	= m.RES_FILE_SIZE_LO;
 | |
|   res->dev	= m.RES_DEV;
 | |
|   res->uid	= m.RES_UID;
 | |
|   res->gid	= m.RES_GID;
 | |
| 
 | |
|   return(r);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				req_newdriver          			     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC int req_newdriver(
 | |
|   endpoint_t fs_e,
 | |
|   dev_t dev,
 | |
|   char *label
 | |
| )
 | |
| {
 | |
|   cp_grant_id_t grant_id;
 | |
|   size_t len;
 | |
|   message m;
 | |
|   int r;
 | |
| 
 | |
|   /* Grant access to label */
 | |
|   len = strlen(label) + 1;
 | |
|   grant_id = cpf_grant_direct(fs_e, (vir_bytes) label, len, CPF_READ);
 | |
|   if (grant_id == -1)
 | |
| 	panic("req_newdriver: cpf_grant_direct failed");
 | |
| 
 | |
|   /* Fill in request message */
 | |
|   m.m_type = REQ_NEW_DRIVER;
 | |
|   m.REQ_DEV = dev;
 | |
|   m.REQ_GRANT = grant_id;
 | |
|   m.REQ_PATH_LEN = len;
 | |
| 
 | |
|   /* Issue request */
 | |
|   r = fs_sendrec(fs_e, &m);
 | |
| 
 | |
|   cpf_revoke(grant_id);
 | |
| 
 | |
|   return(r);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				req_putnode				     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC int req_putnode(fs_e, inode_nr, count)
 | |
| int fs_e;
 | |
| ino_t inode_nr;
 | |
| int count;
 | |
| {
 | |
|   message m;
 | |
| 
 | |
|   /* Fill in request message */
 | |
|   m.m_type = REQ_PUTNODE;
 | |
|   m.REQ_INODE_NR = inode_nr;
 | |
|   m.REQ_COUNT = count;
 | |
| 
 | |
|   /* Send/rec request */
 | |
|   return fs_sendrec(fs_e, &m);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				req_rdlink	     			     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC int req_rdlink(fs_e, inode_nr, who_e, buf, len, direct)
 | |
| endpoint_t fs_e;
 | |
| ino_t inode_nr;
 | |
| endpoint_t who_e;
 | |
| char *buf;
 | |
| size_t len;
 | |
| int direct; /* set to 1 to use direct grants instead of magic grants */
 | |
| {
 | |
|   message m;
 | |
|   int r;
 | |
|   cp_grant_id_t grant_id;
 | |
| 
 | |
|   if (direct) {
 | |
| 	grant_id = cpf_grant_direct(fs_e, (vir_bytes) buf, len, CPF_WRITE);
 | |
|   } else {
 | |
| 	grant_id = cpf_grant_magic(fs_e, who_e, (vir_bytes) buf, len,
 | |
| 								CPF_WRITE);
 | |
|   }
 | |
|   if(grant_id == -1)
 | |
| 	  panic("req_rdlink: cpf_grant_magic failed");
 | |
| 
 | |
|   /* Fill in request message */
 | |
|   m.m_type = REQ_RDLINK;
 | |
|   m.REQ_INODE_NR = inode_nr;
 | |
|   m.REQ_GRANT = grant_id;
 | |
|   m.REQ_MEM_SIZE = len;
 | |
|   
 | |
|   /* Send/rec request */
 | |
|   r = fs_sendrec(fs_e, &m);
 | |
|   cpf_revoke(grant_id);
 | |
| 
 | |
|   if(r == OK) r = m.RES_NBYTES;
 | |
| 
 | |
|   return(r);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				req_readsuper	                  	     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC int req_readsuper(
 | |
|   endpoint_t fs_e,
 | |
|   char *label,
 | |
|   dev_t dev,
 | |
|   int readonly,
 | |
|   int isroot,
 | |
|   struct node_details *res_nodep
 | |
| )
 | |
| {
 | |
|   int r;
 | |
|   cp_grant_id_t grant_id;
 | |
|   size_t len;
 | |
|   message m;
 | |
|   
 | |
|   len = strlen(label)+1;
 | |
|   grant_id = cpf_grant_direct(fs_e, (vir_bytes) label, len, CPF_READ);
 | |
|   if (grant_id == -1)
 | |
| 	  panic("req_readsuper: cpf_grant_direct failed");
 | |
| 
 | |
|   /* Fill in request message */
 | |
|   m.m_type = REQ_READSUPER;
 | |
|   m.REQ_FLAGS = 0;
 | |
|   if(readonly) m.REQ_FLAGS |= REQ_RDONLY;
 | |
|   if(isroot)   m.REQ_FLAGS |= REQ_ISROOT;   
 | |
|   m.REQ_GRANT = grant_id;
 | |
|   m.REQ_DEV = dev;
 | |
|   m.REQ_PATH_LEN = len;
 | |
|   
 | |
|   /* Send/rec request */
 | |
|   r = fs_sendrec(fs_e, &m);
 | |
|   cpf_revoke(grant_id);
 | |
| 
 | |
|   if(r == OK) {
 | |
| 	/* Fill in response structure */
 | |
| 	res_nodep->fs_e = m.m_source;
 | |
| 	res_nodep->inode_nr = m.RES_INODE_NR;
 | |
| 	res_nodep->fmode = m.RES_MODE;
 | |
| 	res_nodep->fsize = m.RES_FILE_SIZE_LO;
 | |
| 	res_nodep->uid = m.RES_UID;
 | |
| 	res_nodep->gid = m.RES_GID;
 | |
|   }
 | |
| 
 | |
|   return(r);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				req_readwrite				     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC int req_readwrite(fs_e, inode_nr, pos, rw_flag, user_e,
 | |
| 	user_addr, num_of_bytes, new_posp, cum_iop)
 | |
| endpoint_t fs_e;
 | |
| ino_t inode_nr;
 | |
| u64_t pos;
 | |
| int rw_flag;
 | |
| endpoint_t user_e;
 | |
| char *user_addr;
 | |
| unsigned int num_of_bytes;
 | |
| u64_t *new_posp;
 | |
| unsigned int *cum_iop;
 | |
| {
 | |
|   int r;
 | |
|   cp_grant_id_t grant_id;
 | |
|   message m;
 | |
| 
 | |
|   if (ex64hi(pos) != 0)
 | |
| 	  panic("req_readwrite: pos too large");
 | |
| 
 | |
|   grant_id = cpf_grant_magic(fs_e, user_e, (vir_bytes) user_addr, num_of_bytes,
 | |
|   			     (rw_flag==READING ? CPF_WRITE:CPF_READ));
 | |
|   if (grant_id == -1)
 | |
| 	  panic("req_readwrite: cpf_grant_magic failed");
 | |
| 
 | |
|   /* Fill in request message */
 | |
|   m.m_type = rw_flag == READING ? REQ_READ : REQ_WRITE;
 | |
|   m.REQ_INODE_NR = inode_nr;
 | |
|   m.REQ_GRANT = grant_id;
 | |
|   m.REQ_SEEK_POS_LO = ex64lo(pos);
 | |
|   m.REQ_SEEK_POS_HI = 0;	/* Not used for now, so clear it. */
 | |
|   m.REQ_NBYTES = num_of_bytes;
 | |
|   
 | |
|   /* Send/rec request */
 | |
|   r = fs_sendrec(fs_e, &m);
 | |
|   cpf_revoke(grant_id);
 | |
| 
 | |
|   if (r == OK) {
 | |
| 	/* Fill in response structure */
 | |
| 	*new_posp = cvul64(m.RES_SEEK_POS_LO);
 | |
| 	*cum_iop = m.RES_NBYTES;
 | |
|   }
 | |
|   
 | |
|   return(r);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				req_rename	     			     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC int req_rename(fs_e, old_dir, old_name, new_dir, new_name)
 | |
| endpoint_t fs_e;
 | |
| ino_t old_dir;
 | |
| char *old_name;
 | |
| ino_t new_dir;
 | |
| char *new_name;
 | |
| {
 | |
|   int r;
 | |
|   cp_grant_id_t gid_old, gid_new;
 | |
|   size_t len_old, len_new;
 | |
|   message m;
 | |
| 
 | |
|   len_old = strlen(old_name) + 1;
 | |
|   gid_old = cpf_grant_direct(fs_e, (vir_bytes) old_name, len_old, CPF_READ);
 | |
|   if(gid_old == -1)
 | |
| 	  panic("req_rename: cpf_grant_direct failed");
 | |
| 
 | |
|   len_new = strlen(new_name) + 1;
 | |
|   gid_new = cpf_grant_direct(fs_e, (vir_bytes) new_name, len_new, CPF_READ);
 | |
|   if(gid_new == -1)
 | |
| 	  panic("req_rename: cpf_grant_direct failed");
 | |
| 
 | |
|   /* Fill in request message */
 | |
|   m.m_type = REQ_RENAME;
 | |
|   m.REQ_REN_OLD_DIR = old_dir;
 | |
|   m.REQ_REN_NEW_DIR = new_dir;
 | |
|   m.REQ_REN_GRANT_OLD = gid_old;
 | |
|   m.REQ_REN_LEN_OLD = len_old;
 | |
|   m.REQ_REN_GRANT_NEW = gid_new;
 | |
|   m.REQ_REN_LEN_NEW = len_new;
 | |
|   
 | |
|   /* Send/rec request */
 | |
|   r = fs_sendrec(fs_e, &m);
 | |
|   cpf_revoke(gid_old);
 | |
|   cpf_revoke(gid_new);
 | |
| 
 | |
|   return(r);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				req_rmdir	      			     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC int req_rmdir(fs_e, inode_nr, lastc)
 | |
| endpoint_t fs_e;
 | |
| ino_t inode_nr;
 | |
| char *lastc;
 | |
| {
 | |
|   int r;
 | |
|   cp_grant_id_t grant_id;
 | |
|   size_t len;
 | |
|   message m;
 | |
|   
 | |
|   len = strlen(lastc) + 1;
 | |
|   grant_id = cpf_grant_direct(fs_e, (vir_bytes) lastc, len, CPF_READ);
 | |
|   if(grant_id == -1)
 | |
| 	  panic("req_rmdir: cpf_grant_direct failed");
 | |
| 
 | |
|   /* Fill in request message */
 | |
|   m.m_type = REQ_RMDIR;
 | |
|   m.REQ_INODE_NR = inode_nr;
 | |
|   m.REQ_GRANT = grant_id;
 | |
|   m.REQ_PATH_LEN = len;
 | |
| 
 | |
|   /* Send/rec request */
 | |
|   r = fs_sendrec(fs_e, &m);
 | |
|   cpf_revoke(grant_id);
 | |
| 
 | |
|   return(r);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				req_slink	      			     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC int req_slink(
 | |
|   endpoint_t fs_e,
 | |
|   ino_t inode_nr,
 | |
|   char *lastc,
 | |
|   endpoint_t who_e,
 | |
|   char *path_addr,
 | |
|   unsigned short path_length,
 | |
|   uid_t uid,
 | |
|   gid_t gid
 | |
| )
 | |
| {
 | |
|   int r;
 | |
|   size_t len;
 | |
|   cp_grant_id_t gid_name, gid_buf;
 | |
|   message m;
 | |
| 
 | |
|   len = strlen(lastc) + 1;
 | |
|   gid_name = cpf_grant_direct(fs_e, (vir_bytes) lastc, len, CPF_READ);
 | |
|   if(gid_name == -1)
 | |
| 	  panic("req_slink: cpf_grant_direct failed");
 | |
| 
 | |
|   gid_buf = cpf_grant_magic(fs_e, who_e, (vir_bytes) path_addr, path_length,
 | |
| 			    CPF_READ);
 | |
|   if(gid_buf == -1) {
 | |
| 	  cpf_revoke(gid_name);
 | |
| 	  panic("req_slink: cpf_grant_magic failed");
 | |
|   }
 | |
| 
 | |
|   /* Fill in request message */
 | |
|   m.m_type = REQ_SLINK;
 | |
|   m.REQ_INODE_NR = inode_nr;
 | |
|   m.REQ_UID = uid;
 | |
|   m.REQ_GID = gid;
 | |
|   m.REQ_GRANT = gid_name;
 | |
|   m.REQ_PATH_LEN = len;
 | |
|   m.REQ_GRANT3 = gid_buf;
 | |
|   m.REQ_MEM_SIZE = path_length;
 | |
| 
 | |
|   /* Send/rec request */
 | |
|   r = fs_sendrec(fs_e, &m);
 | |
|   cpf_revoke(gid_name);
 | |
|   cpf_revoke(gid_buf);
 | |
| 
 | |
|   return(r);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				req_stat	       			     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC int req_stat(fs_e, inode_nr, who_e, buf, pos, stat_version)
 | |
| int fs_e;
 | |
| ino_t inode_nr;
 | |
| int who_e;
 | |
| char *buf;
 | |
| int pos;
 | |
| int stat_version;
 | |
| {
 | |
|   cp_grant_id_t grant_id;
 | |
|   int r;
 | |
|   message m;
 | |
|   struct stat sb;
 | |
|   struct minix_prev_stat old_sb; /* for backward compatibility */
 | |
| 
 | |
|   if (pos != 0 || stat_version != 0)
 | |
| 	  grant_id = cpf_grant_direct(fs_e, (vir_bytes) &sb,
 | |
| 	  			      sizeof(struct stat), CPF_WRITE);
 | |
|   else
 | |
| 	  grant_id = cpf_grant_magic(fs_e, who_e, (vir_bytes) buf,
 | |
| 				sizeof(struct stat), CPF_WRITE);
 | |
| 
 | |
|   if (grant_id < 0)
 | |
| 	panic("req_stat: cpf_grant_* failed");
 | |
| 
 | |
|   /* Fill in request message */
 | |
|   m.m_type = REQ_STAT;
 | |
|   m.REQ_INODE_NR = inode_nr;
 | |
|   m.REQ_GRANT = grant_id;
 | |
| 
 | |
|   /* Send/rec request */
 | |
|   r = fs_sendrec(fs_e, &m);
 | |
|   cpf_revoke(grant_id);
 | |
| 
 | |
|   if (r != OK || (pos == 0 && stat_version == 0))
 | |
| 	return(r);
 | |
| 
 | |
|   if (pos != 0)
 | |
| 	sb.st_size -= pos;
 | |
|   if (stat_version == 0) {
 | |
| 	r = sys_vircopy(SELF, D, (vir_bytes) &sb, who_e, D, (vir_bytes) buf, 
 | |
| 			sizeof(struct stat));
 | |
| 	return(r);
 | |
|   }
 | |
| 
 | |
|   /* User needs old struct stat.
 | |
|    * Just 1 prev version at this moment */
 | |
|   assert(stat_version == 1);
 | |
|  
 | |
| /* XXX until that st_Xtime macroses used, we have to undefine them,
 | |
|  * because of minix_prev_stat
 | |
|  */
 | |
| #undef st_atime
 | |
| #undef st_ctime
 | |
| #undef st_mtime
 | |
| 
 | |
| /* Copy field by field because of st_gid type mismath and
 | |
|  * difference in order after atime.
 | |
|  */
 | |
|   old_sb.st_dev = sb.st_dev;
 | |
|   old_sb.st_ino = sb.st_ino;
 | |
|   old_sb.st_mode = sb.st_mode;
 | |
|   old_sb.st_nlink = sb.st_nlink;
 | |
|   old_sb.st_uid = sb.st_uid;
 | |
|   old_sb.st_gid = sb.st_gid;
 | |
|   old_sb.st_rdev = sb.st_rdev;
 | |
|   old_sb.st_size = sb.st_size;
 | |
| #if defined(_NETBSD_SOURCE)
 | |
|   old_sb.st_atime = sb.st_atimespec.tv_sec;
 | |
|   old_sb.st_mtime = sb.st_mtimespec.tv_sec;
 | |
|   old_sb.st_ctime = sb.st_ctimespec.tv_sec;
 | |
| #else
 | |
|   old_sb.st_atime = sb.st_atime;
 | |
|   old_sb.st_mtime = sb.st_mtime;
 | |
|   old_sb.st_ctime = sb.st_ctime;
 | |
| #endif
 | |
| 
 | |
|   r = sys_vircopy(SELF, D, (vir_bytes) &old_sb, who_e, D, (vir_bytes) buf, 
 | |
| 		  sizeof(struct minix_prev_stat));
 | |
|   
 | |
|   return(r);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				req_sync	       			     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC int req_sync(fs_e)
 | |
| endpoint_t fs_e; 
 | |
| {
 | |
|   message m;
 | |
| 
 | |
|   /* Fill in request message */
 | |
|   m.m_type = REQ_SYNC;
 | |
|   
 | |
|   /* Send/rec request */
 | |
|   return fs_sendrec(fs_e, &m);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				req_unlink	     			     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC int req_unlink(fs_e, inode_nr, lastc)
 | |
| endpoint_t fs_e;
 | |
| ino_t inode_nr;
 | |
| char *lastc;
 | |
| {
 | |
|   cp_grant_id_t grant_id;
 | |
|   size_t len;
 | |
|   int r;
 | |
|   message m;
 | |
|   
 | |
|   len = strlen(lastc) + 1;
 | |
|   grant_id = cpf_grant_direct(fs_e, (vir_bytes) lastc, len, CPF_READ);
 | |
|   if(grant_id == -1)
 | |
| 	  panic("req_unlink: cpf_grant_direct failed");
 | |
| 
 | |
|   /* Fill in request message */
 | |
|   m.m_type = REQ_UNLINK;
 | |
|   m.REQ_INODE_NR = inode_nr;
 | |
|   m.REQ_GRANT = grant_id;
 | |
|   m.REQ_PATH_LEN = len;
 | |
| 
 | |
|   /* Send/rec request */
 | |
|   r = fs_sendrec(fs_e, &m);
 | |
|   cpf_revoke(grant_id);
 | |
|   
 | |
|   return(r);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				req_unmount	    			     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC int req_unmount(fs_e)
 | |
| endpoint_t fs_e; 
 | |
| {
 | |
|   message m;
 | |
| 
 | |
|   /* Fill in request message */
 | |
|   m.m_type = REQ_UNMOUNT;
 | |
|     
 | |
|   /* Send/rec request */
 | |
|   return fs_sendrec(fs_e, &m);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				req_utime	      			     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC int req_utime(fs_e, inode_nr, actime, modtime)
 | |
| endpoint_t fs_e;
 | |
| ino_t inode_nr;
 | |
| time_t actime;
 | |
| time_t modtime;
 | |
| {
 | |
|   message m;
 | |
| 
 | |
|   /* Fill in request message */
 | |
|   m.m_type = REQ_UTIME;
 | |
|   m.REQ_INODE_NR = inode_nr;
 | |
|   m.REQ_ACTIME = actime;
 | |
|   m.REQ_MODTIME = modtime;
 | |
|   
 | |
|   /* Send/rec request */
 | |
|   return fs_sendrec(fs_e, &m);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				fs_sendrec				     *
 | |
|  *===========================================================================*/
 | |
| PRIVATE int fs_sendrec_f(char *file, int line, endpoint_t fs_e, message *reqm)
 | |
| {
 | |
| /* This is the low level function that sends requests to FS processes.
 | |
|  * It also handles driver recovery mechanism and reissuing the
 | |
|  * request which failed due to a dead driver.
 | |
|  */
 | |
|   int r;
 | |
|   message origm;
 | |
| 
 | |
|   if(fs_e <= 0 || fs_e == NONE)
 | |
| 	panic("talking to bogus endpoint: %d", fs_e);
 | |
| 
 | |
|   /* Make a copy of the request so that we can load it back in
 | |
|    * case of a dead driver */
 | |
|   origm = *reqm;
 | |
| 
 | |
|   /* In response to the request we sent, some file systems may send back their
 | |
|    * own VFS request, instead of a reply. VFS currently offers limited support
 | |
|    * for this. As long as the FS keeps sending requests, we process them and
 | |
|    * send back a reply. We break out of the loop as soon as the FS sends a
 | |
|    * reply to the original request.
 | |
|    *
 | |
|    * There is no form of locking or whatever on global data structures, so it
 | |
|    * is quite easy to mess things up; hence, 'limited' support. A future async
 | |
|    * VFS will solve this problem for good.
 | |
|    */
 | |
|   for (;;) {
 | |
| 	/* Do the actual send, receive */
 | |
| 	if (OK != (r = sendrec(fs_e, reqm))) {
 | |
| 		printf("VFS:fs_sendrec:%s:%d: error sending message. "
 | |
| 		       "FS_e: %d req_nr: %d err: %d\n", file, line, fs_e,
 | |
| 		       reqm->m_type, r);
 | |
| 		util_stacktrace();
 | |
| 		return(r);
 | |
| 	}
 | |
| 
 | |
| 	/* If the type field is 0 (OK) or negative (E*), this is a reply. If it
 | |
| 	 * contains a positive nonzero value, this is a request.
 | |
| 	 */
 | |
| 	if (reqm->m_type <= 0)
 | |
| 		break; /* Reply */
 | |
| 
 | |
| 	/* Request */
 | |
| 	nested_fs_call(reqm);
 | |
|   }
 | |
| 
 | |
|   /* Return message type */
 | |
|   return(reqm->m_type);
 | |
| }
 | |
| 
 |