part.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  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 "stdinc.h"
  10. #include <ctype.h>
  11. #include "dat.h"
  12. #include "fns.h"
  13. uint32_t maxblocksize;
  14. int readonly;
  15. static int
  16. strtoullsuf(char *p, char **pp, int rad, uint64_t *u)
  17. {
  18. uint64_t v;
  19. if(!isdigit((unsigned char)*p))
  20. return -1;
  21. v = strtoull(p, &p, rad);
  22. switch(*p){
  23. case 'k':
  24. case 'K':
  25. v *= 1024;
  26. p++;
  27. break;
  28. case 'm':
  29. case 'M':
  30. v *= 1024*1024;
  31. p++;
  32. break;
  33. case 'g':
  34. case 'G':
  35. v *= 1024*1024*1024;
  36. p++;
  37. break;
  38. case 't':
  39. case 'T':
  40. v *= 1024*1024;
  41. v *= 1024*1024;
  42. p++;
  43. break;
  44. }
  45. *pp = p;
  46. *u = v;
  47. return 0;
  48. }
  49. static int
  50. parsepart(char *name, char **file, uint64_t *lo, uint64_t *hi)
  51. {
  52. char *p;
  53. *file = estrdup(name);
  54. if((p = strrchr(*file, ':')) == nil){
  55. *lo = 0;
  56. *hi = 0;
  57. return 0;
  58. }
  59. *p++ = 0;
  60. if(*p == '-')
  61. *lo = 0;
  62. else{
  63. if(strtoullsuf(p, &p, 0, lo) < 0){
  64. free(*file);
  65. return -1;
  66. }
  67. }
  68. if(*p == '-')
  69. p++;
  70. if(*p == 0){
  71. *hi = 0;
  72. return 0;
  73. }
  74. if(strtoullsuf(p, &p, 0, hi) < 0 || *p != 0){
  75. free(*file);
  76. return -1;
  77. }
  78. return 0;
  79. }
  80. Part*
  81. initpart(char *name, int mode)
  82. {
  83. Part *part;
  84. Dir *dir;
  85. char *file;
  86. uint64_t lo, hi;
  87. if(parsepart(name, &file, &lo, &hi) < 0)
  88. return nil;
  89. trace(TraceDisk, "initpart %s file %s lo 0x%llx hi 0x%llx", name, file, lo, hi);
  90. part = MKZ(Part);
  91. part->name = estrdup(name);
  92. part->filename = estrdup(file);
  93. if(readonly){
  94. mode &= ~(OREAD|OWRITE|ORDWR);
  95. mode |= OREAD;
  96. }
  97. part->fd = open(file, mode);
  98. if(part->fd < 0){
  99. if((mode&(OREAD|OWRITE|ORDWR)) == ORDWR)
  100. part->fd = open(file, (mode&~ORDWR)|OREAD);
  101. if(part->fd < 0){
  102. freepart(part);
  103. fprint(2, "can't open partition='%s': %r\n", file);
  104. seterr(EOk, "can't open partition='%s': %r", file);
  105. fprint(2, "%r\n");
  106. free(file);
  107. return nil;
  108. }
  109. fprint(2, "warning: %s opened for reading only\n", name);
  110. }
  111. part->offset = lo;
  112. dir = dirfstat(part->fd);
  113. if(dir == nil){
  114. freepart(part);
  115. seterr(EOk, "can't stat partition='%s': %r", file);
  116. free(file);
  117. return nil;
  118. }
  119. if(dir->length == 0){
  120. free(dir);
  121. freepart(part);
  122. seterr(EOk, "can't determine size of partition %s", file);
  123. free(file);
  124. return nil;
  125. }
  126. if(dir->length < hi || dir->length < lo){
  127. freepart(part);
  128. seterr(EOk, "partition '%s': bounds out of range (max %lld)", name, dir->length);
  129. free(dir);
  130. free(file);
  131. return nil;
  132. }
  133. if(hi == 0)
  134. hi = dir->length;
  135. part->size = hi - part->offset;
  136. free(dir);
  137. return part;
  138. }
  139. int
  140. flushpart(Part *part)
  141. {
  142. USED(part);
  143. return 0;
  144. }
  145. void
  146. freepart(Part *part)
  147. {
  148. if(part == nil)
  149. return;
  150. if(part->fd >= 0)
  151. close(part->fd);
  152. free(part->name);
  153. free(part);
  154. }
  155. void
  156. partblocksize(Part *part, uint32_t blocksize)
  157. {
  158. if(part->blocksize)
  159. sysfatal("resetting partition=%s's block size", part->name);
  160. part->blocksize = blocksize;
  161. if(blocksize > maxblocksize)
  162. maxblocksize = blocksize;
  163. }
  164. enum {
  165. Maxxfer = 64*1024, /* for NCR SCSI controllers; was 128K */
  166. };
  167. int
  168. rwpart(Part *part, int isread, uint64_t offset0, uint8_t *buf0,
  169. uint32_t count0)
  170. {
  171. uint32_t count, opsize;
  172. int n;
  173. uint8_t *buf;
  174. uint64_t offset;
  175. trace(TraceDisk, "%s %s %ud at 0x%llx",
  176. isread ? "read" : "write", part->name, count0, offset0);
  177. if(offset0 >= part->size || offset0+count0 > part->size){
  178. seterr(EStrange, "out of bounds %s offset 0x%llux count %ud to partition %s size 0x%llux",
  179. isread ? "read" : "write", offset0, count0, part->name,
  180. part->size);
  181. return -1;
  182. }
  183. buf = buf0;
  184. count = count0;
  185. offset = offset0;
  186. while(count > 0){
  187. opsize = count;
  188. if(opsize > Maxxfer)
  189. opsize = Maxxfer;
  190. if(isread)
  191. n = pread(part->fd, buf, opsize, offset);
  192. else
  193. n = pwrite(part->fd, buf, opsize, offset);
  194. if(n <= 0){
  195. seterr(EAdmin, "%s %s offset 0x%llux count %ud buf %p returned %d: %r",
  196. isread ? "read" : "write", part->filename, offset, opsize, buf, n);
  197. return -1;
  198. }
  199. offset += n;
  200. count -= n;
  201. buf += n;
  202. }
  203. return count0;
  204. }
  205. int
  206. readpart(Part *part, uint64_t offset, uint8_t *buf, uint32_t count)
  207. {
  208. return rwpart(part, 1, offset, buf, count);
  209. }
  210. int
  211. writepart(Part *part, uint64_t offset, uint8_t *buf, uint32_t count)
  212. {
  213. return rwpart(part, 0, offset, buf, count);
  214. }
  215. ZBlock*
  216. readfile(char *name)
  217. {
  218. Part *p;
  219. ZBlock *b;
  220. p = initpart(name, OREAD);
  221. if(p == nil)
  222. return nil;
  223. b = alloczblock(p->size, 0, p->blocksize);
  224. if(b == nil){
  225. seterr(EOk, "can't alloc %s: %r", name);
  226. freepart(p);
  227. return nil;
  228. }
  229. if(readpart(p, 0, b->data, p->size) < 0){
  230. seterr(EOk, "can't read %s: %r", name);
  231. freepart(p);
  232. freezblock(b);
  233. return nil;
  234. }
  235. freepart(p);
  236. return b;
  237. }