mkfs.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <fcntl.h>
  6. #include <assert.h>
  7. #define stat xv6_stat // avoid clash with host struct stat
  8. #include "types.h"
  9. #include "fs.h"
  10. #include "stat.h"
  11. #include "param.h"
  12. #define static_assert(a, b) do { switch (0) case 0: case (a): ; } while (0)
  13. int nblocks = 985;
  14. int nlog = LOGSIZE;
  15. int ninodes = 200;
  16. int size = 1024;
  17. int fsfd;
  18. struct superblock sb;
  19. char zeroes[512];
  20. uint freeblock;
  21. uint usedblocks;
  22. uint bitblocks;
  23. uint freeinode = 1;
  24. void balloc(int);
  25. void wsect(uint, void*);
  26. void winode(uint, struct dinode*);
  27. void rinode(uint inum, struct dinode *ip);
  28. void rsect(uint sec, void *buf);
  29. uint ialloc(ushort type);
  30. void iappend(uint inum, void *p, int n);
  31. // convert to intel byte order
  32. ushort
  33. xshort(ushort x)
  34. {
  35. ushort y;
  36. uchar *a = (uchar*)&y;
  37. a[0] = x;
  38. a[1] = x >> 8;
  39. return y;
  40. }
  41. uint
  42. xint(uint x)
  43. {
  44. uint y;
  45. uchar *a = (uchar*)&y;
  46. a[0] = x;
  47. a[1] = x >> 8;
  48. a[2] = x >> 16;
  49. a[3] = x >> 24;
  50. return y;
  51. }
  52. int
  53. main(int argc, char *argv[])
  54. {
  55. int i, cc, fd;
  56. uint rootino, inum, off;
  57. struct dirent de;
  58. char buf[512];
  59. struct dinode din;
  60. static_assert(sizeof(int) == 4, "Integers must be 4 bytes!");
  61. if(argc < 2){
  62. fprintf(stderr, "Usage: mkfs fs.img files...\n");
  63. exit(1);
  64. }
  65. assert((512 % sizeof(struct dinode)) == 0);
  66. assert((512 % sizeof(struct dirent)) == 0);
  67. fsfd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666);
  68. if(fsfd < 0){
  69. perror(argv[1]);
  70. exit(1);
  71. }
  72. sb.size = xint(size);
  73. sb.nblocks = xint(nblocks); // so whole disk is size sectors
  74. sb.ninodes = xint(ninodes);
  75. sb.nlog = xint(nlog);
  76. bitblocks = size/(512*8) + 1;
  77. usedblocks = ninodes / IPB + 3 + bitblocks;
  78. freeblock = usedblocks;
  79. printf("used %d (bit %d ninode %zu) free %u log %u total %d\n", usedblocks,
  80. bitblocks, ninodes/IPB + 1, freeblock, nlog, nblocks+usedblocks+nlog);
  81. assert(nblocks + usedblocks + nlog == size);
  82. for(i = 0; i < nblocks + usedblocks + nlog; i++)
  83. wsect(i, zeroes);
  84. memset(buf, 0, sizeof(buf));
  85. memmove(buf, &sb, sizeof(sb));
  86. wsect(1, buf);
  87. rootino = ialloc(T_DIR);
  88. assert(rootino == ROOTINO);
  89. bzero(&de, sizeof(de));
  90. de.inum = xshort(rootino);
  91. strcpy(de.name, ".");
  92. iappend(rootino, &de, sizeof(de));
  93. bzero(&de, sizeof(de));
  94. de.inum = xshort(rootino);
  95. strcpy(de.name, "..");
  96. iappend(rootino, &de, sizeof(de));
  97. for(i = 2; i < argc; i++){
  98. assert(index(argv[i], '/') == 0);
  99. if((fd = open(argv[i], 0)) < 0){
  100. perror(argv[i]);
  101. exit(1);
  102. }
  103. // Skip leading _ in name when writing to file system.
  104. // The binaries are named _rm, _cat, etc. to keep the
  105. // build operating system from trying to execute them
  106. // in place of system binaries like rm and cat.
  107. if(argv[i][0] == '_')
  108. ++argv[i];
  109. inum = ialloc(T_FILE);
  110. bzero(&de, sizeof(de));
  111. de.inum = xshort(inum);
  112. strncpy(de.name, argv[i], DIRSIZ);
  113. iappend(rootino, &de, sizeof(de));
  114. while((cc = read(fd, buf, sizeof(buf))) > 0)
  115. iappend(inum, buf, cc);
  116. close(fd);
  117. }
  118. // fix size of root inode dir
  119. rinode(rootino, &din);
  120. off = xint(din.size);
  121. off = ((off/BSIZE) + 1) * BSIZE;
  122. din.size = xint(off);
  123. winode(rootino, &din);
  124. balloc(usedblocks);
  125. exit(0);
  126. }
  127. void
  128. wsect(uint sec, void *buf)
  129. {
  130. if(lseek(fsfd, sec * 512L, 0) != sec * 512L){
  131. perror("lseek");
  132. exit(1);
  133. }
  134. if(write(fsfd, buf, 512) != 512){
  135. perror("write");
  136. exit(1);
  137. }
  138. }
  139. uint
  140. i2b(uint inum)
  141. {
  142. return (inum / IPB) + 2;
  143. }
  144. void
  145. winode(uint inum, struct dinode *ip)
  146. {
  147. char buf[512];
  148. uint bn;
  149. struct dinode *dip;
  150. bn = i2b(inum);
  151. rsect(bn, buf);
  152. dip = ((struct dinode*)buf) + (inum % IPB);
  153. *dip = *ip;
  154. wsect(bn, buf);
  155. }
  156. void
  157. rinode(uint inum, struct dinode *ip)
  158. {
  159. char buf[512];
  160. uint bn;
  161. struct dinode *dip;
  162. bn = i2b(inum);
  163. rsect(bn, buf);
  164. dip = ((struct dinode*)buf) + (inum % IPB);
  165. *ip = *dip;
  166. }
  167. void
  168. rsect(uint sec, void *buf)
  169. {
  170. if(lseek(fsfd, sec * 512L, 0) != sec * 512L){
  171. perror("lseek");
  172. exit(1);
  173. }
  174. if(read(fsfd, buf, 512) != 512){
  175. perror("read");
  176. exit(1);
  177. }
  178. }
  179. uint
  180. ialloc(ushort type)
  181. {
  182. uint inum = freeinode++;
  183. struct dinode din;
  184. bzero(&din, sizeof(din));
  185. din.type = xshort(type);
  186. din.nlink = xshort(1);
  187. din.size = xint(0);
  188. winode(inum, &din);
  189. return inum;
  190. }
  191. void
  192. balloc(int used)
  193. {
  194. uchar buf[512];
  195. int i;
  196. printf("balloc: first %d blocks have been allocated\n", used);
  197. assert(used < 512*8);
  198. bzero(buf, 512);
  199. for(i = 0; i < used; i++){
  200. buf[i/8] = buf[i/8] | (0x1 << (i%8));
  201. }
  202. printf("balloc: write bitmap block at sector %zu\n", ninodes/IPB + 3);
  203. wsect(ninodes / IPB + 3, buf);
  204. }
  205. #define min(a, b) ((a) < (b) ? (a) : (b))
  206. void
  207. iappend(uint inum, void *xp, int n)
  208. {
  209. char *p = (char*)xp;
  210. uint fbn, off, n1;
  211. struct dinode din;
  212. char buf[512];
  213. uint indirect[NINDIRECT];
  214. uint x;
  215. rinode(inum, &din);
  216. off = xint(din.size);
  217. while(n > 0){
  218. fbn = off / 512;
  219. assert(fbn < MAXFILE);
  220. if(fbn < NDIRECT){
  221. if(xint(din.addrs[fbn]) == 0){
  222. din.addrs[fbn] = xint(freeblock++);
  223. usedblocks++;
  224. }
  225. x = xint(din.addrs[fbn]);
  226. } else {
  227. if(xint(din.addrs[NDIRECT]) == 0){
  228. // printf("allocate indirect block\n");
  229. din.addrs[NDIRECT] = xint(freeblock++);
  230. usedblocks++;
  231. }
  232. // printf("read indirect block\n");
  233. rsect(xint(din.addrs[NDIRECT]), (char*)indirect);
  234. if(indirect[fbn - NDIRECT] == 0){
  235. indirect[fbn - NDIRECT] = xint(freeblock++);
  236. usedblocks++;
  237. wsect(xint(din.addrs[NDIRECT]), (char*)indirect);
  238. }
  239. x = xint(indirect[fbn-NDIRECT]);
  240. }
  241. n1 = min(n, (fbn + 1) * 512 - off);
  242. rsect(x, buf);
  243. bcopy(p, buf + off - (fbn * 512), n1);
  244. wsect(x, buf);
  245. n -= n1;
  246. off += n1;
  247. p += n1;
  248. }
  249. din.size = xint(off);
  250. winode(inum, &din);
  251. }