1 /* 2 * host's snarf buffer 3 */ 4 5 #include "dat.h" 6 #include "fns.h" 7 #include "../port/error.h" 8 9 enum{ 10 Qdir, 11 Qsnarf, 12 13 Maxsnarf= 100*1024 14 }; 15 16 static 17 Dirtab snarftab[]={ 18 ".", {Qdir, 0, QTDIR}, 0, 0555, 19 "snarf", {Qsnarf}, 0, 0666, 20 }; 21 22 static QLock snarflock; /* easiest to synchronise all access */ 23 24 static Chan* 25 snarfattach(char *spec) 26 { 27 return devattach('^', spec); 28 } 29 30 static Walkqid* 31 snarfwalk(Chan *c, Chan *nc, char **name, int nname) 32 { 33 return devwalk(c, nc, name, nname, snarftab, nelem(snarftab), devgen); 34 } 35 36 static int 37 snarfstat(Chan* c, uchar *db, int n) 38 { 39 return devstat(c, db, n, snarftab, nelem(snarftab), devgen); 40 } 41 42 static Chan* 43 snarfopen(Chan* c, int omode) 44 { 45 c = devopen(c, omode, snarftab, nelem(snarftab), devgen); 46 if(c->qid.path == Qsnarf){ 47 if(c->mode == ORDWR || c->mode == OWRITE){ 48 qlock(&snarflock); 49 free(c->aux); 50 c->aux = nil; 51 qunlock(&snarflock); 52 } 53 } 54 return c; 55 } 56 57 static void 58 snarfclose(Chan* c) 59 { 60 if((c->flag & COPEN) == 0) 61 return; 62 if(c->qid.path == Qsnarf){ 63 /* this must be the last reference: no need to lock */ 64 if(c->mode == ORDWR || c->mode == OWRITE){ 65 if(!waserror()){ 66 if(c->aux != nil) 67 clipwrite(c->aux); 68 poperror(); 69 } 70 } 71 free(c->aux); 72 } 73 } 74 75 static long 76 snarfread(Chan* c, void* a, long n, vlong offset) 77 { 78 void *p; 79 80 switch((ulong)c->qid.path){ 81 case Qdir: 82 return devdirread(c, a, n, snarftab, nelem(snarftab), devgen); 83 case Qsnarf: 84 qlock(&snarflock); 85 if(waserror()){ 86 qunlock(&snarflock); 87 nexterror(); 88 } 89 if(offset == 0){ 90 p = c->aux; 91 c->aux = nil; 92 free(p); 93 c->aux = clipread(); 94 } 95 if(c->aux != nil) 96 n = readstr(offset, a, n, c->aux); 97 else 98 n = 0; 99 poperror(); 100 qunlock(&snarflock); 101 break; 102 default: 103 n=0; 104 break; 105 } 106 return n; 107 } 108 109 static long 110 snarfwrite(Chan* c, void* va, long n, vlong offset) 111 { 112 ulong l; 113 char *p; 114 115 switch((ulong)c->qid.path){ 116 case Qsnarf: 117 /* append only */ 118 USED(offset); /* not */ 119 qlock(&snarflock); 120 if(waserror()){ 121 qunlock(&snarflock); 122 nexterror(); 123 } 124 if(c->aux != nil) 125 l = strlen(c->aux); 126 else 127 l = 0; 128 if(l+n > Maxsnarf) 129 error(Etoobig); 130 c->aux = realloc(c->aux, l+n+1); 131 if((p = c->aux) == nil) 132 error(Enovmem); 133 memmove(p+l, va, n); 134 p[l+n] = 0; 135 snarftab[1].qid.vers++; 136 poperror(); 137 qunlock(&snarflock); 138 break; 139 default: 140 error(Ebadusefd); 141 } 142 return n; 143 } 144 145 Dev snarfdevtab = { 146 '^', 147 "snarf", 148 149 devinit, 150 snarfattach, 151 snarfwalk, 152 snarfstat, 153 snarfopen, 154 devcreate, 155 snarfclose, 156 snarfread, 157 devbread, 158 snarfwrite, 159 devbwrite, 160 devremove, 161 devwstat, 162 }; 163