xfile.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include "iotrack.h"
  12. #include "dat.h"
  13. #include "fns.h"
  14. #define FIDMOD 127 /* prime */
  15. static Xfs *xhead;
  16. static Xfile *xfiles[FIDMOD], *freelist;
  17. static MLock xlock, xlocks[FIDMOD], freelock;
  18. Xfs *
  19. getxfs(char *user, char *name)
  20. {
  21. Xfs *xf, *fxf;
  22. Dir *dir;
  23. Qid dqid;
  24. char *p, *q;
  25. int32_t offset;
  26. int fd, omode;
  27. USED(user);
  28. if(name==nil || name[0]==0)
  29. name = deffile;
  30. if(name == nil){
  31. errno = Enofilsys;
  32. return 0;
  33. }
  34. /*
  35. * If the name passed is of the form 'name:offset' then
  36. * offset is used to prime xf->offset. This allows accessing
  37. * a FAT-based filesystem anywhere within a partition.
  38. * Typical use would be to mount a filesystem in the presence
  39. * of a boot manager programme at the beginning of the disc.
  40. */
  41. offset = 0;
  42. if(p = strrchr(name, ':')){
  43. *p++ = 0;
  44. offset = strtol((const char *)p, &q, 0);
  45. chat("name %s, offset %ld\n", p, offset);
  46. if(offset < 0 || p == q){
  47. errno = Enofilsys;
  48. return 0;
  49. }
  50. offset *= Sectorsize;
  51. }
  52. if(readonly)
  53. omode = OREAD;
  54. else
  55. omode = ORDWR;
  56. fd = open(name, omode);
  57. if(fd < 0 && omode==ORDWR){
  58. omode = OREAD;
  59. fd = open(name, omode);
  60. }
  61. if(fd < 0){
  62. chat("can't open %s: %r\n", name);
  63. errno = Eerrstr;
  64. return 0;
  65. }
  66. dir = dirfstat(fd);
  67. if(dir == nil){
  68. errno = Eio;
  69. close(fd);
  70. return 0;
  71. }
  72. dqid = dir->qid;
  73. free(dir);
  74. mlock(&xlock);
  75. for(fxf=0,xf=xhead; xf; xf=xf->next){
  76. if(xf->ref == 0){
  77. if(fxf == 0)
  78. fxf = xf;
  79. continue;
  80. }
  81. if(!eqqid(xf->qid, dqid))
  82. continue;
  83. if(strcmp(xf->name, name) != 0 || xf->dev < 0)
  84. continue;
  85. if(devcheck(xf) < 0) /* look for media change */
  86. continue;
  87. if(offset && xf->offset != offset)
  88. continue;
  89. chat("incref \"%s\", dev=%d...", xf->name, xf->dev);
  90. ++xf->ref;
  91. unmlock(&xlock);
  92. close(fd);
  93. return xf;
  94. }
  95. if(fxf == nil){
  96. fxf = malloc(sizeof(Xfs));
  97. if(fxf == nil){
  98. unmlock(&xlock);
  99. close(fd);
  100. errno = Enomem;
  101. return nil;
  102. }
  103. fxf->next = xhead;
  104. xhead = fxf;
  105. }
  106. chat("alloc \"%s\", dev=%d...", name, fd);
  107. fxf->name = strdup(name);
  108. fxf->ref = 1;
  109. fxf->qid = dqid;
  110. fxf->dev = fd;
  111. fxf->fmt = 0;
  112. fxf->offset = offset;
  113. fxf->ptr = nil;
  114. fxf->isfat32 = 0;
  115. fxf->omode = omode;
  116. unmlock(&xlock);
  117. return fxf;
  118. }
  119. void
  120. refxfs(Xfs *xf, int delta)
  121. {
  122. mlock(&xlock);
  123. xf->ref += delta;
  124. if(xf->ref == 0){
  125. chat("free \"%s\", dev=%d...", xf->name, xf->dev);
  126. free(xf->name);
  127. free(xf->ptr);
  128. purgebuf(xf);
  129. if(xf->dev >= 0){
  130. close(xf->dev);
  131. xf->dev = -1;
  132. }
  133. }
  134. unmlock(&xlock);
  135. }
  136. Xfile *
  137. xfile(int fid, int flag)
  138. {
  139. Xfile **hp, *f, *pf;
  140. int k;
  141. k = ((uint32_t)fid) % FIDMOD;
  142. hp = &xfiles[k];
  143. mlock(&xlocks[k]);
  144. pf = nil;
  145. for(f=*hp; f; f=f->next){
  146. if(f->fid == fid)
  147. break;
  148. pf = f;
  149. }
  150. if(f && pf){
  151. pf->next = f->next;
  152. f->next = *hp;
  153. *hp = f;
  154. }
  155. switch(flag){
  156. default:
  157. panic("xfile");
  158. case Asis:
  159. unmlock(&xlocks[k]);
  160. return (f && f->xf && f->xf->dev < 0) ? nil : f;
  161. case Clean:
  162. break;
  163. case Clunk:
  164. if(f){
  165. *hp = f->next;
  166. unmlock(&xlocks[k]);
  167. clean(f);
  168. mlock(&freelock);
  169. f->next = freelist;
  170. freelist = f;
  171. unmlock(&freelock);
  172. } else
  173. unmlock(&xlocks[k]);
  174. return nil;
  175. }
  176. unmlock(&xlocks[k]);
  177. if(f)
  178. return clean(f);
  179. mlock(&freelock);
  180. if(f = freelist){ /* assign = */
  181. freelist = f->next;
  182. unmlock(&freelock);
  183. } else {
  184. unmlock(&freelock);
  185. f = malloc(sizeof(Xfile));
  186. if(f == nil){
  187. errno = Enomem;
  188. return nil;
  189. }
  190. }
  191. mlock(&xlocks[k]);
  192. f->next = *hp;
  193. *hp = f;
  194. unmlock(&xlocks[k]);
  195. f->fid = fid;
  196. f->flags = 0;
  197. f->qid = (Qid){0,0,0};
  198. f->xf = nil;
  199. f->ptr = nil;
  200. return f;
  201. }
  202. Xfile *
  203. clean(Xfile *f)
  204. {
  205. if(f->ptr){
  206. free(f->ptr);
  207. f->ptr = nil;
  208. }
  209. if(f->xf){
  210. refxfs(f->xf, -1);
  211. f->xf = nil;
  212. }
  213. f->flags = 0;
  214. f->qid = (Qid){0,0,0};
  215. return f;
  216. }
  217. /*
  218. * the file at <addr, offset> has moved
  219. * relocate the dos entries of all fids in the same file
  220. */
  221. void
  222. dosptrreloc(Xfile *f, Dosptr *dp, uint32_t addr, uint32_t offset)
  223. {
  224. int i;
  225. Xfile *p;
  226. Dosptr *xdp;
  227. for(i=0; i < FIDMOD; i++){
  228. for(p = xfiles[i]; p != nil; p = p->next){
  229. xdp = p->ptr;
  230. if(p != f && p->xf == f->xf
  231. && xdp != nil && xdp->addr == addr && xdp->offset == offset){
  232. memmove(xdp, dp, sizeof(Dosptr));
  233. xdp->p = nil;
  234. xdp->d = nil;
  235. p->qid.path = QIDPATH(xdp);
  236. }
  237. }
  238. }
  239. }