Unify process_alloc() and process_realloc() with PROCESS_ALLOC_MODE_REALLOC bit
[moveable_pool.git] / mkfs.c
1
2 /**************************************************
3 UZI (Unix Z80 Implementation) Utilities:  mkfs.c
4 ***************************************************/
5
6 #include <stdio.h>
7 #include <stdint.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <sys/types.h>
11 #include <unistd.h>
12 #include <sys/stat.h>
13 #include "fuzix_fs.h"
14 #include "util.h"
15
16 /* This makes a filesystem 
17  *
18  * example use:
19  *   ./mkfs ./blankfs.img 64 4096
20  * (this will write a 2MB filesystem with 64 blocks of inodes to ./blankfs.img)
21  *
22  * */
23
24 char zero512[512];
25
26 direct dirbuf[64] = {
27         { ROOTINODE, "." },
28         { ROOTINODE, ".."}
29 };
30
31 struct dinode inode[8];
32 int swizzling = 0;
33
34 void mkfs(uint16_t fsize, uint16_t isize, uint8_t shift);
35 void dwrite(uint16_t blk, char *addr);
36
37 union disk {
38         struct filesys fs;
39         uint8_t zero[512];
40 } fs_super;
41
42 static void usage(void)
43 {
44         printf("Usage: mkfs [-X] [-b blocksize] device isize fsize\n");
45         exit(1);
46 }
47
48 static uint8_t validate(uint16_t bsize)
49 {
50         switch(bsize) {
51         case 512:
52                 return 0;
53         case 1024:
54                 return 1;
55         case 2048:
56                 return 2;
57         case 4096:
58                 return 3;
59         case 8192:
60                 return 4;
61         case 16384:
62                 return 5;
63         default:
64                 fprintf(stderr, "mkfs: unsupported block size.\n");
65                 exit(1);
66         }
67 }
68
69 int main(int argc, char **argv)
70 {
71         uint16_t fsize, isize, bsize = 512, shift = 0;
72         uint16_t j;
73         uint32_t s;
74         int opt;
75
76         while((opt = getopt(argc, argv, "Xb:")) != -1) {
77                 switch(opt) {
78                         case 'X':       
79                                 swizzling = 1;
80                                 break;
81                         case 'b':
82                                 bsize = atoi(optarg);
83                                 shift = validate(bsize);
84                                 break;
85                         default:
86                                 usage();
87                 }
88         }
89         if (argc - optind != 3)
90                 usage();
91
92         if (sizeof(inode) != 512) {
93                 printf("inode is the wrong size -- %d\n",
94                        (int) sizeof(inode));
95         }
96
97         isize = (uint16_t) atoi(argv[optind + 1]);
98         fsize = (uint16_t) atoi(argv[optind + 2]);
99
100         if (fsize < 3 || isize < 2 || isize >= fsize) {
101                 printf("Bad parameter values\n");
102                 return -1;
103         }
104
105         memset(zero512, 0, 512);
106
107         printf("Making %d byte/block filesystem with %s byte order on device %s with fsize = %u and isize = %u.\n",
108                bsize, swizzling==0 ? "normal" : "reversed", argv[optind], fsize, isize);
109
110         if (fd_open(argv[optind])) {
111                 printf("Can't open device");
112                 return -1;
113         }
114
115         s = fsize << shift;
116
117         /* Zero out the blocks */
118         for (j = 0; j < s; ++j)
119                 dwrite(j, zero512);
120
121         /* Initialize the super-block */
122
123         fs_super.fs.s_mounted = swizzle16(SMOUNTED);    /* Magic number */
124         fs_super.fs.s_isize = swizzle16(isize);
125         fs_super.fs.s_fsize = swizzle16(fsize);
126         fs_super.fs.s_nfree = swizzle16(1);
127         fs_super.fs.s_free[0] = 0;
128         fs_super.fs.s_tfree = 0;
129         fs_super.fs.s_ninode = 0;
130         fs_super.fs.s_tinode = swizzle16(8 * (isize - 2) - 2);
131         fs_super.fs.s_shift = shift;
132
133         /* Free each block, building the free list. This is done in
134            terms of the block shift, while isize is in 512 byte blocks.
135            Adjust isize so that it's in block terms and references the
136            block after the last inode */
137           
138         isize <<= shift;
139
140         /* Don't free the block isize because it's got the / directory in it */
141         for (j = fsize - 1; j > isize; --j) {
142                 int n;
143                 if (swizzle16(fs_super.fs.s_nfree) == 50) {
144                         dwrite(j, (char *) &fs_super.fs.s_nfree);
145                         fs_super.fs.s_nfree = 0;
146                 }
147
148                 fs_super.fs.s_tfree =
149                     swizzle16(swizzle16(fs_super.fs.s_tfree) + 1);
150                 n = swizzle16(fs_super.fs.s_nfree);
151                 fs_super.fs.s_free[n++] = swizzle16(j);
152                 fs_super.fs.s_nfree = swizzle16(n);
153         }
154
155         /* The inodes are already zeroed out */
156         /* create the root dir */
157         inode[ROOTINODE].i_mode = swizzle16(F_DIR | (0777 & MODE_MASK));
158         inode[ROOTINODE].i_nlink = swizzle16(3);
159         inode[ROOTINODE].i_size = swizzle32(64);
160         inode[ROOTINODE].i_addr[0] = swizzle16(isize);
161
162         /* Reserve reserved inode */
163         inode[0].i_nlink = swizzle16(1);
164         inode[0].i_mode = ~0;
165
166         dwrite(2, (char *) inode);
167
168         dirbuf[0].d_ino = swizzle16(dirbuf[0].d_ino);
169         dirbuf[1].d_ino = swizzle16(dirbuf[1].d_ino);
170         dwrite(isize, (char *) dirbuf);
171
172         /* Write out super block */
173         dwrite(1, (char *) &fs_super);
174         return 0;
175 }
176
177 void dwrite(uint16_t blk, char *addr)
178 {
179         lseek(dev_fd, ((int) blk) * 512, SEEK_SET);
180         if (write(dev_fd, addr, 512) != 512) {
181                 perror("write");
182                 exit(1);
183         }
184 }