plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

fid.c (2894B)


      1 #include <u.h>
      2 #include <libc.h>
      3 #include <fcall.h>
      4 #include <9pclient.h>
      5 #include "plumb.h"
      6 
      7 static CFsys *fsplumb;
      8 static int pfd = -1;
      9 static CFid *pfid;
     10 
     11 int
     12 plumbunmount(void)
     13 {
     14 	CFsys *fsys;
     15 
     16 	if(fsplumb){
     17 		fsys = fsplumb;
     18 		fsplumb = nil;
     19 		fsunmount(fsys);
     20 	}
     21 	return 0;
     22 }
     23 
     24 int
     25 plumbopen(char *name, int omode)
     26 {
     27 	if(fsplumb == nil)
     28 		fsplumb = nsmount("plumb", "");
     29 	if(fsplumb == nil)
     30 		return -1;
     31 	/*
     32 	* It's important that when we send something,
     33 	* we find out whether it was a valid plumb write.
     34 	* (If it isn't, the client might fall back to some
     35 	* other mechanism or indicate to the user what happened.)
     36 	* We can't use a pipe for this, so we have to use the
     37 	* fid interface.  But we need to return a fd.
     38 	* Return a fd for /dev/null so that we return a unique
     39 	* file descriptor.  In plumbsend we'll look for pfd
     40 	* and use the recorded fid instead.
     41 	*/
     42 	if((omode&3) == OWRITE){
     43 		if(pfd != -1){
     44 			werrstr("already have plumb send open");
     45 			return -1;
     46 		}
     47 		pfd = open("/dev/null", OWRITE);
     48 		if(pfd < 0)
     49 			return -1;
     50 		pfid = fsopen(fsplumb, name, omode);
     51 		if(pfid == nil){
     52 			close(pfd);
     53 			pfd = -1;
     54 			return -1;
     55 		}
     56 		return pfd;
     57 	}
     58 
     59 	return fsopenfd(fsplumb, name, omode);
     60 }
     61 
     62 CFid*
     63 plumbopenfid(char *name, int mode)
     64 {
     65 	if(fsplumb == nil){
     66 		fsplumb = nsmount("plumb", "");
     67 		if(fsplumb == nil){
     68 			werrstr("mount plumb: %r");
     69 			return nil;
     70 		}
     71 	}
     72 	return fsopen(fsplumb, name, mode);
     73 }
     74 
     75 int
     76 plumbsendtofid(CFid *fid, Plumbmsg *m)
     77 {
     78 	char *buf;
     79 	int n;
     80 
     81 	if(fid == nil){
     82 		werrstr("invalid fid");
     83 		return -1;
     84 	}
     85 	buf = plumbpack(m, &n);
     86 	if(buf == nil)
     87 		return -1;
     88 	n = fswrite(fid, buf, n);
     89 	free(buf);
     90 	return n;
     91 }
     92 
     93 int
     94 plumbsend(int fd, Plumbmsg *m)
     95 {
     96 	if(fd == -1){
     97 		werrstr("invalid fd");
     98 		return -1;
     99 	}
    100 	if(fd != pfd){
    101 		werrstr("fd is not the plumber");
    102 		return -1;
    103 	}
    104 	return plumbsendtofid(pfid, m);
    105 }
    106 
    107 Plumbmsg*
    108 plumbrecv(int fd)
    109 {
    110 	char *buf;
    111 	Plumbmsg *m;
    112 	int n, more;
    113 
    114 	buf = malloc(8192);
    115 	if(buf == nil)
    116 		return nil;
    117 	n = read(fd, buf, 8192);
    118 	m = nil;
    119 	if(n > 0){
    120 		m = plumbunpackpartial(buf, n, &more);
    121 		if(m==nil && more>0){
    122 			/* we now know how many more bytes to read for complete message */
    123 			buf = realloc(buf, n+more);
    124 			if(buf == nil)
    125 				return nil;
    126 			if(readn(fd, buf+n, more) == more)
    127 				m = plumbunpackpartial(buf, n+more, nil);
    128 		}
    129 	}
    130 	free(buf);
    131 	return m;
    132 }
    133 
    134 Plumbmsg*
    135 plumbrecvfid(CFid *fid)
    136 {
    137 	char *buf;
    138 	Plumbmsg *m;
    139 	int n, more;
    140 
    141 	if(fid == nil){
    142 		werrstr("invalid fid");
    143 		return nil;
    144 	}
    145 	buf = malloc(8192);
    146 	if(buf == nil)
    147 		return nil;
    148 	n = fsread(fid, buf, 8192);
    149 	m = nil;
    150 	if(n > 0){
    151 		m = plumbunpackpartial(buf, n, &more);
    152 		if(m==nil && more>0){
    153 			/* we now know how many more bytes to read for complete message */
    154 			buf = realloc(buf, n+more);
    155 			if(buf == nil)
    156 				return nil;
    157 			if(fsreadn(fid, buf+n, more) == more)
    158 				m = plumbunpackpartial(buf, n+more, nil);
    159 		}
    160 	}
    161 	free(buf);
    162 	return m;
    163 }