Initialize root directory to have proper i_size.
[omfsprogs.git] / omfs.c
blob34af274ebb2f52efa345aba042c9fee9a6ccef85
1 /*
2 * Super/root block reading routines
3 */
4 #define _GNU_SOURCE
5 #define _FILE_OFFSET_BITS 64
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <ctype.h>
11 #include "omfs.h"
12 #include "crc.h"
14 static void _omfs_swap_buffer(void *buf, int count)
16 #ifdef RTV_HACK
17 // only valid for Replay 4xxx and 5xxx: unconditionally force change
18 // of endianness
19 int i;
20 u32 *ibuf = (u32 *) buf;
21 count >>= 2;
23 for (i=0; i<count; i++)
24 ibuf[i] = __swap32(ibuf[i]);
25 #endif
29 * Write the superblock to disk
31 int omfs_write_super(FILE *dev, struct omfs_super_block *super)
33 int count;
35 fseeko(dev, 0LL, SEEK_SET);
36 _omfs_swap_buffer(super, sizeof(struct omfs_super_block));
37 count = fwrite(super, 1, sizeof(struct omfs_super_block), dev);
39 if (count < sizeof(struct omfs_super_block))
40 return -1;
42 return 0;
46 * Read the superblock and store the result in ret
48 int omfs_read_super(FILE *dev, struct omfs_super_block *ret)
50 int count;
52 fseeko(dev, 0LL, SEEK_SET);
53 count = fread(ret, 1, sizeof(struct omfs_super_block), dev);
55 if (count < sizeof(struct omfs_super_block))
56 return -1;
58 _omfs_swap_buffer(ret, count);
59 return 0;
62 static int _omfs_write_block(FILE *dev, struct omfs_super_block *sb,
63 u64 block, u8* buf, size_t len)
65 int i, count;
66 _omfs_swap_buffer(buf, len);
67 for (i=0; i<swap_be32(sb->mirrors); i++)
69 fseeko(dev, (block + i) * swap_be32(sb->blocksize), SEEK_SET);
70 count = fwrite(buf, 1, len, dev);
71 if (count != len)
72 return -1;
74 return 0;
79 * Read the numbered block into a raw array.
80 * buf must be at least blocksize bytes.
82 static int _omfs_read_block(FILE *dev, struct omfs_super_block *sb,
83 u64 block, u8 *buf)
85 int count;
86 fseeko(dev, block * swap_be32(sb->blocksize), SEEK_SET);
87 count = fread(buf, 1, swap_be32(sb->blocksize), dev);
89 if (count < swap_be32(sb->blocksize))
90 return -1;
92 _omfs_swap_buffer(buf, count);
93 return 0;
96 static void _update_header_checksums(u8 *buf, int block_size)
98 int xor, i;
99 omfs_header_t *header = (omfs_header_t *) buf;
100 u8 *body = buf + sizeof(omfs_header_t);
101 int body_size = block_size - sizeof(omfs_header_t);
103 header->crc = swap_be16(crc_ccitt_msb(0, body, body_size));
105 xor = buf[0];
106 for (i=1; i<OMFS_XOR_COUNT; i++)
107 xor ^= buf[i];
108 header->check_xor = xor;
112 int omfs_write_root_block(FILE *dev, struct omfs_super_block *sb,
113 struct omfs_root_block *root)
115 u64 block = swap_be64(root->head.self);
116 return _omfs_write_block(dev, sb, block, (u8*) root,
117 sizeof(struct omfs_root_block));
121 int omfs_read_root_block(FILE *dev, struct omfs_super_block *sb,
122 struct omfs_root_block *root)
124 u8 *buf;
126 buf = omfs_get_block(dev, sb, swap_be64(sb->root_block));
127 if (!buf)
128 return -1;
130 memcpy(root, buf, sizeof(struct omfs_root_block));
131 free(buf);
132 return 0;
135 u8 *omfs_get_block(FILE *dev, struct omfs_super_block *sb, u64 block)
137 u8 *buf;
138 if (!(buf = malloc(swap_be32(sb->blocksize))))
139 return 0;
141 if (_omfs_read_block(dev, sb, block, buf))
143 free(buf);
144 return 0;
147 return buf;
151 * Write an inode to the device.
153 int omfs_write_inode(omfs_info_t *info, omfs_inode_t *inode)
155 int size = swap_be32(inode->head.body_size) + sizeof(omfs_header_t);
157 _update_header_checksums((u8*)inode, size);
159 return _omfs_write_block(info->dev, info->super,
160 swap_be64(inode->head.self), (u8*) inode, size);
163 omfs_inode_t *omfs_get_inode(omfs_info_t *info, u64 block)
165 u8 *buf;
166 buf = omfs_get_block(info->dev, info->super, block);
167 if (!buf)
168 return NULL;
170 return (omfs_inode_t *) buf;
173 void omfs_release_inode(omfs_inode_t *oi)
175 free(oi);
178 int omfs_write_bitmap(omfs_info_t *info, u8* bitmap)
180 size_t size, count;
181 u64 bitmap_blk = swap_be64(info->root->bitmap);
183 size = (swap_be64(info->super->num_blocks) + 7) / 8;
184 fseeko(info->dev, bitmap_blk * swap_be32(info->super->blocksize),
185 SEEK_SET);
186 count = fwrite(bitmap, 1, size, info->dev);
187 if (size != count)
188 return -1;
189 return 0;
192 u8 *omfs_get_bitmap(omfs_info_t *info)
194 size_t size;
195 u8 *buf;
196 u64 bitmap_blk = swap_be64(info->root->bitmap);
197 if (bitmap_blk == ~0)
198 return NULL;
200 size = (swap_be64(info->super->num_blocks) + 7) / 8;
202 if (!(buf = malloc(size)))
203 return NULL;
205 fseeko(info->dev, bitmap_blk * swap_be32(info->super->blocksize), SEEK_SET);
206 fread(buf, 1, size, info->dev);
207 return buf;
210 int omfs_compute_hash(omfs_info_t *info, char *filename)
212 int hash = 0, i;
213 int m = (swap_be32(info->super->sys_blocksize) - OMFS_DIR_START) / 8;
215 for (i=0; i<strlen(filename); i++)
216 hash ^= tolower(filename[i]) << (i % 24);
218 return hash % m;
221 void omfs_sync(omfs_info_t *info)
223 fflush(info->dev);