1dc5a79c1SDavid du Colombier /*
2dc5a79c1SDavid du Colombier * ext2subs.c version 0.20
3dc5a79c1SDavid du Colombier *
4dc5a79c1SDavid du Colombier * Some strategic functions come from linux/fs/ext2
5dc5a79c1SDavid du Colombier * kernel sources written by Remy Card.
6dc5a79c1SDavid du Colombier *
7dc5a79c1SDavid du Colombier */
8dc5a79c1SDavid du Colombier
9dc5a79c1SDavid du Colombier #include <u.h>
10dc5a79c1SDavid du Colombier #include <libc.h>
11dc5a79c1SDavid du Colombier #include <bio.h>
12dc5a79c1SDavid du Colombier #include <fcall.h>
13dc5a79c1SDavid du Colombier #include <thread.h>
14dc5a79c1SDavid du Colombier #include <9p.h>
15dc5a79c1SDavid du Colombier #include "dat.h"
16dc5a79c1SDavid du Colombier #include "fns.h"
17dc5a79c1SDavid du Colombier
18dc5a79c1SDavid du Colombier #define putext2(e) putbuf((e).buf)
19dc5a79c1SDavid du Colombier #define dirtyext2(e) dirtybuf((e).buf)
20dc5a79c1SDavid du Colombier
21dc5a79c1SDavid du Colombier static Intmap *uidmap, *gidmap;
22dc5a79c1SDavid du Colombier
23dc5a79c1SDavid du Colombier static int
getnum(char * s,int * n)24dc5a79c1SDavid du Colombier getnum(char *s, int *n)
25dc5a79c1SDavid du Colombier {
26dc5a79c1SDavid du Colombier char *r;
27dc5a79c1SDavid du Colombier
28dc5a79c1SDavid du Colombier *n = strtol(s, &r, 10);
29dc5a79c1SDavid du Colombier return (r != s);
30dc5a79c1SDavid du Colombier }
31dc5a79c1SDavid du Colombier
32dc5a79c1SDavid du Colombier static Intmap*
idfile(char * f)33dc5a79c1SDavid du Colombier idfile(char *f)
34dc5a79c1SDavid du Colombier {
35dc5a79c1SDavid du Colombier Biobuf *bin;
36dc5a79c1SDavid du Colombier Intmap *map;
37dc5a79c1SDavid du Colombier char *fields[3];
38dc5a79c1SDavid du Colombier char *s;
39dc5a79c1SDavid du Colombier int nf, id;
40dc5a79c1SDavid du Colombier
41dc5a79c1SDavid du Colombier map = allocmap(0);
42dc5a79c1SDavid du Colombier bin = Bopen(f, OREAD);
43dc5a79c1SDavid du Colombier if (bin == 0)
44dc5a79c1SDavid du Colombier return 0;
45dc5a79c1SDavid du Colombier while ((s = Brdline(bin, '\n')) != 0) {
46dc5a79c1SDavid du Colombier s[Blinelen(bin)-1] = '\0';
47dc5a79c1SDavid du Colombier nf = getfields(s, fields, 3, 0, ":");
48dc5a79c1SDavid du Colombier if (nf == 3 && getnum(fields[2], &id))
49dc5a79c1SDavid du Colombier insertkey(map, id, strdup(fields[0]));
50dc5a79c1SDavid du Colombier }
51dc5a79c1SDavid du Colombier Bterm(bin);
52dc5a79c1SDavid du Colombier return map;
53dc5a79c1SDavid du Colombier }
54dc5a79c1SDavid du Colombier
55dc5a79c1SDavid du Colombier void
uidfile(char * f)56dc5a79c1SDavid du Colombier uidfile(char *f)
57dc5a79c1SDavid du Colombier {
58dc5a79c1SDavid du Colombier uidmap = idfile(f);
59dc5a79c1SDavid du Colombier }
60dc5a79c1SDavid du Colombier
61dc5a79c1SDavid du Colombier void
gidfile(char * f)62dc5a79c1SDavid du Colombier gidfile(char *f)
63dc5a79c1SDavid du Colombier {
64dc5a79c1SDavid du Colombier gidmap = idfile(f);
65dc5a79c1SDavid du Colombier }
66dc5a79c1SDavid du Colombier
67dc5a79c1SDavid du Colombier static char*
mapuid(int id)68dc5a79c1SDavid du Colombier mapuid(int id)
69dc5a79c1SDavid du Colombier {
70dc5a79c1SDavid du Colombier static char s[12];
71dc5a79c1SDavid du Colombier char *p;
72dc5a79c1SDavid du Colombier
73dc5a79c1SDavid du Colombier if (uidmap && (p = lookupkey(uidmap, id)) != 0)
74dc5a79c1SDavid du Colombier return p;
75dc5a79c1SDavid du Colombier sprint(s, "%d", id);
76dc5a79c1SDavid du Colombier return s;
77dc5a79c1SDavid du Colombier }
78dc5a79c1SDavid du Colombier
79dc5a79c1SDavid du Colombier static char*
mapgid(int id)80dc5a79c1SDavid du Colombier mapgid(int id)
81dc5a79c1SDavid du Colombier {
82dc5a79c1SDavid du Colombier static char s[12];
83dc5a79c1SDavid du Colombier char *p;
84dc5a79c1SDavid du Colombier
85dc5a79c1SDavid du Colombier if (gidmap && (p = lookupkey(gidmap, id)) != 0)
86dc5a79c1SDavid du Colombier return p;
87dc5a79c1SDavid du Colombier sprint(s, "%d", id);
88dc5a79c1SDavid du Colombier return s;
89dc5a79c1SDavid du Colombier }
90dc5a79c1SDavid du Colombier
91dc5a79c1SDavid du Colombier int
ext2fs(Xfs * xf)92dc5a79c1SDavid du Colombier ext2fs(Xfs *xf)
93dc5a79c1SDavid du Colombier {
94dc5a79c1SDavid du Colombier SuperBlock superblock;
95dc5a79c1SDavid du Colombier
96dc5a79c1SDavid du Colombier /* get the super block */
97dc5a79c1SDavid du Colombier seek(xf->dev, OFFSET_SUPER_BLOCK, 0);
98dc5a79c1SDavid du Colombier if( sizeof(SuperBlock) !=
99dc5a79c1SDavid du Colombier read(xf->dev, &superblock, sizeof(SuperBlock)) ){
100dc5a79c1SDavid du Colombier chat("can't read super block %r...", xf->dev);
101dc5a79c1SDavid du Colombier errno = Eformat;
102dc5a79c1SDavid du Colombier return -1;
103dc5a79c1SDavid du Colombier }
104dc5a79c1SDavid du Colombier if( superblock.s_magic != EXT2_SUPER_MAGIC ){
105dc5a79c1SDavid du Colombier chat("Bad super block...");
106dc5a79c1SDavid du Colombier errno = Eformat;
107dc5a79c1SDavid du Colombier return -1;
108dc5a79c1SDavid du Colombier }
109dc5a79c1SDavid du Colombier if( !(superblock.s_state & EXT2_VALID_FS) ){
110dc5a79c1SDavid du Colombier chat("fs not checked...");
111dc5a79c1SDavid du Colombier errno = Enotclean;
112dc5a79c1SDavid du Colombier return -1;
113dc5a79c1SDavid du Colombier }
114dc5a79c1SDavid du Colombier
115dc5a79c1SDavid du Colombier xf->block_size = EXT2_MIN_BLOCK_SIZE << superblock.s_log_block_size;
116dc5a79c1SDavid du Colombier xf->desc_per_block = xf->block_size / sizeof (GroupDesc);
117dc5a79c1SDavid du Colombier xf->inodes_per_group = superblock.s_inodes_per_group;
118dc5a79c1SDavid du Colombier xf->inodes_per_block = xf->block_size / sizeof (Inode);
119dc5a79c1SDavid du Colombier xf->addr_per_block = xf->block_size / sizeof (uint);
120dc5a79c1SDavid du Colombier xf->blocks_per_group = superblock.s_blocks_per_group;
121dc5a79c1SDavid du Colombier
122dc5a79c1SDavid du Colombier if( xf->block_size == OFFSET_SUPER_BLOCK )
123dc5a79c1SDavid du Colombier xf->superaddr = 1, xf->superoff = 0, xf->grpaddr = 2;
124dc5a79c1SDavid du Colombier else if( xf->block_size == 2*OFFSET_SUPER_BLOCK ||
125dc5a79c1SDavid du Colombier xf->block_size == 4*OFFSET_SUPER_BLOCK )
126dc5a79c1SDavid du Colombier xf->superaddr = 0, xf->superoff = OFFSET_SUPER_BLOCK, xf->grpaddr = 1;
127dc5a79c1SDavid du Colombier else {
128dc5a79c1SDavid du Colombier chat(" blocks of %d bytes are not supported...", xf->block_size);
129dc5a79c1SDavid du Colombier errno = Eformat;
130dc5a79c1SDavid du Colombier return -1;
131dc5a79c1SDavid du Colombier }
132dc5a79c1SDavid du Colombier
133dc5a79c1SDavid du Colombier chat("good super block...");
134dc5a79c1SDavid du Colombier
135dc5a79c1SDavid du Colombier xf->ngroups = (superblock.s_blocks_count -
136dc5a79c1SDavid du Colombier superblock.s_first_data_block +
137dc5a79c1SDavid du Colombier superblock.s_blocks_per_group -1) /
138dc5a79c1SDavid du Colombier superblock.s_blocks_per_group;
139dc5a79c1SDavid du Colombier
140dc5a79c1SDavid du Colombier superblock.s_state &= ~EXT2_VALID_FS;
141dc5a79c1SDavid du Colombier superblock.s_mnt_count++;
142dc5a79c1SDavid du Colombier seek(xf->dev, OFFSET_SUPER_BLOCK, 0);
143dc5a79c1SDavid du Colombier if( !rdonly && sizeof(SuperBlock) !=
144dc5a79c1SDavid du Colombier write(xf->dev, &superblock, sizeof(SuperBlock)) ){
145dc5a79c1SDavid du Colombier chat("can't write super block...");
146dc5a79c1SDavid du Colombier errno = Eio;
147dc5a79c1SDavid du Colombier return -1;
148dc5a79c1SDavid du Colombier }
149dc5a79c1SDavid du Colombier
150dc5a79c1SDavid du Colombier return 0;
151dc5a79c1SDavid du Colombier }
152dc5a79c1SDavid du Colombier Ext2
getext2(Xfs * xf,char type,int n)153dc5a79c1SDavid du Colombier getext2(Xfs *xf, char type, int n)
154dc5a79c1SDavid du Colombier {
155dc5a79c1SDavid du Colombier Iobuf *bd;
156dc5a79c1SDavid du Colombier Ext2 e;
157dc5a79c1SDavid du Colombier
158dc5a79c1SDavid du Colombier switch(type){
159dc5a79c1SDavid du Colombier case EXT2_SUPER:
160dc5a79c1SDavid du Colombier e.buf = getbuf(xf, xf->superaddr);
161dc5a79c1SDavid du Colombier if( !e.buf ) goto error;
162dc5a79c1SDavid du Colombier e.u.sb = (SuperBlock *)(e.buf->iobuf + xf->superoff);
163dc5a79c1SDavid du Colombier e.type = EXT2_SUPER;
164dc5a79c1SDavid du Colombier break;
165dc5a79c1SDavid du Colombier case EXT2_DESC:
166dc5a79c1SDavid du Colombier e.buf = getbuf(xf, DESC_ADDR(xf, n));
167dc5a79c1SDavid du Colombier if( !e.buf ) goto error;
168dc5a79c1SDavid du Colombier e.u.gd = DESC_OFFSET(xf, e.buf->iobuf, n);
169dc5a79c1SDavid du Colombier e.type = EXT2_DESC;
170dc5a79c1SDavid du Colombier break;
171dc5a79c1SDavid du Colombier case EXT2_BBLOCK:
172dc5a79c1SDavid du Colombier bd = getbuf(xf, DESC_ADDR(xf, n));
173dc5a79c1SDavid du Colombier if( !bd ) goto error;
174dc5a79c1SDavid du Colombier e.buf = getbuf(xf, DESC_OFFSET(xf, bd->iobuf, n)->bg_block_bitmap);
175dc5a79c1SDavid du Colombier if( !e.buf ){
176dc5a79c1SDavid du Colombier putbuf(bd);
177dc5a79c1SDavid du Colombier goto error;
178dc5a79c1SDavid du Colombier }
179dc5a79c1SDavid du Colombier putbuf(bd);
180dc5a79c1SDavid du Colombier e.u.bmp = (char *)e.buf->iobuf;
181dc5a79c1SDavid du Colombier e.type = EXT2_BBLOCK;
182dc5a79c1SDavid du Colombier break;
183dc5a79c1SDavid du Colombier case EXT2_BINODE:
184dc5a79c1SDavid du Colombier bd = getbuf(xf, DESC_ADDR(xf, n));
185dc5a79c1SDavid du Colombier if( !bd ) goto error;
186dc5a79c1SDavid du Colombier e.buf = getbuf(xf, DESC_OFFSET(xf, bd->iobuf, n)->bg_inode_bitmap);
187dc5a79c1SDavid du Colombier if( !e.buf ){
188dc5a79c1SDavid du Colombier putbuf(bd);
189dc5a79c1SDavid du Colombier goto error;
190dc5a79c1SDavid du Colombier }
191dc5a79c1SDavid du Colombier putbuf(bd);
192dc5a79c1SDavid du Colombier e.u.bmp = (char *)e.buf->iobuf;
193dc5a79c1SDavid du Colombier e.type = EXT2_BINODE;
194dc5a79c1SDavid du Colombier break;
195dc5a79c1SDavid du Colombier default:
196dc5a79c1SDavid du Colombier goto error;
197dc5a79c1SDavid du Colombier }
198dc5a79c1SDavid du Colombier return e;
199dc5a79c1SDavid du Colombier error:
200dc5a79c1SDavid du Colombier panic("getext2");
201dc5a79c1SDavid du Colombier return e;
202dc5a79c1SDavid du Colombier }
203dc5a79c1SDavid du Colombier int
get_inode(Xfile * file,uint nr)204dc5a79c1SDavid du Colombier get_inode( Xfile *file, uint nr )
205dc5a79c1SDavid du Colombier {
206dc5a79c1SDavid du Colombier unsigned long block_group, block;
207dc5a79c1SDavid du Colombier Xfs *xf = file->xf;
208dc5a79c1SDavid du Colombier Ext2 ed, es;
209dc5a79c1SDavid du Colombier
210dc5a79c1SDavid du Colombier es = getext2(xf, EXT2_SUPER, 0);
211*c93608ccSDavid du Colombier if(nr > es.u.sb->s_inodes_count ){
212dc5a79c1SDavid du Colombier chat("inode number %d is too big...", nr);
213dc5a79c1SDavid du Colombier putext2(es);
214dc5a79c1SDavid du Colombier errno = Eio;
215dc5a79c1SDavid du Colombier return -1;
216dc5a79c1SDavid du Colombier }
217dc5a79c1SDavid du Colombier putext2(es);
218dc5a79c1SDavid du Colombier block_group = (nr - 1) / xf->inodes_per_group;
219dc5a79c1SDavid du Colombier if( block_group >= xf->ngroups ){
220dc5a79c1SDavid du Colombier chat("block group (%d) > groups count...", block_group);
221dc5a79c1SDavid du Colombier errno = Eio;
222dc5a79c1SDavid du Colombier return -1;
223dc5a79c1SDavid du Colombier }
224dc5a79c1SDavid du Colombier ed = getext2(xf, EXT2_DESC, block_group);
225dc5a79c1SDavid du Colombier block = ed.u.gd->bg_inode_table + (((nr-1) % xf->inodes_per_group) /
226dc5a79c1SDavid du Colombier xf->inodes_per_block);
227dc5a79c1SDavid du Colombier putext2(ed);
228dc5a79c1SDavid du Colombier
229dc5a79c1SDavid du Colombier file->bufoffset = (nr-1) % xf->inodes_per_block;
230dc5a79c1SDavid du Colombier file->inbr = nr;
231dc5a79c1SDavid du Colombier file->bufaddr= block;
232dc5a79c1SDavid du Colombier
233dc5a79c1SDavid du Colombier return 1;
234dc5a79c1SDavid du Colombier }
235dc5a79c1SDavid du Colombier int
get_file(Xfile * f,char * name)236dc5a79c1SDavid du Colombier get_file( Xfile *f, char *name)
237dc5a79c1SDavid du Colombier {
238dc5a79c1SDavid du Colombier uint offset, nr, i;
239dc5a79c1SDavid du Colombier Xfs *xf = f->xf;
240dc5a79c1SDavid du Colombier Inode *inode;
241dc5a79c1SDavid du Colombier int nblock;
242dc5a79c1SDavid du Colombier DirEntry *dir;
243dc5a79c1SDavid du Colombier Iobuf *buf, *ibuf;
244dc5a79c1SDavid du Colombier
245dc5a79c1SDavid du Colombier if( !S_ISDIR(getmode(f)) )
246dc5a79c1SDavid du Colombier return -1;
247dc5a79c1SDavid du Colombier ibuf = getbuf(xf, f->bufaddr);
248dc5a79c1SDavid du Colombier if( !ibuf )
249dc5a79c1SDavid du Colombier return -1;
250dc5a79c1SDavid du Colombier inode = ((Inode *)ibuf->iobuf) + f->bufoffset;
251dc5a79c1SDavid du Colombier nblock = (inode->i_blocks * 512) / xf->block_size;
252dc5a79c1SDavid du Colombier
253dc5a79c1SDavid du Colombier for(i=0 ; (i < nblock) && (i < EXT2_NDIR_BLOCKS) ; i++){
254dc5a79c1SDavid du Colombier buf = getbuf(xf, inode->i_block[i]);
255dc5a79c1SDavid du Colombier if( !buf ){
256dc5a79c1SDavid du Colombier putbuf(ibuf);
257dc5a79c1SDavid du Colombier return -1;
258dc5a79c1SDavid du Colombier }
259dc5a79c1SDavid du Colombier for(offset=0 ; offset < xf->block_size ; ){
260dc5a79c1SDavid du Colombier dir = (DirEntry *)(buf->iobuf + offset);
261dc5a79c1SDavid du Colombier if( dir->name_len==strlen(name) &&
262dc5a79c1SDavid du Colombier !strncmp(name, dir->name, dir->name_len) ){
263dc5a79c1SDavid du Colombier nr = dir->inode;
264dc5a79c1SDavid du Colombier putbuf(buf);
265dc5a79c1SDavid du Colombier putbuf(ibuf);
266dc5a79c1SDavid du Colombier return nr;
267dc5a79c1SDavid du Colombier }
268dc5a79c1SDavid du Colombier offset += dir->rec_len;
269dc5a79c1SDavid du Colombier }
270dc5a79c1SDavid du Colombier putbuf(buf);
271dc5a79c1SDavid du Colombier
272dc5a79c1SDavid du Colombier }
273dc5a79c1SDavid du Colombier putbuf(ibuf);
274dc5a79c1SDavid du Colombier errno = Enonexist;
275dc5a79c1SDavid du Colombier return -1;
276dc5a79c1SDavid du Colombier }
277dc5a79c1SDavid du Colombier char *
getname(Xfile * f,char * str)278dc5a79c1SDavid du Colombier getname(Xfile *f, char *str)
279dc5a79c1SDavid du Colombier {
280dc5a79c1SDavid du Colombier Xfile ft;
281dc5a79c1SDavid du Colombier int offset, i, len;
282dc5a79c1SDavid du Colombier Xfs *xf = f->xf;
283dc5a79c1SDavid du Colombier Inode *inode;
284dc5a79c1SDavid du Colombier int nblock;
285dc5a79c1SDavid du Colombier DirEntry *dir;
286dc5a79c1SDavid du Colombier Iobuf *buf, *ibuf;
287dc5a79c1SDavid du Colombier
288dc5a79c1SDavid du Colombier ft = *f;
289dc5a79c1SDavid du Colombier if( get_inode(&ft, f->pinbr) < 0 )
290dc5a79c1SDavid du Colombier return 0;
291dc5a79c1SDavid du Colombier if( !S_ISDIR(getmode(&ft)) )
292dc5a79c1SDavid du Colombier return 0;
293dc5a79c1SDavid du Colombier ibuf = getbuf(xf, ft.bufaddr);
294dc5a79c1SDavid du Colombier if( !ibuf )
295dc5a79c1SDavid du Colombier return 0;
296dc5a79c1SDavid du Colombier inode = ((Inode *)ibuf->iobuf) + ft.bufoffset;
297dc5a79c1SDavid du Colombier nblock = (inode->i_blocks * 512) / xf->block_size;
298dc5a79c1SDavid du Colombier
299dc5a79c1SDavid du Colombier for(i=0 ; (i < nblock) && (i < EXT2_NDIR_BLOCKS) ; i++){
300dc5a79c1SDavid du Colombier buf = getbuf(xf, inode->i_block[i]);
301dc5a79c1SDavid du Colombier if( !buf ){
302dc5a79c1SDavid du Colombier putbuf(ibuf);
303dc5a79c1SDavid du Colombier return 0;
304dc5a79c1SDavid du Colombier }
305dc5a79c1SDavid du Colombier for(offset=0 ; offset < xf->block_size ; ){
306dc5a79c1SDavid du Colombier dir = (DirEntry *)(buf->iobuf + offset);
307dc5a79c1SDavid du Colombier if( f->inbr == dir->inode ){
308dc5a79c1SDavid du Colombier len = (dir->name_len < EXT2_NAME_LEN) ? dir->name_len : EXT2_NAME_LEN;
309dc5a79c1SDavid du Colombier if (str == 0)
310dc5a79c1SDavid du Colombier str = malloc(len+1);
311dc5a79c1SDavid du Colombier strncpy(str, dir->name, len);
312dc5a79c1SDavid du Colombier str[len] = 0;
313dc5a79c1SDavid du Colombier putbuf(buf);
314dc5a79c1SDavid du Colombier putbuf(ibuf);
315dc5a79c1SDavid du Colombier return str;
316dc5a79c1SDavid du Colombier }
317dc5a79c1SDavid du Colombier offset += dir->rec_len;
318dc5a79c1SDavid du Colombier }
319dc5a79c1SDavid du Colombier putbuf(buf);
320dc5a79c1SDavid du Colombier }
321dc5a79c1SDavid du Colombier putbuf(ibuf);
322dc5a79c1SDavid du Colombier errno = Enonexist;
323dc5a79c1SDavid du Colombier return 0;
324dc5a79c1SDavid du Colombier }
325dc5a79c1SDavid du Colombier void
dostat(Qid qid,Xfile * f,Dir * dir)326dc5a79c1SDavid du Colombier dostat(Qid qid, Xfile *f, Dir *dir )
327dc5a79c1SDavid du Colombier {
328dc5a79c1SDavid du Colombier Inode *inode;
329dc5a79c1SDavid du Colombier Iobuf *ibuf;
330dc5a79c1SDavid du Colombier char *name;
331dc5a79c1SDavid du Colombier
332dc5a79c1SDavid du Colombier memset(dir, 0, sizeof(Dir));
333dc5a79c1SDavid du Colombier
334dc5a79c1SDavid du Colombier if( f->inbr == EXT2_ROOT_INODE ){
335dc5a79c1SDavid du Colombier dir->name = estrdup9p("/");
336dc5a79c1SDavid du Colombier dir->qid = (Qid){0,0,QTDIR};
337dc5a79c1SDavid du Colombier dir->mode = DMDIR | 0777;
338dc5a79c1SDavid du Colombier }else{
339dc5a79c1SDavid du Colombier ibuf = getbuf(f->xf, f->bufaddr);
340dc5a79c1SDavid du Colombier if( !ibuf )
341dc5a79c1SDavid du Colombier return;
342dc5a79c1SDavid du Colombier inode = ((Inode *)ibuf->iobuf) + f->bufoffset;
343dc5a79c1SDavid du Colombier dir->length = inode->i_size;
344dc5a79c1SDavid du Colombier dir->atime = inode->i_atime;
345dc5a79c1SDavid du Colombier dir->mtime = inode->i_mtime;
346dc5a79c1SDavid du Colombier putbuf(ibuf);
347dc5a79c1SDavid du Colombier name = getname(f, 0);
348dc5a79c1SDavid du Colombier dir->name = name;
349dc5a79c1SDavid du Colombier dir->uid = estrdup9p(mapuid(inode->i_uid));
350dc5a79c1SDavid du Colombier dir->gid = estrdup9p(mapgid(inode->i_gid));
351dc5a79c1SDavid du Colombier dir->qid = qid;
352dc5a79c1SDavid du Colombier dir->mode = getmode(f);
353dc5a79c1SDavid du Colombier if( qid.type & QTDIR )
354dc5a79c1SDavid du Colombier dir->mode |= DMDIR;
355dc5a79c1SDavid du Colombier }
356dc5a79c1SDavid du Colombier
357dc5a79c1SDavid du Colombier }
358dc5a79c1SDavid du Colombier int
dowstat(Xfile * f,Dir * stat)359dc5a79c1SDavid du Colombier dowstat(Xfile *f, Dir *stat)
360dc5a79c1SDavid du Colombier {
361dc5a79c1SDavid du Colombier Xfs *xf = f->xf;
362dc5a79c1SDavid du Colombier Inode *inode;
363dc5a79c1SDavid du Colombier Xfile fdir;
364dc5a79c1SDavid du Colombier Iobuf *ibuf;
365dc5a79c1SDavid du Colombier char name[EXT2_NAME_LEN+1];
366dc5a79c1SDavid du Colombier
367dc5a79c1SDavid du Colombier /* change name */
368dc5a79c1SDavid du Colombier getname(f, name);
369dc5a79c1SDavid du Colombier if( stat->name && stat->name[0] != 0 && strcmp(name, stat->name) ){
370dc5a79c1SDavid du Colombier
371dc5a79c1SDavid du Colombier /* get dir */
372dc5a79c1SDavid du Colombier fdir = *f;
373dc5a79c1SDavid du Colombier if( get_inode(&fdir, f->pinbr) < 0 ){
374dc5a79c1SDavid du Colombier chat("can't get inode %d...", f->pinbr);
375dc5a79c1SDavid du Colombier return -1;
376dc5a79c1SDavid du Colombier }
377dc5a79c1SDavid du Colombier
378dc5a79c1SDavid du Colombier ibuf = getbuf(xf, fdir.bufaddr);
379dc5a79c1SDavid du Colombier if( !ibuf )
380dc5a79c1SDavid du Colombier return -1;
381dc5a79c1SDavid du Colombier inode = ((Inode *)ibuf->iobuf) +fdir.bufoffset;
382dc5a79c1SDavid du Colombier
383dc5a79c1SDavid du Colombier /* Clean old dir entry */
384dc5a79c1SDavid du Colombier if( delete_entry(xf, inode, f->inbr) < 0 ){
385dc5a79c1SDavid du Colombier chat("delete entry failed...");
386dc5a79c1SDavid du Colombier putbuf(ibuf);
387dc5a79c1SDavid du Colombier return -1;
388dc5a79c1SDavid du Colombier }
389dc5a79c1SDavid du Colombier putbuf(ibuf);
390dc5a79c1SDavid du Colombier
391dc5a79c1SDavid du Colombier /* add the new entry */
392dc5a79c1SDavid du Colombier if( add_entry(&fdir, stat->name, f->inbr) < 0 ){
393dc5a79c1SDavid du Colombier chat("add entry failed...");
394dc5a79c1SDavid du Colombier return -1;
395dc5a79c1SDavid du Colombier }
396dc5a79c1SDavid du Colombier
397dc5a79c1SDavid du Colombier }
398dc5a79c1SDavid du Colombier
399dc5a79c1SDavid du Colombier ibuf = getbuf(xf, f->bufaddr);
400dc5a79c1SDavid du Colombier if( !ibuf )
401dc5a79c1SDavid du Colombier return -1;
402dc5a79c1SDavid du Colombier inode = ((Inode *)ibuf->iobuf) + f->bufoffset;
403dc5a79c1SDavid du Colombier
404dc5a79c1SDavid du Colombier if (stat->mode != ~0)
405dc5a79c1SDavid du Colombier if( (getmode(f) & 0777) != (stat->mode & 0777) ){
406dc5a79c1SDavid du Colombier inode->i_mode = (getmode(f) & ~0777) | (stat->mode & 0777);
407dc5a79c1SDavid du Colombier dirtybuf(ibuf);
408dc5a79c1SDavid du Colombier }
409dc5a79c1SDavid du Colombier if (stat->mtime != ~0)
410dc5a79c1SDavid du Colombier if( inode->i_mtime != stat->mtime ){
411dc5a79c1SDavid du Colombier inode->i_mtime = stat->mtime;
412dc5a79c1SDavid du Colombier dirtybuf(ibuf);
413dc5a79c1SDavid du Colombier }
414dc5a79c1SDavid du Colombier
415dc5a79c1SDavid du Colombier putbuf(ibuf);
416dc5a79c1SDavid du Colombier
417dc5a79c1SDavid du Colombier return 1;
418dc5a79c1SDavid du Colombier }
419dc5a79c1SDavid du Colombier long
readfile(Xfile * f,void * vbuf,vlong offset,long count)420dc5a79c1SDavid du Colombier readfile(Xfile *f, void *vbuf, vlong offset, long count)
421dc5a79c1SDavid du Colombier {
422dc5a79c1SDavid du Colombier Xfs *xf = f->xf;
423dc5a79c1SDavid du Colombier Inode *inode;
424dc5a79c1SDavid du Colombier Iobuf *buffer, *ibuf;
425dc5a79c1SDavid du Colombier long rcount;
426dc5a79c1SDavid du Colombier int len, o, cur_block, baddr;
427dc5a79c1SDavid du Colombier uchar *buf;
428dc5a79c1SDavid du Colombier
429dc5a79c1SDavid du Colombier buf = vbuf;
430dc5a79c1SDavid du Colombier
431dc5a79c1SDavid du Colombier ibuf = getbuf(xf, f->bufaddr);
432dc5a79c1SDavid du Colombier if( !ibuf )
433dc5a79c1SDavid du Colombier return -1;
434dc5a79c1SDavid du Colombier inode = ((Inode *)ibuf->iobuf) + f->bufoffset;
435dc5a79c1SDavid du Colombier
436dc5a79c1SDavid du Colombier if( offset >= inode->i_size ){
437dc5a79c1SDavid du Colombier putbuf(ibuf);
438dc5a79c1SDavid du Colombier return 0;
439dc5a79c1SDavid du Colombier }
440dc5a79c1SDavid du Colombier if( offset + count > inode->i_size )
441dc5a79c1SDavid du Colombier count = inode->i_size - offset;
442dc5a79c1SDavid du Colombier
443dc5a79c1SDavid du Colombier /* fast link */
444dc5a79c1SDavid du Colombier if( S_ISLNK(getmode(f)) && (inode->i_size <= EXT2_N_BLOCKS<<2) ){
445dc5a79c1SDavid du Colombier memcpy(&buf[0], ((char *)inode->i_block)+offset, count);
446dc5a79c1SDavid du Colombier putbuf(ibuf);
447dc5a79c1SDavid du Colombier return count;
448dc5a79c1SDavid du Colombier }
449dc5a79c1SDavid du Colombier chat("read block [ ");
450dc5a79c1SDavid du Colombier cur_block = offset / xf->block_size;
451dc5a79c1SDavid du Colombier o = offset % xf->block_size;
452dc5a79c1SDavid du Colombier rcount = 0;
453dc5a79c1SDavid du Colombier while( count > 0 ){
454dc5a79c1SDavid du Colombier baddr = bmap(f, cur_block++);
455dc5a79c1SDavid du Colombier if( !baddr ){
456dc5a79c1SDavid du Colombier putbuf(ibuf);
457dc5a79c1SDavid du Colombier return -1;
458dc5a79c1SDavid du Colombier }
459dc5a79c1SDavid du Colombier buffer = getbuf(xf, baddr);
460dc5a79c1SDavid du Colombier if( !buffer ){
461dc5a79c1SDavid du Colombier putbuf(ibuf);
462dc5a79c1SDavid du Colombier return -1;
463dc5a79c1SDavid du Colombier }
464dc5a79c1SDavid du Colombier chat("%d ", baddr);
465dc5a79c1SDavid du Colombier len = xf->block_size - o;
466dc5a79c1SDavid du Colombier if( len > count )
467dc5a79c1SDavid du Colombier len = count;
468dc5a79c1SDavid du Colombier memcpy(&buf[rcount], &buffer->iobuf[o], len);
469dc5a79c1SDavid du Colombier rcount += len;
470dc5a79c1SDavid du Colombier count -= len;
471dc5a79c1SDavid du Colombier o = 0;
472dc5a79c1SDavid du Colombier putbuf(buffer);
473dc5a79c1SDavid du Colombier }
474dc5a79c1SDavid du Colombier chat("] ...");
475dc5a79c1SDavid du Colombier inode->i_atime = time(0);
476dc5a79c1SDavid du Colombier dirtybuf(ibuf);
477dc5a79c1SDavid du Colombier putbuf(ibuf);
478dc5a79c1SDavid du Colombier return rcount;
479dc5a79c1SDavid du Colombier }
480dc5a79c1SDavid du Colombier long
readdir(Xfile * f,void * vbuf,vlong offset,long count)481dc5a79c1SDavid du Colombier readdir(Xfile *f, void *vbuf, vlong offset, long count)
482dc5a79c1SDavid du Colombier {
483dc5a79c1SDavid du Colombier int off, i, len;
484dc5a79c1SDavid du Colombier long rcount;
485dc5a79c1SDavid du Colombier Xfs *xf = f->xf;
486dc5a79c1SDavid du Colombier Inode *inode, *tinode;
487dc5a79c1SDavid du Colombier int nblock;
488dc5a79c1SDavid du Colombier DirEntry *edir;
489dc5a79c1SDavid du Colombier Iobuf *buffer, *ibuf, *tbuf;
490dc5a79c1SDavid du Colombier Dir pdir;
491dc5a79c1SDavid du Colombier Xfile ft;
492dc5a79c1SDavid du Colombier uchar *buf;
493dc5a79c1SDavid du Colombier char name[EXT2_NAME_LEN+1];
494dc5a79c1SDavid du Colombier unsigned int dirlen;
495dc5a79c1SDavid du Colombier int index;
496dc5a79c1SDavid du Colombier
497dc5a79c1SDavid du Colombier buf = vbuf;
498dc5a79c1SDavid du Colombier if (offset == 0)
499dc5a79c1SDavid du Colombier f->dirindex = 0;
500dc5a79c1SDavid du Colombier
501dc5a79c1SDavid du Colombier if( !S_ISDIR(getmode(f)) )
502dc5a79c1SDavid du Colombier return -1;
503dc5a79c1SDavid du Colombier
504dc5a79c1SDavid du Colombier ibuf = getbuf(xf, f->bufaddr);
505dc5a79c1SDavid du Colombier if( !ibuf )
506dc5a79c1SDavid du Colombier return -1;
507dc5a79c1SDavid du Colombier inode = ((Inode *)ibuf->iobuf) + f->bufoffset;
508dc5a79c1SDavid du Colombier nblock = (inode->i_blocks * 512) / xf->block_size;
509dc5a79c1SDavid du Colombier ft = *f;
510dc5a79c1SDavid du Colombier chat("read block [ ");
511dc5a79c1SDavid du Colombier index = 0;
512dc5a79c1SDavid du Colombier for(i=0, rcount=0 ; (i < nblock) && (i < EXT2_NDIR_BLOCKS) ; i++){
513dc5a79c1SDavid du Colombier
514dc5a79c1SDavid du Colombier buffer = getbuf(xf, inode->i_block[i]);
515dc5a79c1SDavid du Colombier if( !buffer ){
516dc5a79c1SDavid du Colombier putbuf(ibuf);
517dc5a79c1SDavid du Colombier return -1;
518dc5a79c1SDavid du Colombier }
519dc5a79c1SDavid du Colombier chat("%d, ", buffer->addr);
520dc5a79c1SDavid du Colombier for(off=0 ; off < xf->block_size ; ){
521dc5a79c1SDavid du Colombier
522dc5a79c1SDavid du Colombier edir = (DirEntry *)(buffer->iobuf + off);
523dc5a79c1SDavid du Colombier off += edir->rec_len;
524dc5a79c1SDavid du Colombier if( (edir->name[0] == '.' ) && (edir->name_len == 1))
525dc5a79c1SDavid du Colombier continue;
526dc5a79c1SDavid du Colombier if(edir->name[0] == '.' && edir->name[1] == '.' &&
527dc5a79c1SDavid du Colombier edir->name_len == 2)
528dc5a79c1SDavid du Colombier continue;
529dc5a79c1SDavid du Colombier if( edir->inode == 0 ) /* for lost+found dir ... */
530dc5a79c1SDavid du Colombier continue;
531dc5a79c1SDavid du Colombier if( index++ < f->dirindex )
532dc5a79c1SDavid du Colombier continue;
533dc5a79c1SDavid du Colombier
534dc5a79c1SDavid du Colombier if( get_inode(&ft, edir->inode) < 0 ){
535dc5a79c1SDavid du Colombier chat("can't find ino no %d ] ...", edir->inode);
536dc5a79c1SDavid du Colombier error: putbuf(buffer);
537dc5a79c1SDavid du Colombier putbuf(ibuf);
538dc5a79c1SDavid du Colombier return -1;
539dc5a79c1SDavid du Colombier }
540dc5a79c1SDavid du Colombier tbuf = getbuf(xf, ft.bufaddr);
541dc5a79c1SDavid du Colombier if( !tbuf )
542dc5a79c1SDavid du Colombier goto error;
543dc5a79c1SDavid du Colombier tinode = ((Inode *)tbuf->iobuf) + ft.bufoffset;
544dc5a79c1SDavid du Colombier
545dc5a79c1SDavid du Colombier memset(&pdir, 0, sizeof(Dir));
546dc5a79c1SDavid du Colombier
547dc5a79c1SDavid du Colombier /* fill plan9 dir struct */
548dc5a79c1SDavid du Colombier pdir.name = name;
549dc5a79c1SDavid du Colombier len = (edir->name_len < EXT2_NAME_LEN) ? edir->name_len : EXT2_NAME_LEN;
550dc5a79c1SDavid du Colombier strncpy(pdir.name, edir->name, len);
551dc5a79c1SDavid du Colombier pdir.name[len] = 0;
552dc5a79c1SDavid du Colombier // chat("name %s len %d\n", pdir.name, edir->name_len);
553dc5a79c1SDavid du Colombier pdir.uid = mapuid(tinode->i_uid);
554dc5a79c1SDavid du Colombier pdir.gid = mapgid(tinode->i_gid);
555dc5a79c1SDavid du Colombier pdir.qid.path = edir->inode;
556dc5a79c1SDavid du Colombier pdir.mode = tinode->i_mode;
557dc5a79c1SDavid du Colombier if( edir->inode == EXT2_ROOT_INODE )
558dc5a79c1SDavid du Colombier pdir.qid.path = f->xf->rootqid.path;
559dc5a79c1SDavid du Colombier else if( S_ISDIR( tinode->i_mode) )
560dc5a79c1SDavid du Colombier pdir.qid.type |= QTDIR;
561dc5a79c1SDavid du Colombier if( pdir.qid.type & QTDIR )
562dc5a79c1SDavid du Colombier pdir.mode |= DMDIR;
563dc5a79c1SDavid du Colombier pdir.length = tinode->i_size;
564dc5a79c1SDavid du Colombier pdir.atime = tinode->i_atime;
565dc5a79c1SDavid du Colombier pdir.mtime = tinode->i_mtime;
566dc5a79c1SDavid du Colombier
567dc5a79c1SDavid du Colombier putbuf(tbuf);
568dc5a79c1SDavid du Colombier
569dc5a79c1SDavid du Colombier dirlen = convD2M(&pdir, &buf[rcount], count-rcount);
570dc5a79c1SDavid du Colombier if ( dirlen <= BIT16SZ ) {
571dc5a79c1SDavid du Colombier chat("] ...");
572dc5a79c1SDavid du Colombier putbuf(buffer);
573dc5a79c1SDavid du Colombier putbuf(ibuf);
574dc5a79c1SDavid du Colombier return rcount;
575dc5a79c1SDavid du Colombier }
576dc5a79c1SDavid du Colombier rcount += dirlen;
577dc5a79c1SDavid du Colombier f->dirindex++;
578dc5a79c1SDavid du Colombier
579dc5a79c1SDavid du Colombier }
580dc5a79c1SDavid du Colombier putbuf(buffer);
581dc5a79c1SDavid du Colombier }
582dc5a79c1SDavid du Colombier chat("] ...");
583dc5a79c1SDavid du Colombier putbuf(ibuf);
584dc5a79c1SDavid du Colombier return rcount;
585dc5a79c1SDavid du Colombier }
586dc5a79c1SDavid du Colombier int
bmap(Xfile * f,int block)587dc5a79c1SDavid du Colombier bmap( Xfile *f, int block )
588dc5a79c1SDavid du Colombier {
589dc5a79c1SDavid du Colombier Xfs *xf = f->xf;
590dc5a79c1SDavid du Colombier Inode *inode;
591dc5a79c1SDavid du Colombier Iobuf *buf, *ibuf;
592dc5a79c1SDavid du Colombier int addr;
593dc5a79c1SDavid du Colombier int addr_per_block = xf->addr_per_block;
594dc5a79c1SDavid du Colombier int addr_per_block_bits = ffz(~addr_per_block);
595dc5a79c1SDavid du Colombier
596dc5a79c1SDavid du Colombier if(block < 0) {
597dc5a79c1SDavid du Colombier chat("bmap() block < 0 ...");
598dc5a79c1SDavid du Colombier return 0;
599dc5a79c1SDavid du Colombier }
600dc5a79c1SDavid du Colombier if(block >= EXT2_NDIR_BLOCKS + addr_per_block +
601dc5a79c1SDavid du Colombier (1 << (addr_per_block_bits * 2)) +
602dc5a79c1SDavid du Colombier ((1 << (addr_per_block_bits * 2)) << addr_per_block_bits)) {
603dc5a79c1SDavid du Colombier chat("bmap() block > big...");
604dc5a79c1SDavid du Colombier return 0;
605dc5a79c1SDavid du Colombier }
606dc5a79c1SDavid du Colombier
607dc5a79c1SDavid du Colombier ibuf = getbuf(xf, f->bufaddr);
608dc5a79c1SDavid du Colombier if( !ibuf )
609dc5a79c1SDavid du Colombier return 0;
610dc5a79c1SDavid du Colombier inode = ((Inode *)ibuf->iobuf) + f->bufoffset;
611dc5a79c1SDavid du Colombier
612dc5a79c1SDavid du Colombier /* direct blocks */
613dc5a79c1SDavid du Colombier if(block < EXT2_NDIR_BLOCKS){
614dc5a79c1SDavid du Colombier putbuf(ibuf);
615dc5a79c1SDavid du Colombier return inode->i_block[block];
616dc5a79c1SDavid du Colombier }
617dc5a79c1SDavid du Colombier block -= EXT2_NDIR_BLOCKS;
618dc5a79c1SDavid du Colombier
619dc5a79c1SDavid du Colombier /* indirect blocks*/
620dc5a79c1SDavid du Colombier if(block < addr_per_block) {
621dc5a79c1SDavid du Colombier addr = inode->i_block[EXT2_IND_BLOCK];
622dc5a79c1SDavid du Colombier if (!addr) goto error;
623dc5a79c1SDavid du Colombier buf = getbuf(xf, addr);
624dc5a79c1SDavid du Colombier if( !buf ) goto error;
625dc5a79c1SDavid du Colombier addr = *(((uint *)buf->iobuf) + block);
626dc5a79c1SDavid du Colombier putbuf(buf);
627dc5a79c1SDavid du Colombier putbuf(ibuf);
628dc5a79c1SDavid du Colombier return addr;
629dc5a79c1SDavid du Colombier }
630dc5a79c1SDavid du Colombier block -= addr_per_block;
631dc5a79c1SDavid du Colombier
632dc5a79c1SDavid du Colombier /* double indirect blocks */
633dc5a79c1SDavid du Colombier if(block < (1 << (addr_per_block_bits * 2))) {
634dc5a79c1SDavid du Colombier addr = inode->i_block[EXT2_DIND_BLOCK];
635dc5a79c1SDavid du Colombier if (!addr) goto error;
636dc5a79c1SDavid du Colombier buf = getbuf(xf, addr);
637dc5a79c1SDavid du Colombier if( !buf ) goto error;
638dc5a79c1SDavid du Colombier addr = *(((uint *)buf->iobuf) + (block >> addr_per_block_bits));
639dc5a79c1SDavid du Colombier putbuf(buf);
640dc5a79c1SDavid du Colombier buf = getbuf(xf, addr);
641dc5a79c1SDavid du Colombier if( !buf ) goto error;
642dc5a79c1SDavid du Colombier addr = *(((uint *)buf->iobuf) + (block & (addr_per_block - 1)));
643dc5a79c1SDavid du Colombier putbuf(buf);
644dc5a79c1SDavid du Colombier putbuf(ibuf);
645dc5a79c1SDavid du Colombier return addr;
646dc5a79c1SDavid du Colombier }
647dc5a79c1SDavid du Colombier block -= (1 << (addr_per_block_bits * 2));
648dc5a79c1SDavid du Colombier
649dc5a79c1SDavid du Colombier /* triple indirect blocks */
650dc5a79c1SDavid du Colombier addr = inode->i_block[EXT2_TIND_BLOCK];
651dc5a79c1SDavid du Colombier if(!addr) goto error;
652dc5a79c1SDavid du Colombier buf = getbuf(xf, addr);
653dc5a79c1SDavid du Colombier if( !buf ) goto error;
654dc5a79c1SDavid du Colombier addr = *(((uint *)buf->iobuf) + (block >> (addr_per_block_bits * 2)));
655dc5a79c1SDavid du Colombier putbuf(buf);
656dc5a79c1SDavid du Colombier if(!addr) goto error;
657dc5a79c1SDavid du Colombier buf = getbuf(xf, addr);
658dc5a79c1SDavid du Colombier if( !buf ) goto error;
659dc5a79c1SDavid du Colombier addr = *(((uint *)buf->iobuf) +
660dc5a79c1SDavid du Colombier ((block >> addr_per_block_bits) & (addr_per_block - 1)));
661dc5a79c1SDavid du Colombier putbuf(buf);
662dc5a79c1SDavid du Colombier if(!addr) goto error;
663dc5a79c1SDavid du Colombier buf = getbuf(xf, addr);
664dc5a79c1SDavid du Colombier if( !buf ) goto error;
665dc5a79c1SDavid du Colombier addr = *(((uint *)buf->iobuf) + (block & (addr_per_block - 1)));
666dc5a79c1SDavid du Colombier putbuf(buf);
667dc5a79c1SDavid du Colombier putbuf(ibuf);
668dc5a79c1SDavid du Colombier return addr;
669dc5a79c1SDavid du Colombier error:
670dc5a79c1SDavid du Colombier putbuf(ibuf);
671dc5a79c1SDavid du Colombier return 0;
672dc5a79c1SDavid du Colombier }
673dc5a79c1SDavid du Colombier long
writefile(Xfile * f,void * vbuf,vlong offset,long count)674dc5a79c1SDavid du Colombier writefile(Xfile *f, void *vbuf, vlong offset, long count)
675dc5a79c1SDavid du Colombier {
676dc5a79c1SDavid du Colombier Xfs *xf = f->xf;
677dc5a79c1SDavid du Colombier Inode *inode;
678dc5a79c1SDavid du Colombier Iobuf *buffer, *ibuf;
679dc5a79c1SDavid du Colombier long w;
680dc5a79c1SDavid du Colombier int len, o, cur_block, baddr;
681dc5a79c1SDavid du Colombier char *buf;
682dc5a79c1SDavid du Colombier
683dc5a79c1SDavid du Colombier buf = vbuf;
684dc5a79c1SDavid du Colombier
685dc5a79c1SDavid du Colombier ibuf = getbuf(xf, f->bufaddr);
686dc5a79c1SDavid du Colombier if( !ibuf )
687dc5a79c1SDavid du Colombier return -1;
688dc5a79c1SDavid du Colombier inode = ((Inode *)ibuf->iobuf) + f->bufoffset;
689dc5a79c1SDavid du Colombier
690dc5a79c1SDavid du Colombier chat("write block [ ");
691dc5a79c1SDavid du Colombier cur_block = offset / xf->block_size;
692dc5a79c1SDavid du Colombier o = offset % xf->block_size;
693dc5a79c1SDavid du Colombier w = 0;
694dc5a79c1SDavid du Colombier while( count > 0 ){
695dc5a79c1SDavid du Colombier baddr = getblk(f, cur_block++);
696dc5a79c1SDavid du Colombier if( baddr <= 0 )
697dc5a79c1SDavid du Colombier goto end;
698dc5a79c1SDavid du Colombier buffer = getbuf(xf, baddr);
699dc5a79c1SDavid du Colombier if( !buffer )
700dc5a79c1SDavid du Colombier goto end;
701dc5a79c1SDavid du Colombier chat("%d ", baddr);
702dc5a79c1SDavid du Colombier len = xf->block_size - o;
703dc5a79c1SDavid du Colombier if( len > count )
704dc5a79c1SDavid du Colombier len = count;
705dc5a79c1SDavid du Colombier memcpy(&buffer->iobuf[o], &buf[w], len);
706dc5a79c1SDavid du Colombier dirtybuf(buffer);
707dc5a79c1SDavid du Colombier w += len;
708dc5a79c1SDavid du Colombier count -= len;
709dc5a79c1SDavid du Colombier o = 0;
710dc5a79c1SDavid du Colombier putbuf(buffer);
711dc5a79c1SDavid du Colombier }
712dc5a79c1SDavid du Colombier end:
713dc5a79c1SDavid du Colombier if( inode->i_size < offset + w )
714dc5a79c1SDavid du Colombier inode->i_size = offset + w;
715dc5a79c1SDavid du Colombier inode->i_atime = inode->i_mtime = time(0);
716dc5a79c1SDavid du Colombier dirtybuf(ibuf);
717dc5a79c1SDavid du Colombier putbuf(ibuf);
718dc5a79c1SDavid du Colombier chat("]...");
719dc5a79c1SDavid du Colombier if( errno )
720dc5a79c1SDavid du Colombier return -1;
721dc5a79c1SDavid du Colombier return w;
722dc5a79c1SDavid du Colombier }
723dc5a79c1SDavid du Colombier int
new_block(Xfile * f,int goal)724dc5a79c1SDavid du Colombier new_block( Xfile *f, int goal )
725dc5a79c1SDavid du Colombier {
726dc5a79c1SDavid du Colombier Xfs *xf= f->xf;
727dc5a79c1SDavid du Colombier int group, block, baddr, k, redo;
728dc5a79c1SDavid du Colombier ulong lmap;
729dc5a79c1SDavid du Colombier char *p, *r;
730dc5a79c1SDavid du Colombier Iobuf *buf;
731dc5a79c1SDavid du Colombier Ext2 ed, es, eb;
732dc5a79c1SDavid du Colombier
733dc5a79c1SDavid du Colombier es = getext2(xf, EXT2_SUPER, 0);
734dc5a79c1SDavid du Colombier redo = 0;
735dc5a79c1SDavid du Colombier
736dc5a79c1SDavid du Colombier repeat:
737dc5a79c1SDavid du Colombier
738dc5a79c1SDavid du Colombier if( goal < es.u.sb->s_first_data_block || goal >= es.u.sb->s_blocks_count )
739dc5a79c1SDavid du Colombier goal = es.u.sb->s_first_data_block;
740dc5a79c1SDavid du Colombier group = (goal - es.u.sb->s_first_data_block) / xf->blocks_per_group;
741dc5a79c1SDavid du Colombier
742dc5a79c1SDavid du Colombier ed = getext2(xf, EXT2_DESC, group);
743dc5a79c1SDavid du Colombier eb = getext2(xf, EXT2_BBLOCK, group);
744dc5a79c1SDavid du Colombier
745dc5a79c1SDavid du Colombier /*
746dc5a79c1SDavid du Colombier * First, test if goal block is free
747dc5a79c1SDavid du Colombier */
748dc5a79c1SDavid du Colombier if( ed.u.gd->bg_free_blocks_count > 0 ){
749dc5a79c1SDavid du Colombier block = (goal - es.u.sb->s_first_data_block) % xf->blocks_per_group;
750dc5a79c1SDavid du Colombier
751dc5a79c1SDavid du Colombier if( !test_bit(block, eb.u.bmp) )
752dc5a79c1SDavid du Colombier goto got_block;
753dc5a79c1SDavid du Colombier
754dc5a79c1SDavid du Colombier if( block ){
755dc5a79c1SDavid du Colombier /*
756dc5a79c1SDavid du Colombier * goal wasn't free ; search foward for a free
757dc5a79c1SDavid du Colombier * block within the next 32 blocks
758dc5a79c1SDavid du Colombier */
759dc5a79c1SDavid du Colombier
760dc5a79c1SDavid du Colombier lmap = (((ulong *)eb.u.bmp)[block>>5]) >>
761dc5a79c1SDavid du Colombier ((block & 31) + 1);
762dc5a79c1SDavid du Colombier if( block < xf->blocks_per_group - 32 )
763dc5a79c1SDavid du Colombier lmap |= (((ulong *)eb.u.bmp)[(block>>5)+1]) <<
764dc5a79c1SDavid du Colombier ( 31-(block & 31) );
765dc5a79c1SDavid du Colombier else
766dc5a79c1SDavid du Colombier lmap |= 0xffffffff << ( 31-(block & 31) );
767dc5a79c1SDavid du Colombier
768dc5a79c1SDavid du Colombier if( lmap != 0xffffffffl ){
769dc5a79c1SDavid du Colombier k = ffz(lmap) + 1;
770dc5a79c1SDavid du Colombier if( (block + k) < xf->blocks_per_group ){
771dc5a79c1SDavid du Colombier block += k;
772dc5a79c1SDavid du Colombier goto got_block;
773dc5a79c1SDavid du Colombier }
774dc5a79c1SDavid du Colombier }
775dc5a79c1SDavid du Colombier }
776dc5a79c1SDavid du Colombier /*
777dc5a79c1SDavid du Colombier * Search in the remaider of the group
778dc5a79c1SDavid du Colombier */
779dc5a79c1SDavid du Colombier p = eb.u.bmp + (block>>3);
780dc5a79c1SDavid du Colombier r = memscan(p, 0, (xf->blocks_per_group - block + 7) >>3);
781dc5a79c1SDavid du Colombier k = ( r - eb.u.bmp )<<3;
782dc5a79c1SDavid du Colombier if( k < xf->blocks_per_group ){
783dc5a79c1SDavid du Colombier block = k;
784dc5a79c1SDavid du Colombier goto search_back;
785dc5a79c1SDavid du Colombier }
786dc5a79c1SDavid du Colombier k = find_next_zero_bit((unsigned long *)eb.u.bmp,
787dc5a79c1SDavid du Colombier xf->blocks_per_group>>3, block);
788dc5a79c1SDavid du Colombier if( k < xf->blocks_per_group ){
789dc5a79c1SDavid du Colombier block = k;
790dc5a79c1SDavid du Colombier goto got_block;
791dc5a79c1SDavid du Colombier }
792dc5a79c1SDavid du Colombier }
793dc5a79c1SDavid du Colombier
794dc5a79c1SDavid du Colombier /*
795dc5a79c1SDavid du Colombier * Search the rest of groups
796dc5a79c1SDavid du Colombier */
797dc5a79c1SDavid du Colombier putext2(ed); putext2(eb);
798dc5a79c1SDavid du Colombier for(k=0 ; k < xf->ngroups ; k++){
799dc5a79c1SDavid du Colombier group++;
800dc5a79c1SDavid du Colombier if( group >= xf->ngroups )
801dc5a79c1SDavid du Colombier group = 0;
802dc5a79c1SDavid du Colombier ed = getext2(xf, EXT2_DESC, group);
803dc5a79c1SDavid du Colombier if( ed.u.gd->bg_free_blocks_count > 0 )
804dc5a79c1SDavid du Colombier break;
805dc5a79c1SDavid du Colombier putext2(ed);
806dc5a79c1SDavid du Colombier }
807dc5a79c1SDavid du Colombier if( redo && group == xf->ngroups-1 ){
808dc5a79c1SDavid du Colombier putext2(ed);
809dc5a79c1SDavid du Colombier goto full;
810dc5a79c1SDavid du Colombier }
811dc5a79c1SDavid du Colombier if( k >=xf->ngroups ){
812dc5a79c1SDavid du Colombier /*
813dc5a79c1SDavid du Colombier * All groups are full or
814dc5a79c1SDavid du Colombier * we have retry (because the last block) and all other
815dc5a79c1SDavid du Colombier * groups are also full.
816dc5a79c1SDavid du Colombier */
817dc5a79c1SDavid du Colombier full:
818dc5a79c1SDavid du Colombier chat("no free blocks ...");
819dc5a79c1SDavid du Colombier putext2(es);
820dc5a79c1SDavid du Colombier errno = Enospace;
821dc5a79c1SDavid du Colombier return 0;
822dc5a79c1SDavid du Colombier }
823dc5a79c1SDavid du Colombier eb = getext2(xf, EXT2_BBLOCK, group);
824dc5a79c1SDavid du Colombier r = memscan(eb.u.bmp, 0, xf->blocks_per_group>>3);
825dc5a79c1SDavid du Colombier block = (r - eb.u.bmp) <<3;
826dc5a79c1SDavid du Colombier if( block < xf->blocks_per_group )
827dc5a79c1SDavid du Colombier goto search_back;
828dc5a79c1SDavid du Colombier else
829dc5a79c1SDavid du Colombier block = find_first_zero_bit((ulong *)eb.u.bmp,
830dc5a79c1SDavid du Colombier xf->blocks_per_group>>3);
831dc5a79c1SDavid du Colombier if( block >= xf->blocks_per_group ){
832dc5a79c1SDavid du Colombier chat("Free block count courupted for block group %d...", group);
833dc5a79c1SDavid du Colombier putext2(ed); putext2(eb); putext2(es);
834dc5a79c1SDavid du Colombier errno = Ecorrupt;
835dc5a79c1SDavid du Colombier return 0;
836dc5a79c1SDavid du Colombier }
837dc5a79c1SDavid du Colombier
838dc5a79c1SDavid du Colombier
839dc5a79c1SDavid du Colombier search_back:
840dc5a79c1SDavid du Colombier /*
841dc5a79c1SDavid du Colombier * A free byte was found in the block. Now search backwards up
842dc5a79c1SDavid du Colombier * to 7 bits to find the start of this group of free block.
843dc5a79c1SDavid du Colombier */
844dc5a79c1SDavid du Colombier for(k=0 ; k < 7 && block > 0 &&
845dc5a79c1SDavid du Colombier !test_bit(block-1, eb.u.bmp) ; k++, block--);
846dc5a79c1SDavid du Colombier
847dc5a79c1SDavid du Colombier got_block:
848dc5a79c1SDavid du Colombier
849dc5a79c1SDavid du Colombier baddr = block + (group * xf->blocks_per_group) +
850dc5a79c1SDavid du Colombier es.u.sb->s_first_data_block;
851dc5a79c1SDavid du Colombier
852dc5a79c1SDavid du Colombier if( baddr == ed.u.gd->bg_block_bitmap ||
853dc5a79c1SDavid du Colombier baddr == ed.u.gd->bg_inode_bitmap ){
854dc5a79c1SDavid du Colombier chat("Allocating block in system zone...");
855dc5a79c1SDavid du Colombier putext2(ed); putext2(eb); putext2(es);
856dc5a79c1SDavid du Colombier errno = Eintern;
857dc5a79c1SDavid du Colombier return 0;
858dc5a79c1SDavid du Colombier }
859dc5a79c1SDavid du Colombier
860dc5a79c1SDavid du Colombier if( set_bit(block, eb.u.bmp) ){
861dc5a79c1SDavid du Colombier chat("bit already set (%d)...", block);
862dc5a79c1SDavid du Colombier putext2(ed); putext2(eb); putext2(es);
863dc5a79c1SDavid du Colombier errno = Ecorrupt;
864dc5a79c1SDavid du Colombier return 0;
865dc5a79c1SDavid du Colombier }
866dc5a79c1SDavid du Colombier dirtyext2(eb);
867dc5a79c1SDavid du Colombier
868dc5a79c1SDavid du Colombier if( baddr >= es.u.sb->s_blocks_count ){
869dc5a79c1SDavid du Colombier chat("block >= blocks count...");
870dc5a79c1SDavid du Colombier errno = Eintern;
871dc5a79c1SDavid du Colombier error:
872dc5a79c1SDavid du Colombier clear_bit(block, eb.u.bmp);
873dc5a79c1SDavid du Colombier putext2(eb); putext2(ed); putext2(es);
874dc5a79c1SDavid du Colombier return 0;
875dc5a79c1SDavid du Colombier }
876dc5a79c1SDavid du Colombier
877dc5a79c1SDavid du Colombier buf = getbuf(xf, baddr);
878dc5a79c1SDavid du Colombier if( !buf ){
879dc5a79c1SDavid du Colombier if( !redo ){
880dc5a79c1SDavid du Colombier /*
881dc5a79c1SDavid du Colombier * It's perhaps the last block of the disk and
882dc5a79c1SDavid du Colombier * it can't be acceded because the last sector.
883dc5a79c1SDavid du Colombier * Therefore, we try one more time with goal at 0
884dc5a79c1SDavid du Colombier * to force scanning all groups.
885dc5a79c1SDavid du Colombier */
886dc5a79c1SDavid du Colombier clear_bit(block, eb.u.bmp);
887dc5a79c1SDavid du Colombier putext2(eb); putext2(ed);
888dc5a79c1SDavid du Colombier goal = 0; errno = 0; redo++;
889dc5a79c1SDavid du Colombier goto repeat;
890dc5a79c1SDavid du Colombier }
891dc5a79c1SDavid du Colombier goto error;
892dc5a79c1SDavid du Colombier }
893dc5a79c1SDavid du Colombier memset(&buf->iobuf[0], 0, xf->block_size);
894dc5a79c1SDavid du Colombier dirtybuf(buf);
895dc5a79c1SDavid du Colombier putbuf(buf);
896dc5a79c1SDavid du Colombier
897dc5a79c1SDavid du Colombier es.u.sb->s_free_blocks_count--;
898dc5a79c1SDavid du Colombier dirtyext2(es);
899dc5a79c1SDavid du Colombier ed.u.gd->bg_free_blocks_count--;
900dc5a79c1SDavid du Colombier dirtyext2(ed);
901dc5a79c1SDavid du Colombier
902dc5a79c1SDavid du Colombier putext2(eb);
903dc5a79c1SDavid du Colombier putext2(ed);
904dc5a79c1SDavid du Colombier putext2(es);
905dc5a79c1SDavid du Colombier chat("new ");
906dc5a79c1SDavid du Colombier return baddr;
907dc5a79c1SDavid du Colombier }
908dc5a79c1SDavid du Colombier int
getblk(Xfile * f,int block)909dc5a79c1SDavid du Colombier getblk(Xfile *f, int block)
910dc5a79c1SDavid du Colombier {
911dc5a79c1SDavid du Colombier Xfs *xf = f->xf;
912dc5a79c1SDavid du Colombier int baddr;
913dc5a79c1SDavid du Colombier int addr_per_block = xf->addr_per_block;
914dc5a79c1SDavid du Colombier
915dc5a79c1SDavid du Colombier if (block < 0) {
916dc5a79c1SDavid du Colombier chat("getblk() block < 0 ...");
917dc5a79c1SDavid du Colombier return 0;
918dc5a79c1SDavid du Colombier }
919dc5a79c1SDavid du Colombier if(block > EXT2_NDIR_BLOCKS + addr_per_block +
920dc5a79c1SDavid du Colombier addr_per_block * addr_per_block +
921dc5a79c1SDavid du Colombier addr_per_block * addr_per_block * addr_per_block ){
922dc5a79c1SDavid du Colombier chat("getblk() block > big...");
923dc5a79c1SDavid du Colombier errno = Eintern;
924dc5a79c1SDavid du Colombier return 0;
925dc5a79c1SDavid du Colombier }
926dc5a79c1SDavid du Colombier if( block < EXT2_NDIR_BLOCKS )
927dc5a79c1SDavid du Colombier return inode_getblk(f, block);
928dc5a79c1SDavid du Colombier block -= EXT2_NDIR_BLOCKS;
929dc5a79c1SDavid du Colombier if( block < addr_per_block ){
930dc5a79c1SDavid du Colombier baddr = inode_getblk(f, EXT2_IND_BLOCK);
931dc5a79c1SDavid du Colombier baddr = block_getblk(f, baddr, block);
932dc5a79c1SDavid du Colombier return baddr;
933dc5a79c1SDavid du Colombier }
934dc5a79c1SDavid du Colombier block -= addr_per_block;
935dc5a79c1SDavid du Colombier if( block < addr_per_block * addr_per_block ){
936dc5a79c1SDavid du Colombier baddr = inode_getblk(f, EXT2_DIND_BLOCK);
937dc5a79c1SDavid du Colombier baddr = block_getblk(f, baddr, block / addr_per_block);
938dc5a79c1SDavid du Colombier baddr = block_getblk(f, baddr, block & ( addr_per_block-1));
939dc5a79c1SDavid du Colombier return baddr;
940dc5a79c1SDavid du Colombier }
941dc5a79c1SDavid du Colombier block -= addr_per_block * addr_per_block;
942dc5a79c1SDavid du Colombier baddr = inode_getblk(f, EXT2_TIND_BLOCK);
943dc5a79c1SDavid du Colombier baddr = block_getblk(f, baddr, block / (addr_per_block * addr_per_block));
944dc5a79c1SDavid du Colombier baddr = block_getblk(f, baddr, (block / addr_per_block) & ( addr_per_block-1));
945dc5a79c1SDavid du Colombier return block_getblk(f, baddr, block & ( addr_per_block-1));
946dc5a79c1SDavid du Colombier }
947dc5a79c1SDavid du Colombier int
block_getblk(Xfile * f,int rb,int nr)948dc5a79c1SDavid du Colombier block_getblk(Xfile *f, int rb, int nr)
949dc5a79c1SDavid du Colombier {
950dc5a79c1SDavid du Colombier Xfs *xf = f->xf;
951dc5a79c1SDavid du Colombier Inode *inode;
952dc5a79c1SDavid du Colombier int tmp, goal = 0;
953dc5a79c1SDavid du Colombier int blocks = xf->block_size / 512;
954dc5a79c1SDavid du Colombier Iobuf *buf, *ibuf;
955dc5a79c1SDavid du Colombier uint *p;
956dc5a79c1SDavid du Colombier Ext2 es;
957dc5a79c1SDavid du Colombier
958dc5a79c1SDavid du Colombier if( !rb )
959dc5a79c1SDavid du Colombier return 0;
960dc5a79c1SDavid du Colombier
961dc5a79c1SDavid du Colombier buf = getbuf(xf, rb);
962dc5a79c1SDavid du Colombier if( !buf )
963dc5a79c1SDavid du Colombier return 0;
964dc5a79c1SDavid du Colombier p = (uint *)(buf->iobuf) + nr;
965dc5a79c1SDavid du Colombier if( *p ){
966dc5a79c1SDavid du Colombier tmp = *p;
967dc5a79c1SDavid du Colombier putbuf(buf);
968dc5a79c1SDavid du Colombier return tmp;
969dc5a79c1SDavid du Colombier }
970dc5a79c1SDavid du Colombier
971dc5a79c1SDavid du Colombier for(tmp=nr - 1 ; tmp >= 0 ; tmp--){
972dc5a79c1SDavid du Colombier if( ((uint *)(buf->iobuf))[tmp] ){
973dc5a79c1SDavid du Colombier goal = ((uint *)(buf->iobuf))[tmp];
974dc5a79c1SDavid du Colombier break;
975dc5a79c1SDavid du Colombier }
976dc5a79c1SDavid du Colombier }
977dc5a79c1SDavid du Colombier if( !goal ){
978dc5a79c1SDavid du Colombier es = getext2(xf, EXT2_SUPER, 0);
979dc5a79c1SDavid du Colombier goal = (((f->inbr -1) / xf->inodes_per_group) *
980dc5a79c1SDavid du Colombier xf->blocks_per_group) +
981dc5a79c1SDavid du Colombier es.u.sb->s_first_data_block;
982dc5a79c1SDavid du Colombier putext2(es);
983dc5a79c1SDavid du Colombier }
984dc5a79c1SDavid du Colombier
985dc5a79c1SDavid du Colombier tmp = new_block(f, goal);
986dc5a79c1SDavid du Colombier if( !tmp ){
987dc5a79c1SDavid du Colombier putbuf(buf);
988dc5a79c1SDavid du Colombier return 0;
989dc5a79c1SDavid du Colombier }
990dc5a79c1SDavid du Colombier
991dc5a79c1SDavid du Colombier *p = tmp;
992dc5a79c1SDavid du Colombier dirtybuf(buf);
993dc5a79c1SDavid du Colombier putbuf(buf);
994dc5a79c1SDavid du Colombier
995dc5a79c1SDavid du Colombier ibuf = getbuf(xf, f->bufaddr);
996dc5a79c1SDavid du Colombier if( !ibuf )
997dc5a79c1SDavid du Colombier return -1;
998dc5a79c1SDavid du Colombier inode = ((Inode *)ibuf->iobuf) + f->bufoffset;
999dc5a79c1SDavid du Colombier inode->i_blocks += blocks;
1000dc5a79c1SDavid du Colombier dirtybuf(ibuf);
1001dc5a79c1SDavid du Colombier putbuf(ibuf);
1002dc5a79c1SDavid du Colombier
1003dc5a79c1SDavid du Colombier return tmp;
1004dc5a79c1SDavid du Colombier }
1005dc5a79c1SDavid du Colombier int
inode_getblk(Xfile * f,int block)1006dc5a79c1SDavid du Colombier inode_getblk(Xfile *f, int block)
1007dc5a79c1SDavid du Colombier {
1008dc5a79c1SDavid du Colombier Xfs *xf = f->xf;
1009dc5a79c1SDavid du Colombier Inode *inode;
1010dc5a79c1SDavid du Colombier Iobuf *ibuf;
1011dc5a79c1SDavid du Colombier int tmp, goal = 0;
1012dc5a79c1SDavid du Colombier int blocks = xf->block_size / 512;
1013dc5a79c1SDavid du Colombier Ext2 es;
1014dc5a79c1SDavid du Colombier
1015dc5a79c1SDavid du Colombier ibuf = getbuf(xf, f->bufaddr);
1016dc5a79c1SDavid du Colombier if( !ibuf )
1017dc5a79c1SDavid du Colombier return -1;
1018dc5a79c1SDavid du Colombier inode = ((Inode *)ibuf->iobuf) + f->bufoffset;
1019dc5a79c1SDavid du Colombier
1020dc5a79c1SDavid du Colombier
1021dc5a79c1SDavid du Colombier if( inode->i_block[block] ){
1022dc5a79c1SDavid du Colombier putbuf(ibuf);
1023dc5a79c1SDavid du Colombier return inode->i_block[block];
1024dc5a79c1SDavid du Colombier }
1025dc5a79c1SDavid du Colombier
1026dc5a79c1SDavid du Colombier for(tmp=block - 1 ; tmp >= 0 ; tmp--){
1027dc5a79c1SDavid du Colombier if( inode->i_block[tmp] ){
1028dc5a79c1SDavid du Colombier goal = inode->i_block[tmp];
1029dc5a79c1SDavid du Colombier break;
1030dc5a79c1SDavid du Colombier }
1031dc5a79c1SDavid du Colombier }
1032dc5a79c1SDavid du Colombier if( !goal ){
1033dc5a79c1SDavid du Colombier es = getext2(xf, EXT2_SUPER, 0);
1034dc5a79c1SDavid du Colombier goal = (((f->inbr -1) / xf->inodes_per_group) *
1035dc5a79c1SDavid du Colombier xf->blocks_per_group) +
1036dc5a79c1SDavid du Colombier es.u.sb->s_first_data_block;
1037dc5a79c1SDavid du Colombier putext2(es);
1038dc5a79c1SDavid du Colombier }
1039dc5a79c1SDavid du Colombier
1040dc5a79c1SDavid du Colombier tmp = new_block(f, goal);
1041dc5a79c1SDavid du Colombier if( !tmp ){
1042dc5a79c1SDavid du Colombier putbuf(ibuf);
1043dc5a79c1SDavid du Colombier return 0;
1044dc5a79c1SDavid du Colombier }
1045dc5a79c1SDavid du Colombier
1046dc5a79c1SDavid du Colombier inode->i_block[block] = tmp;
1047dc5a79c1SDavid du Colombier inode->i_blocks += blocks;
1048dc5a79c1SDavid du Colombier dirtybuf(ibuf);
1049dc5a79c1SDavid du Colombier putbuf(ibuf);
1050dc5a79c1SDavid du Colombier
1051dc5a79c1SDavid du Colombier return tmp;
1052dc5a79c1SDavid du Colombier }
1053dc5a79c1SDavid du Colombier int
new_inode(Xfile * f,int mode)1054dc5a79c1SDavid du Colombier new_inode(Xfile *f, int mode)
1055dc5a79c1SDavid du Colombier {
1056dc5a79c1SDavid du Colombier Xfs *xf = f->xf;
1057dc5a79c1SDavid du Colombier Inode *inode, *finode;
1058dc5a79c1SDavid du Colombier Iobuf *buf, *ibuf;
1059dc5a79c1SDavid du Colombier int ave,group, i, j;
1060dc5a79c1SDavid du Colombier Ext2 ed, es, eb;
1061dc5a79c1SDavid du Colombier
1062dc5a79c1SDavid du Colombier group = -1;
1063dc5a79c1SDavid du Colombier
1064dc5a79c1SDavid du Colombier es = getext2(xf, EXT2_SUPER, 0);
1065dc5a79c1SDavid du Colombier
1066dc5a79c1SDavid du Colombier if( S_ISDIR(mode) ){ /* create directory inode */
1067dc5a79c1SDavid du Colombier ave = es.u.sb->s_free_inodes_count / xf->ngroups;
1068dc5a79c1SDavid du Colombier for(i=0 ; i < xf->ngroups ; i++){
1069dc5a79c1SDavid du Colombier ed = getext2(xf, EXT2_DESC, i);
1070dc5a79c1SDavid du Colombier if( ed.u.gd->bg_free_inodes_count &&
1071dc5a79c1SDavid du Colombier ed.u.gd->bg_free_inodes_count >= ave ){
1072dc5a79c1SDavid du Colombier if( group<0 || ed.u.gd->bg_free_inodes_count >
1073dc5a79c1SDavid du Colombier ed.u.gd->bg_free_inodes_count )
1074dc5a79c1SDavid du Colombier group = i;
1075dc5a79c1SDavid du Colombier }
1076dc5a79c1SDavid du Colombier putext2(ed);
1077dc5a79c1SDavid du Colombier }
1078dc5a79c1SDavid du Colombier
1079dc5a79c1SDavid du Colombier }else{ /* create file inode */
1080dc5a79c1SDavid du Colombier /* Try to put inode in its parent directory */
1081dc5a79c1SDavid du Colombier i = (f->inbr -1) / xf->inodes_per_group;
1082dc5a79c1SDavid du Colombier ed = getext2(xf, EXT2_DESC, i);
1083dc5a79c1SDavid du Colombier if( ed.u.gd->bg_free_inodes_count ){
1084dc5a79c1SDavid du Colombier group = i;
1085dc5a79c1SDavid du Colombier putext2(ed);
1086dc5a79c1SDavid du Colombier }else{
1087dc5a79c1SDavid du Colombier /*
1088dc5a79c1SDavid du Colombier * Use a quadratic hash to find a group whith
1089dc5a79c1SDavid du Colombier * a free inode
1090dc5a79c1SDavid du Colombier */
1091dc5a79c1SDavid du Colombier putext2(ed);
1092dc5a79c1SDavid du Colombier for( j=1 ; j < xf->ngroups ; j <<= 1){
1093dc5a79c1SDavid du Colombier i += j;
1094dc5a79c1SDavid du Colombier if( i >= xf->ngroups )
1095dc5a79c1SDavid du Colombier i -= xf->ngroups;
1096dc5a79c1SDavid du Colombier ed = getext2(xf, EXT2_DESC, i);
1097dc5a79c1SDavid du Colombier if( ed.u.gd->bg_free_inodes_count ){
1098dc5a79c1SDavid du Colombier group = i;
1099dc5a79c1SDavid du Colombier putext2(ed);
1100dc5a79c1SDavid du Colombier break;
1101dc5a79c1SDavid du Colombier }
1102dc5a79c1SDavid du Colombier putext2(ed);
1103dc5a79c1SDavid du Colombier }
1104dc5a79c1SDavid du Colombier }
1105dc5a79c1SDavid du Colombier if( group < 0 ){
1106dc5a79c1SDavid du Colombier /* try a linear search */
1107dc5a79c1SDavid du Colombier i = ((f->inbr -1) / xf->inodes_per_group) + 1;
1108dc5a79c1SDavid du Colombier for(j=2 ; j < xf->ngroups ; j++){
1109dc5a79c1SDavid du Colombier if( ++i >= xf->ngroups )
1110dc5a79c1SDavid du Colombier i = 0;
1111dc5a79c1SDavid du Colombier ed = getext2(xf, EXT2_DESC, i);
1112dc5a79c1SDavid du Colombier if( ed.u.gd->bg_free_inodes_count ){
1113dc5a79c1SDavid du Colombier group = i;
1114dc5a79c1SDavid du Colombier putext2(ed);
1115dc5a79c1SDavid du Colombier break;
1116dc5a79c1SDavid du Colombier }
1117dc5a79c1SDavid du Colombier putext2(ed);
1118dc5a79c1SDavid du Colombier }
1119dc5a79c1SDavid du Colombier }
1120dc5a79c1SDavid du Colombier
1121dc5a79c1SDavid du Colombier }
1122dc5a79c1SDavid du Colombier if( group < 0 ){
1123dc5a79c1SDavid du Colombier chat("group < 0...");
1124dc5a79c1SDavid du Colombier putext2(es);
1125dc5a79c1SDavid du Colombier return 0;
1126dc5a79c1SDavid du Colombier }
1127dc5a79c1SDavid du Colombier ed = getext2(xf, EXT2_DESC, group);
1128dc5a79c1SDavid du Colombier eb = getext2(xf, EXT2_BINODE, group);
1129dc5a79c1SDavid du Colombier if( (j = find_first_zero_bit(eb.u.bmp,
1130dc5a79c1SDavid du Colombier xf->inodes_per_group>>3)) < xf->inodes_per_group){
1131dc5a79c1SDavid du Colombier if( set_bit(j, eb.u.bmp) ){
1132dc5a79c1SDavid du Colombier chat("inode %d of group %d is already allocated...", j, group);
1133dc5a79c1SDavid du Colombier putext2(ed); putext2(eb); putext2(es);
1134dc5a79c1SDavid du Colombier errno = Ecorrupt;
1135dc5a79c1SDavid du Colombier return 0;
1136dc5a79c1SDavid du Colombier }
1137dc5a79c1SDavid du Colombier dirtyext2(eb);
1138dc5a79c1SDavid du Colombier }else if( ed.u.gd->bg_free_inodes_count != 0 ){
1139dc5a79c1SDavid du Colombier chat("free inodes count corrupted for group %d...", group);
1140dc5a79c1SDavid du Colombier putext2(ed); putext2(eb); putext2(es);
1141dc5a79c1SDavid du Colombier errno = Ecorrupt;
1142dc5a79c1SDavid du Colombier return 0;
1143dc5a79c1SDavid du Colombier }
1144dc5a79c1SDavid du Colombier i = j;
1145dc5a79c1SDavid du Colombier j += group * xf->inodes_per_group + 1;
1146dc5a79c1SDavid du Colombier if( j < EXT2_FIRST_INO || j >= es.u.sb->s_inodes_count ){
1147dc5a79c1SDavid du Colombier chat("reserved inode or inode > inodes count...");
1148dc5a79c1SDavid du Colombier errno = Ecorrupt;
1149dc5a79c1SDavid du Colombier error:
1150dc5a79c1SDavid du Colombier clear_bit(i, eb.u.bmp);
1151dc5a79c1SDavid du Colombier putext2(eb); putext2(ed); putext2(es);
1152dc5a79c1SDavid du Colombier return 0;
1153dc5a79c1SDavid du Colombier }
1154dc5a79c1SDavid du Colombier
1155dc5a79c1SDavid du Colombier buf = getbuf(xf, ed.u.gd->bg_inode_table +
1156dc5a79c1SDavid du Colombier (((j-1) % xf->inodes_per_group) /
1157dc5a79c1SDavid du Colombier xf->inodes_per_block));
1158dc5a79c1SDavid du Colombier if( !buf )
1159dc5a79c1SDavid du Colombier goto error;
1160dc5a79c1SDavid du Colombier inode = ((struct Inode *) buf->iobuf) +
1161dc5a79c1SDavid du Colombier ((j-1) % xf->inodes_per_block);
1162dc5a79c1SDavid du Colombier memset(inode, 0, sizeof(Inode));
1163dc5a79c1SDavid du Colombier inode->i_mode = mode;
1164dc5a79c1SDavid du Colombier inode->i_links_count = 1;
1165dc5a79c1SDavid du Colombier inode->i_uid = DEFAULT_UID;
1166dc5a79c1SDavid du Colombier inode->i_gid = DEFAULT_GID;
1167dc5a79c1SDavid du Colombier inode->i_mtime = inode->i_atime = inode->i_ctime = time(0);
1168dc5a79c1SDavid du Colombier dirtybuf(buf);
1169dc5a79c1SDavid du Colombier
1170dc5a79c1SDavid du Colombier ibuf = getbuf(xf, f->bufaddr);
1171dc5a79c1SDavid du Colombier if( !ibuf ){
1172dc5a79c1SDavid du Colombier putbuf(buf);
1173dc5a79c1SDavid du Colombier goto error;
1174dc5a79c1SDavid du Colombier }
1175dc5a79c1SDavid du Colombier finode = ((Inode *)ibuf->iobuf) + f->bufoffset;
1176dc5a79c1SDavid du Colombier inode->i_flags = finode->i_flags;
1177dc5a79c1SDavid du Colombier inode->i_uid = finode->i_uid;
1178dc5a79c1SDavid du Colombier inode->i_gid = finode->i_gid;
1179dc5a79c1SDavid du Colombier dirtybuf(ibuf);
1180dc5a79c1SDavid du Colombier putbuf(ibuf);
1181dc5a79c1SDavid du Colombier
1182dc5a79c1SDavid du Colombier putbuf(buf);
1183dc5a79c1SDavid du Colombier
1184dc5a79c1SDavid du Colombier ed.u.gd->bg_free_inodes_count--;
1185dc5a79c1SDavid du Colombier if( S_ISDIR(mode) )
1186dc5a79c1SDavid du Colombier ed.u.gd->bg_used_dirs_count++;
1187dc5a79c1SDavid du Colombier dirtyext2(ed);
1188dc5a79c1SDavid du Colombier
1189dc5a79c1SDavid du Colombier es.u.sb->s_free_inodes_count--;
1190dc5a79c1SDavid du Colombier dirtyext2(es);
1191dc5a79c1SDavid du Colombier
1192dc5a79c1SDavid du Colombier putext2(eb);
1193dc5a79c1SDavid du Colombier putext2(ed);
1194dc5a79c1SDavid du Colombier putext2(es);
1195dc5a79c1SDavid du Colombier
1196dc5a79c1SDavid du Colombier return j;
1197dc5a79c1SDavid du Colombier }
1198dc5a79c1SDavid du Colombier int
create_file(Xfile * fdir,char * name,int mode)1199dc5a79c1SDavid du Colombier create_file(Xfile *fdir, char *name, int mode)
1200dc5a79c1SDavid du Colombier {
1201dc5a79c1SDavid du Colombier int inr;
1202dc5a79c1SDavid du Colombier
1203dc5a79c1SDavid du Colombier inr = new_inode(fdir, mode);
1204dc5a79c1SDavid du Colombier if( !inr ){
1205dc5a79c1SDavid du Colombier chat("create one new inode failed...");
1206dc5a79c1SDavid du Colombier return -1;
1207dc5a79c1SDavid du Colombier }
1208dc5a79c1SDavid du Colombier if( add_entry(fdir, name, inr) < 0 ){
1209dc5a79c1SDavid du Colombier chat("add entry failed...");
1210dc5a79c1SDavid du Colombier free_inode(fdir->xf, inr);
1211dc5a79c1SDavid du Colombier return -1;
1212dc5a79c1SDavid du Colombier }
1213dc5a79c1SDavid du Colombier
1214dc5a79c1SDavid du Colombier return inr;
1215dc5a79c1SDavid du Colombier }
1216dc5a79c1SDavid du Colombier void
free_inode(Xfs * xf,int inr)1217dc5a79c1SDavid du Colombier free_inode( Xfs *xf, int inr)
1218dc5a79c1SDavid du Colombier {
1219dc5a79c1SDavid du Colombier Inode *inode;
1220dc5a79c1SDavid du Colombier ulong b, bg;
1221dc5a79c1SDavid du Colombier Iobuf *buf;
1222dc5a79c1SDavid du Colombier Ext2 ed, es, eb;
1223dc5a79c1SDavid du Colombier
1224dc5a79c1SDavid du Colombier bg = (inr -1) / xf->inodes_per_group;
1225dc5a79c1SDavid du Colombier b = (inr -1) % xf->inodes_per_group;
1226dc5a79c1SDavid du Colombier
1227dc5a79c1SDavid du Colombier ed = getext2(xf, EXT2_DESC, bg);
1228dc5a79c1SDavid du Colombier buf = getbuf(xf, ed.u.gd->bg_inode_table +
1229dc5a79c1SDavid du Colombier (b / xf->inodes_per_block));
1230dc5a79c1SDavid du Colombier if( !buf ){
1231dc5a79c1SDavid du Colombier putext2(ed);
1232dc5a79c1SDavid du Colombier return;
1233dc5a79c1SDavid du Colombier }
1234dc5a79c1SDavid du Colombier inode = ((struct Inode *) buf->iobuf) +
1235dc5a79c1SDavid du Colombier ((inr-1) % xf->inodes_per_block);
1236dc5a79c1SDavid du Colombier
1237dc5a79c1SDavid du Colombier if( S_ISDIR(inode->i_mode) )
1238dc5a79c1SDavid du Colombier ed.u.gd->bg_used_dirs_count--;
1239dc5a79c1SDavid du Colombier memset(inode, 0, sizeof(Inode));
1240dc5a79c1SDavid du Colombier inode->i_dtime = time(0);
1241dc5a79c1SDavid du Colombier dirtybuf(buf);
1242dc5a79c1SDavid du Colombier putbuf(buf);
1243dc5a79c1SDavid du Colombier
1244dc5a79c1SDavid du Colombier ed.u.gd->bg_free_inodes_count++;
1245dc5a79c1SDavid du Colombier dirtyext2(ed);
1246dc5a79c1SDavid du Colombier putext2(ed);
1247dc5a79c1SDavid du Colombier
1248dc5a79c1SDavid du Colombier eb = getext2(xf, EXT2_BINODE, bg);
1249dc5a79c1SDavid du Colombier clear_bit(b, eb.u.bmp);
1250dc5a79c1SDavid du Colombier dirtyext2(eb);
1251dc5a79c1SDavid du Colombier putext2(eb);
1252dc5a79c1SDavid du Colombier
1253dc5a79c1SDavid du Colombier es = getext2(xf, EXT2_SUPER, 0);
1254dc5a79c1SDavid du Colombier es.u.sb->s_free_inodes_count++;
1255dc5a79c1SDavid du Colombier dirtyext2(es); putext2(es);
1256dc5a79c1SDavid du Colombier }
1257dc5a79c1SDavid du Colombier int
create_dir(Xfile * fdir,char * name,int mode)1258dc5a79c1SDavid du Colombier create_dir(Xfile *fdir, char *name, int mode)
1259dc5a79c1SDavid du Colombier {
1260dc5a79c1SDavid du Colombier Xfs *xf = fdir->xf;
1261dc5a79c1SDavid du Colombier DirEntry *de;
1262dc5a79c1SDavid du Colombier Inode *inode;
1263dc5a79c1SDavid du Colombier Iobuf *buf, *ibuf;
1264dc5a79c1SDavid du Colombier Xfile tf;
1265dc5a79c1SDavid du Colombier int inr, baddr;
1266dc5a79c1SDavid du Colombier
1267dc5a79c1SDavid du Colombier inr = new_inode(fdir, mode);
1268dc5a79c1SDavid du Colombier if( inr == 0 ){
1269dc5a79c1SDavid du Colombier chat("create one new inode failed...");
1270dc5a79c1SDavid du Colombier return -1;
1271dc5a79c1SDavid du Colombier }
1272dc5a79c1SDavid du Colombier if( add_entry(fdir, name, inr) < 0 ){
1273dc5a79c1SDavid du Colombier chat("add entry failed...");
1274dc5a79c1SDavid du Colombier free_inode(fdir->xf, inr);
1275dc5a79c1SDavid du Colombier return -1;
1276dc5a79c1SDavid du Colombier }
1277dc5a79c1SDavid du Colombier
1278dc5a79c1SDavid du Colombier /* create the empty dir */
1279dc5a79c1SDavid du Colombier
1280dc5a79c1SDavid du Colombier tf = *fdir;
1281dc5a79c1SDavid du Colombier if( get_inode(&tf, inr) < 0 ){
1282dc5a79c1SDavid du Colombier chat("can't get inode %d...", inr);
1283dc5a79c1SDavid du Colombier free_inode(fdir->xf, inr);
1284dc5a79c1SDavid du Colombier return -1;
1285dc5a79c1SDavid du Colombier }
1286dc5a79c1SDavid du Colombier
1287dc5a79c1SDavid du Colombier ibuf = getbuf(xf, tf.bufaddr);
1288dc5a79c1SDavid du Colombier if( !ibuf ){
1289dc5a79c1SDavid du Colombier free_inode(fdir->xf, inr);
1290dc5a79c1SDavid du Colombier return -1;
1291dc5a79c1SDavid du Colombier }
1292dc5a79c1SDavid du Colombier inode = ((Inode *)ibuf->iobuf) + tf.bufoffset;
1293dc5a79c1SDavid du Colombier
1294dc5a79c1SDavid du Colombier
1295dc5a79c1SDavid du Colombier baddr = inode_getblk(&tf, 0);
1296dc5a79c1SDavid du Colombier if( !baddr ){
1297dc5a79c1SDavid du Colombier putbuf(ibuf);
1298dc5a79c1SDavid du Colombier ibuf = getbuf(xf, fdir->bufaddr);
1299dc5a79c1SDavid du Colombier if( !ibuf ){
1300dc5a79c1SDavid du Colombier free_inode(fdir->xf, inr);
1301dc5a79c1SDavid du Colombier return -1;
1302dc5a79c1SDavid du Colombier }
1303dc5a79c1SDavid du Colombier inode = ((Inode *)ibuf->iobuf) + fdir->bufoffset;
1304dc5a79c1SDavid du Colombier delete_entry(fdir->xf, inode, inr);
1305dc5a79c1SDavid du Colombier putbuf(ibuf);
1306dc5a79c1SDavid du Colombier free_inode(fdir->xf, inr);
1307dc5a79c1SDavid du Colombier return -1;
1308dc5a79c1SDavid du Colombier }
1309dc5a79c1SDavid du Colombier
1310dc5a79c1SDavid du Colombier inode->i_size = xf->block_size;
1311dc5a79c1SDavid du Colombier buf = getbuf(xf, baddr);
1312dc5a79c1SDavid du Colombier
1313dc5a79c1SDavid du Colombier de = (DirEntry *)buf->iobuf;
1314dc5a79c1SDavid du Colombier de->inode = inr;
1315dc5a79c1SDavid du Colombier de->name_len = 1;
1316dc5a79c1SDavid du Colombier de->rec_len = DIR_REC_LEN(de->name_len);
1317dc5a79c1SDavid du Colombier strcpy(de->name, ".");
1318dc5a79c1SDavid du Colombier
1319dc5a79c1SDavid du Colombier de = (DirEntry *)( (char *)de + de->rec_len);
1320dc5a79c1SDavid du Colombier de->inode = fdir->inbr;
1321dc5a79c1SDavid du Colombier de->name_len = 2;
1322dc5a79c1SDavid du Colombier de->rec_len = xf->block_size - DIR_REC_LEN(1);
1323dc5a79c1SDavid du Colombier strcpy(de->name, "..");
1324dc5a79c1SDavid du Colombier
1325dc5a79c1SDavid du Colombier dirtybuf(buf);
1326dc5a79c1SDavid du Colombier putbuf(buf);
1327dc5a79c1SDavid du Colombier
1328dc5a79c1SDavid du Colombier inode->i_links_count = 2;
1329dc5a79c1SDavid du Colombier dirtybuf(ibuf);
1330dc5a79c1SDavid du Colombier putbuf(ibuf);
1331dc5a79c1SDavid du Colombier
1332dc5a79c1SDavid du Colombier ibuf = getbuf(xf, fdir->bufaddr);
1333dc5a79c1SDavid du Colombier if( !ibuf )
1334dc5a79c1SDavid du Colombier return -1;
1335dc5a79c1SDavid du Colombier inode = ((Inode *)ibuf->iobuf) + fdir->bufoffset;
1336dc5a79c1SDavid du Colombier
1337dc5a79c1SDavid du Colombier inode->i_links_count++;
1338dc5a79c1SDavid du Colombier
1339dc5a79c1SDavid du Colombier dirtybuf(ibuf);
1340dc5a79c1SDavid du Colombier putbuf(ibuf);
1341dc5a79c1SDavid du Colombier
1342dc5a79c1SDavid du Colombier return inr;
1343dc5a79c1SDavid du Colombier }
1344dc5a79c1SDavid du Colombier int
add_entry(Xfile * f,char * name,int inr)1345dc5a79c1SDavid du Colombier add_entry(Xfile *f, char *name, int inr)
1346dc5a79c1SDavid du Colombier {
1347dc5a79c1SDavid du Colombier Xfs *xf = f->xf;
1348dc5a79c1SDavid du Colombier DirEntry *de, *de1;
1349dc5a79c1SDavid du Colombier int offset, baddr;
1350dc5a79c1SDavid du Colombier int rec_len, cur_block;
1351dc5a79c1SDavid du Colombier int namelen = strlen(name);
1352dc5a79c1SDavid du Colombier Inode *inode;
1353dc5a79c1SDavid du Colombier Iobuf *buf, *ibuf;
1354dc5a79c1SDavid du Colombier
1355dc5a79c1SDavid du Colombier ibuf = getbuf(xf, f->bufaddr);
1356dc5a79c1SDavid du Colombier if( !ibuf )
1357dc5a79c1SDavid du Colombier return -1;
1358dc5a79c1SDavid du Colombier inode = ((Inode *)ibuf->iobuf) + f->bufoffset;
1359dc5a79c1SDavid du Colombier
1360dc5a79c1SDavid du Colombier if( inode->i_size == 0 ){
1361dc5a79c1SDavid du Colombier chat("add_entry() no entry !!!...");
1362dc5a79c1SDavid du Colombier putbuf(ibuf);
1363dc5a79c1SDavid du Colombier return -1;
1364dc5a79c1SDavid du Colombier }
1365dc5a79c1SDavid du Colombier cur_block = offset = 0;
1366dc5a79c1SDavid du Colombier rec_len = DIR_REC_LEN(namelen);
1367dc5a79c1SDavid du Colombier buf = getbuf(xf, inode->i_block[cur_block++]);
1368dc5a79c1SDavid du Colombier if( !buf ){
1369dc5a79c1SDavid du Colombier putbuf(ibuf);
1370dc5a79c1SDavid du Colombier return -1;
1371dc5a79c1SDavid du Colombier }
1372dc5a79c1SDavid du Colombier de = (DirEntry *)buf->iobuf;
1373dc5a79c1SDavid du Colombier
1374dc5a79c1SDavid du Colombier for(;;){
1375dc5a79c1SDavid du Colombier if( ((char *)de) >= (xf->block_size + buf->iobuf) ){
1376dc5a79c1SDavid du Colombier putbuf(buf);
1377dc5a79c1SDavid du Colombier if( cur_block >= EXT2_NDIR_BLOCKS ){
1378dc5a79c1SDavid du Colombier errno = Enospace;
1379dc5a79c1SDavid du Colombier putbuf(ibuf);
1380dc5a79c1SDavid du Colombier return -1;
1381dc5a79c1SDavid du Colombier }
1382dc5a79c1SDavid du Colombier if( (baddr = inode_getblk(f, cur_block++)) == 0 ){
1383dc5a79c1SDavid du Colombier putbuf(ibuf);
1384dc5a79c1SDavid du Colombier return -1;
1385dc5a79c1SDavid du Colombier }
1386dc5a79c1SDavid du Colombier buf = getbuf(xf, baddr);
1387dc5a79c1SDavid du Colombier if( !buf ){
1388dc5a79c1SDavid du Colombier putbuf(ibuf);
1389dc5a79c1SDavid du Colombier return -1;
1390dc5a79c1SDavid du Colombier }
1391dc5a79c1SDavid du Colombier if( inode->i_size <= offset ){
1392dc5a79c1SDavid du Colombier de = (DirEntry *)buf->iobuf;
1393dc5a79c1SDavid du Colombier de->inode = 0;
1394dc5a79c1SDavid du Colombier de->rec_len = xf->block_size;
1395dc5a79c1SDavid du Colombier dirtybuf(buf);
1396dc5a79c1SDavid du Colombier inode->i_size = offset + xf->block_size;
1397dc5a79c1SDavid du Colombier dirtybuf(ibuf);
1398dc5a79c1SDavid du Colombier }else{
1399dc5a79c1SDavid du Colombier de = (DirEntry *)buf->iobuf;
1400dc5a79c1SDavid du Colombier }
1401dc5a79c1SDavid du Colombier }
1402dc5a79c1SDavid du Colombier if( de->inode != 0 && de->name_len == namelen &&
1403dc5a79c1SDavid du Colombier !strncmp(name, de->name, namelen) ){
1404dc5a79c1SDavid du Colombier errno = Eexist;
1405dc5a79c1SDavid du Colombier putbuf(ibuf); putbuf(buf);
1406dc5a79c1SDavid du Colombier return -1;
1407dc5a79c1SDavid du Colombier }
1408dc5a79c1SDavid du Colombier offset += de->rec_len;
1409dc5a79c1SDavid du Colombier if( (de->inode == 0 && de->rec_len >= rec_len) ||
1410dc5a79c1SDavid du Colombier (de->rec_len >= DIR_REC_LEN(de->name_len) + rec_len) ){
1411dc5a79c1SDavid du Colombier if( de->inode ){
1412dc5a79c1SDavid du Colombier de1 = (DirEntry *) ((char *)de + DIR_REC_LEN(de->name_len));
1413dc5a79c1SDavid du Colombier de1->rec_len = de->rec_len - DIR_REC_LEN(de->name_len);
1414dc5a79c1SDavid du Colombier de->rec_len = DIR_REC_LEN(de->name_len);
1415dc5a79c1SDavid du Colombier de = de1;
1416dc5a79c1SDavid du Colombier }
1417dc5a79c1SDavid du Colombier de->inode = inr;
1418dc5a79c1SDavid du Colombier de->name_len = namelen;
1419dc5a79c1SDavid du Colombier memcpy(de->name, name, namelen);
1420dc5a79c1SDavid du Colombier dirtybuf(buf);
1421dc5a79c1SDavid du Colombier putbuf(buf);
1422dc5a79c1SDavid du Colombier inode->i_mtime = inode->i_ctime = time(0);
1423dc5a79c1SDavid du Colombier dirtybuf(ibuf);
1424dc5a79c1SDavid du Colombier putbuf(ibuf);
1425dc5a79c1SDavid du Colombier return 0;
1426dc5a79c1SDavid du Colombier }
1427dc5a79c1SDavid du Colombier de = (DirEntry *)((char *)de + de->rec_len);
1428dc5a79c1SDavid du Colombier }
1429b85a8364SDavid du Colombier /* not reached */
1430dc5a79c1SDavid du Colombier }
1431dc5a79c1SDavid du Colombier int
unlink(Xfile * file)1432dc5a79c1SDavid du Colombier unlink( Xfile *file )
1433dc5a79c1SDavid du Colombier {
1434dc5a79c1SDavid du Colombier Xfs *xf = file->xf;
1435dc5a79c1SDavid du Colombier Inode *dir;
1436dc5a79c1SDavid du Colombier int bg, b;
1437dc5a79c1SDavid du Colombier Inode *inode;
1438dc5a79c1SDavid du Colombier Iobuf *buf, *ibuf;
1439dc5a79c1SDavid du Colombier Ext2 ed, es, eb;
1440dc5a79c1SDavid du Colombier
1441dc5a79c1SDavid du Colombier if( S_ISDIR(getmode(file)) && !empty_dir(file) ){
1442dc5a79c1SDavid du Colombier chat("non empty directory...");
1443dc5a79c1SDavid du Colombier errno = Eperm;
1444dc5a79c1SDavid du Colombier return -1;
1445dc5a79c1SDavid du Colombier }
1446dc5a79c1SDavid du Colombier
1447dc5a79c1SDavid du Colombier es = getext2(xf, EXT2_SUPER, 0);
1448dc5a79c1SDavid du Colombier
1449dc5a79c1SDavid du Colombier /* get dir inode */
145022a127bbSDavid du Colombier if( file->pinbr >= es.u.sb->s_inodes_count ){
1451dc5a79c1SDavid du Colombier chat("inode number %d is too big...", file->pinbr);
1452dc5a79c1SDavid du Colombier putext2(es);
1453dc5a79c1SDavid du Colombier errno = Eintern;
1454dc5a79c1SDavid du Colombier return -1;
1455dc5a79c1SDavid du Colombier }
1456dc5a79c1SDavid du Colombier bg = (file->pinbr - 1) / xf->inodes_per_group;
1457dc5a79c1SDavid du Colombier if( bg >= xf->ngroups ){
1458dc5a79c1SDavid du Colombier chat("block group (%d) > groups count...", bg);
1459dc5a79c1SDavid du Colombier putext2(es);
1460dc5a79c1SDavid du Colombier errno = Eintern;
1461dc5a79c1SDavid du Colombier return -1;
1462dc5a79c1SDavid du Colombier }
1463dc5a79c1SDavid du Colombier ed = getext2(xf, EXT2_DESC, bg);
1464dc5a79c1SDavid du Colombier b = ed.u.gd->bg_inode_table +
1465dc5a79c1SDavid du Colombier (((file->pinbr-1) % xf->inodes_per_group) /
1466dc5a79c1SDavid du Colombier xf->inodes_per_block);
1467dc5a79c1SDavid du Colombier putext2(ed);
1468dc5a79c1SDavid du Colombier buf = getbuf(xf, b);
1469dc5a79c1SDavid du Colombier if( !buf ){
1470dc5a79c1SDavid du Colombier putext2(es);
1471dc5a79c1SDavid du Colombier return -1;
1472dc5a79c1SDavid du Colombier }
1473dc5a79c1SDavid du Colombier dir = ((struct Inode *) buf->iobuf) +
1474dc5a79c1SDavid du Colombier ((file->pinbr-1) % xf->inodes_per_block);
1475dc5a79c1SDavid du Colombier
1476dc5a79c1SDavid du Colombier /* Clean dir entry */
1477dc5a79c1SDavid du Colombier
1478dc5a79c1SDavid du Colombier if( delete_entry(xf, dir, file->inbr) < 0 ){
1479dc5a79c1SDavid du Colombier putbuf(buf);
1480dc5a79c1SDavid du Colombier putext2(es);
1481dc5a79c1SDavid du Colombier return -1;
1482dc5a79c1SDavid du Colombier }
1483dc5a79c1SDavid du Colombier if( S_ISDIR(getmode(file)) ){
1484dc5a79c1SDavid du Colombier dir->i_links_count--;
1485dc5a79c1SDavid du Colombier dirtybuf(buf);
1486dc5a79c1SDavid du Colombier }
1487dc5a79c1SDavid du Colombier putbuf(buf);
1488dc5a79c1SDavid du Colombier
1489dc5a79c1SDavid du Colombier /* clean blocks */
1490dc5a79c1SDavid du Colombier ibuf = getbuf(xf, file->bufaddr);
1491dc5a79c1SDavid du Colombier if( !ibuf ){
1492dc5a79c1SDavid du Colombier putext2(es);
1493dc5a79c1SDavid du Colombier return -1;
1494dc5a79c1SDavid du Colombier }
1495dc5a79c1SDavid du Colombier inode = ((Inode *)ibuf->iobuf) + file->bufoffset;
1496dc5a79c1SDavid du Colombier
1497dc5a79c1SDavid du Colombier if( !S_ISLNK(getmode(file)) ||
1498dc5a79c1SDavid du Colombier (S_ISLNK(getmode(file)) && (inode->i_size > EXT2_N_BLOCKS<<2)) )
1499dc5a79c1SDavid du Colombier if( free_block_inode(file) < 0 ){
1500dc5a79c1SDavid du Colombier chat("error while freeing blocks...");
1501dc5a79c1SDavid du Colombier putext2(es);
1502dc5a79c1SDavid du Colombier putbuf(ibuf);
1503dc5a79c1SDavid du Colombier return -1;
1504dc5a79c1SDavid du Colombier }
1505dc5a79c1SDavid du Colombier
1506dc5a79c1SDavid du Colombier
1507dc5a79c1SDavid du Colombier /* clean inode */
1508dc5a79c1SDavid du Colombier
1509dc5a79c1SDavid du Colombier bg = (file->inbr -1) / xf->inodes_per_group;
1510dc5a79c1SDavid du Colombier b = (file->inbr -1) % xf->inodes_per_group;
1511dc5a79c1SDavid du Colombier
1512dc5a79c1SDavid du Colombier eb = getext2(xf, EXT2_BINODE, bg);
1513dc5a79c1SDavid du Colombier clear_bit(b, eb.u.bmp);
1514dc5a79c1SDavid du Colombier dirtyext2(eb);
1515dc5a79c1SDavid du Colombier putext2(eb);
1516dc5a79c1SDavid du Colombier
1517dc5a79c1SDavid du Colombier inode->i_dtime = time(0);
1518dc5a79c1SDavid du Colombier inode->i_links_count--;
1519dc5a79c1SDavid du Colombier if( S_ISDIR(getmode(file)) )
1520dc5a79c1SDavid du Colombier inode->i_links_count = 0;
1521dc5a79c1SDavid du Colombier
1522dc5a79c1SDavid du Colombier es.u.sb->s_free_inodes_count++;
1523dc5a79c1SDavid du Colombier dirtyext2(es);
1524dc5a79c1SDavid du Colombier putext2(es);
1525dc5a79c1SDavid du Colombier
1526dc5a79c1SDavid du Colombier ed = getext2(xf, EXT2_DESC, bg);
1527dc5a79c1SDavid du Colombier ed.u.gd->bg_free_inodes_count++;
1528dc5a79c1SDavid du Colombier if( S_ISDIR(getmode(file)) )
1529dc5a79c1SDavid du Colombier ed.u.gd->bg_used_dirs_count--;
1530dc5a79c1SDavid du Colombier dirtyext2(ed);
1531dc5a79c1SDavid du Colombier putext2(ed);
1532dc5a79c1SDavid du Colombier
1533dc5a79c1SDavid du Colombier dirtybuf(ibuf);
1534dc5a79c1SDavid du Colombier putbuf(ibuf);
1535dc5a79c1SDavid du Colombier
1536dc5a79c1SDavid du Colombier return 1;
1537dc5a79c1SDavid du Colombier }
1538dc5a79c1SDavid du Colombier int
empty_dir(Xfile * dir)1539dc5a79c1SDavid du Colombier empty_dir(Xfile *dir)
1540dc5a79c1SDavid du Colombier {
1541dc5a79c1SDavid du Colombier Xfs *xf = dir->xf;
1542dc5a79c1SDavid du Colombier int nblock;
1543dc5a79c1SDavid du Colombier uint offset, i,count;
1544dc5a79c1SDavid du Colombier DirEntry *de;
1545dc5a79c1SDavid du Colombier Inode *inode;
1546dc5a79c1SDavid du Colombier Iobuf *buf, *ibuf;
1547dc5a79c1SDavid du Colombier
1548dc5a79c1SDavid du Colombier if( !S_ISDIR(getmode(dir)) )
1549dc5a79c1SDavid du Colombier return 0;
1550dc5a79c1SDavid du Colombier
1551dc5a79c1SDavid du Colombier ibuf = getbuf(xf, dir->bufaddr);
1552dc5a79c1SDavid du Colombier if( !ibuf )
1553dc5a79c1SDavid du Colombier return -1;
1554dc5a79c1SDavid du Colombier inode = ((Inode *)ibuf->iobuf) + dir->bufoffset;
1555dc5a79c1SDavid du Colombier nblock = (inode->i_blocks * 512) / xf->block_size;
1556dc5a79c1SDavid du Colombier
1557dc5a79c1SDavid du Colombier for(i=0, count=0 ; (i < nblock) && (i < EXT2_NDIR_BLOCKS) ; i++){
1558dc5a79c1SDavid du Colombier buf = getbuf(xf, inode->i_block[i]);
1559dc5a79c1SDavid du Colombier if( !buf ){
1560dc5a79c1SDavid du Colombier putbuf(ibuf);
1561dc5a79c1SDavid du Colombier return 0;
1562dc5a79c1SDavid du Colombier }
1563dc5a79c1SDavid du Colombier for(offset=0 ; offset < xf->block_size ; ){
1564dc5a79c1SDavid du Colombier de = (DirEntry *)(buf->iobuf + offset);
1565dc5a79c1SDavid du Colombier if(de->inode)
1566dc5a79c1SDavid du Colombier count++;
1567dc5a79c1SDavid du Colombier offset += de->rec_len;
1568dc5a79c1SDavid du Colombier }
1569dc5a79c1SDavid du Colombier putbuf(buf);
1570dc5a79c1SDavid du Colombier if( count > 2 ){
1571dc5a79c1SDavid du Colombier putbuf(ibuf);
1572dc5a79c1SDavid du Colombier return 0;
1573dc5a79c1SDavid du Colombier }
1574dc5a79c1SDavid du Colombier }
1575dc5a79c1SDavid du Colombier putbuf(ibuf);
1576dc5a79c1SDavid du Colombier return 1;
1577dc5a79c1SDavid du Colombier }
1578dc5a79c1SDavid du Colombier int
free_block_inode(Xfile * file)1579dc5a79c1SDavid du Colombier free_block_inode(Xfile *file)
1580dc5a79c1SDavid du Colombier {
1581dc5a79c1SDavid du Colombier Xfs *xf = file->xf;
1582dc5a79c1SDavid du Colombier int i, j, k;
1583dc5a79c1SDavid du Colombier ulong b, *y, *z;
1584dc5a79c1SDavid du Colombier uint *x;
1585dc5a79c1SDavid du Colombier int naddr;
1586dc5a79c1SDavid du Colombier Inode *inode;
1587dc5a79c1SDavid du Colombier Iobuf *buf, *buf1, *buf2, *ibuf;
1588dc5a79c1SDavid du Colombier
1589dc5a79c1SDavid du Colombier ibuf = getbuf(xf, file->bufaddr);
1590dc5a79c1SDavid du Colombier if( !ibuf )
1591dc5a79c1SDavid du Colombier return -1;
1592dc5a79c1SDavid du Colombier inode = ((Inode *)ibuf->iobuf) + file->bufoffset;
1593dc5a79c1SDavid du Colombier
1594dc5a79c1SDavid du Colombier for(i=0 ; i < EXT2_IND_BLOCK ; i++){
1595dc5a79c1SDavid du Colombier x = inode->i_block + i;
1596dc5a79c1SDavid du Colombier if( *x == 0 ){ putbuf(ibuf); return 0; }
1597dc5a79c1SDavid du Colombier free_block(xf, *x);
1598dc5a79c1SDavid du Colombier }
1599dc5a79c1SDavid du Colombier naddr = xf->addr_per_block;
1600dc5a79c1SDavid du Colombier
1601dc5a79c1SDavid du Colombier /* indirect blocks */
1602dc5a79c1SDavid du Colombier
1603dc5a79c1SDavid du Colombier if( (b=inode->i_block[EXT2_IND_BLOCK]) ){
1604dc5a79c1SDavid du Colombier buf = getbuf(xf, b);
1605dc5a79c1SDavid du Colombier if( !buf ){ putbuf(ibuf); return -1; }
1606dc5a79c1SDavid du Colombier for(i=0 ; i < naddr ; i++){
1607dc5a79c1SDavid du Colombier x = ((uint *)buf->iobuf) + i;
1608dc5a79c1SDavid du Colombier if( *x == 0 ) break;
1609dc5a79c1SDavid du Colombier free_block(xf, *x);
1610dc5a79c1SDavid du Colombier }
1611dc5a79c1SDavid du Colombier free_block(xf, b);
1612dc5a79c1SDavid du Colombier putbuf(buf);
1613dc5a79c1SDavid du Colombier }
1614dc5a79c1SDavid du Colombier
1615dc5a79c1SDavid du Colombier /* double indirect block */
1616dc5a79c1SDavid du Colombier
1617dc5a79c1SDavid du Colombier if( (b=inode->i_block[EXT2_DIND_BLOCK]) ){
1618dc5a79c1SDavid du Colombier buf = getbuf(xf, b);
1619dc5a79c1SDavid du Colombier if( !buf ){ putbuf(ibuf); return -1; }
1620dc5a79c1SDavid du Colombier for(i=0 ; i < naddr ; i++){
1621dc5a79c1SDavid du Colombier x = ((uint *)buf->iobuf) + i;
1622dc5a79c1SDavid du Colombier if( *x== 0 ) break;
1623dc5a79c1SDavid du Colombier buf1 = getbuf(xf, *x);
1624dc5a79c1SDavid du Colombier if( !buf1 ){ putbuf(buf); putbuf(ibuf); return -1; }
1625dc5a79c1SDavid du Colombier for(j=0 ; j < naddr ; j++){
1626dc5a79c1SDavid du Colombier y = ((ulong *)buf1->iobuf) + j;
1627dc5a79c1SDavid du Colombier if( *y == 0 ) break;
1628dc5a79c1SDavid du Colombier free_block(xf, *y);
1629dc5a79c1SDavid du Colombier }
1630dc5a79c1SDavid du Colombier free_block(xf, *x);
1631dc5a79c1SDavid du Colombier putbuf(buf1);
1632dc5a79c1SDavid du Colombier }
1633dc5a79c1SDavid du Colombier free_block(xf, b);
1634dc5a79c1SDavid du Colombier putbuf(buf);
1635dc5a79c1SDavid du Colombier }
1636dc5a79c1SDavid du Colombier
1637dc5a79c1SDavid du Colombier /* triple indirect block */
1638dc5a79c1SDavid du Colombier
1639dc5a79c1SDavid du Colombier if( (b=inode->i_block[EXT2_TIND_BLOCK]) ){
1640dc5a79c1SDavid du Colombier buf = getbuf(xf, b);
1641dc5a79c1SDavid du Colombier if( !buf ){ putbuf(ibuf); return -1; }
1642dc5a79c1SDavid du Colombier for(i=0 ; i < naddr ; i++){
1643dc5a79c1SDavid du Colombier x = ((uint *)buf->iobuf) + i;
1644dc5a79c1SDavid du Colombier if( *x == 0 ) break;
1645dc5a79c1SDavid du Colombier buf1 = getbuf(xf, *x);
1646dc5a79c1SDavid du Colombier if( !buf1 ){ putbuf(buf); putbuf(ibuf); return -1; }
1647dc5a79c1SDavid du Colombier for(j=0 ; j < naddr ; j++){
1648dc5a79c1SDavid du Colombier y = ((ulong *)buf1->iobuf) + j;
1649dc5a79c1SDavid du Colombier if( *y == 0 ) break;
1650dc5a79c1SDavid du Colombier buf2 = getbuf(xf, *y);
1651dc5a79c1SDavid du Colombier if( !buf2 ){ putbuf(buf); putbuf(buf1); putbuf(ibuf); return -1; }
1652dc5a79c1SDavid du Colombier for(k=0 ; k < naddr ; k++){
1653dc5a79c1SDavid du Colombier z = ((ulong *)buf2->iobuf) + k;
1654dc5a79c1SDavid du Colombier if( *z == 0 ) break;
1655dc5a79c1SDavid du Colombier free_block(xf, *z);
1656dc5a79c1SDavid du Colombier }
1657dc5a79c1SDavid du Colombier free_block(xf, *y);
1658dc5a79c1SDavid du Colombier putbuf(buf2);
1659dc5a79c1SDavid du Colombier }
1660dc5a79c1SDavid du Colombier free_block(xf, *x);
1661dc5a79c1SDavid du Colombier putbuf(buf1);
1662dc5a79c1SDavid du Colombier }
1663dc5a79c1SDavid du Colombier free_block(xf, b);
1664dc5a79c1SDavid du Colombier putbuf(buf);
1665dc5a79c1SDavid du Colombier }
1666dc5a79c1SDavid du Colombier
1667dc5a79c1SDavid du Colombier putbuf(ibuf);
1668dc5a79c1SDavid du Colombier return 0;
1669dc5a79c1SDavid du Colombier }
free_block(Xfs * xf,ulong block)1670dc5a79c1SDavid du Colombier void free_block( Xfs *xf, ulong block )
1671dc5a79c1SDavid du Colombier {
1672dc5a79c1SDavid du Colombier ulong bg;
1673dc5a79c1SDavid du Colombier Ext2 ed, es, eb;
1674dc5a79c1SDavid du Colombier
1675dc5a79c1SDavid du Colombier es = getext2(xf, EXT2_SUPER, 0);
1676dc5a79c1SDavid du Colombier
1677dc5a79c1SDavid du Colombier bg = (block - es.u.sb->s_first_data_block) / xf->blocks_per_group;
1678dc5a79c1SDavid du Colombier block = (block - es.u.sb->s_first_data_block) % xf->blocks_per_group;
1679dc5a79c1SDavid du Colombier
1680dc5a79c1SDavid du Colombier eb = getext2(xf, EXT2_BBLOCK, bg);
1681dc5a79c1SDavid du Colombier clear_bit(block, eb.u.bmp);
1682dc5a79c1SDavid du Colombier dirtyext2(eb);
1683dc5a79c1SDavid du Colombier putext2(eb);
1684dc5a79c1SDavid du Colombier
1685dc5a79c1SDavid du Colombier es.u.sb->s_free_blocks_count++;
1686dc5a79c1SDavid du Colombier dirtyext2(es);
1687dc5a79c1SDavid du Colombier putext2(es);
1688dc5a79c1SDavid du Colombier
1689dc5a79c1SDavid du Colombier ed = getext2(xf, EXT2_DESC, bg);
1690dc5a79c1SDavid du Colombier ed.u.gd->bg_free_blocks_count++;
1691dc5a79c1SDavid du Colombier dirtyext2(ed);
1692dc5a79c1SDavid du Colombier putext2(ed);
1693dc5a79c1SDavid du Colombier
1694dc5a79c1SDavid du Colombier }
1695dc5a79c1SDavid du Colombier int
delete_entry(Xfs * xf,Inode * inode,int inbr)1696dc5a79c1SDavid du Colombier delete_entry(Xfs *xf, Inode *inode, int inbr)
1697dc5a79c1SDavid du Colombier {
1698dc5a79c1SDavid du Colombier int nblock = (inode->i_blocks * 512) / xf->block_size;
1699dc5a79c1SDavid du Colombier uint offset, i;
1700dc5a79c1SDavid du Colombier DirEntry *de, *pde;
1701dc5a79c1SDavid du Colombier Iobuf *buf;
1702dc5a79c1SDavid du Colombier
1703dc5a79c1SDavid du Colombier if( !S_ISDIR(inode->i_mode) )
1704dc5a79c1SDavid du Colombier return -1;
1705dc5a79c1SDavid du Colombier
1706dc5a79c1SDavid du Colombier for(i=0 ; (i < nblock) && (i < EXT2_NDIR_BLOCKS) ; i++){
1707dc5a79c1SDavid du Colombier buf = getbuf(xf, inode->i_block[i]);
1708dc5a79c1SDavid du Colombier if( !buf )
1709dc5a79c1SDavid du Colombier return -1;
1710dc5a79c1SDavid du Colombier pde = 0;
1711dc5a79c1SDavid du Colombier for(offset=0 ; offset < xf->block_size ; ){
1712dc5a79c1SDavid du Colombier de = (DirEntry *)(buf->iobuf + offset);
1713dc5a79c1SDavid du Colombier if( de->inode == inbr ){
1714dc5a79c1SDavid du Colombier if( pde )
1715dc5a79c1SDavid du Colombier pde->rec_len += de->rec_len;
1716dc5a79c1SDavid du Colombier de->inode = 0;
1717dc5a79c1SDavid du Colombier dirtybuf(buf);
1718dc5a79c1SDavid du Colombier putbuf(buf);
1719dc5a79c1SDavid du Colombier return 1;
1720dc5a79c1SDavid du Colombier }
1721dc5a79c1SDavid du Colombier offset += de->rec_len;
1722dc5a79c1SDavid du Colombier pde = de;
1723dc5a79c1SDavid du Colombier }
1724dc5a79c1SDavid du Colombier putbuf(buf);
1725dc5a79c1SDavid du Colombier
1726dc5a79c1SDavid du Colombier }
1727dc5a79c1SDavid du Colombier errno = Enonexist;
1728dc5a79c1SDavid du Colombier return -1;
1729dc5a79c1SDavid du Colombier }
1730dc5a79c1SDavid du Colombier int
truncfile(Xfile * f)1731dc5a79c1SDavid du Colombier truncfile(Xfile *f)
1732dc5a79c1SDavid du Colombier {
1733dc5a79c1SDavid du Colombier Inode *inode;
1734dc5a79c1SDavid du Colombier Iobuf *ibuf;
1735dc5a79c1SDavid du Colombier chat("trunc(fid=%d) ...", f->fid);
1736dc5a79c1SDavid du Colombier ibuf = getbuf(f->xf, f->bufaddr);
1737dc5a79c1SDavid du Colombier if( !ibuf )
1738dc5a79c1SDavid du Colombier return -1;
1739dc5a79c1SDavid du Colombier inode = ((Inode *)ibuf->iobuf) + f->bufoffset;
1740dc5a79c1SDavid du Colombier
1741dc5a79c1SDavid du Colombier if( free_block_inode(f) < 0 ){
1742dc5a79c1SDavid du Colombier chat("error while freeing blocks...");
1743dc5a79c1SDavid du Colombier putbuf(ibuf);
1744dc5a79c1SDavid du Colombier return -1;
1745dc5a79c1SDavid du Colombier }
1746dc5a79c1SDavid du Colombier inode->i_atime = inode->i_mtime = time(0);
1747dc5a79c1SDavid du Colombier inode->i_blocks = 0;
1748dc5a79c1SDavid du Colombier inode->i_size = 0;
1749dc5a79c1SDavid du Colombier memset(inode->i_block, 0, EXT2_N_BLOCKS*sizeof(ulong));
1750dc5a79c1SDavid du Colombier dirtybuf(ibuf);
1751dc5a79c1SDavid du Colombier putbuf(ibuf);
1752dc5a79c1SDavid du Colombier chat("trunc ok...");
1753dc5a79c1SDavid du Colombier return 0;
1754dc5a79c1SDavid du Colombier }
1755dc5a79c1SDavid du Colombier long
getmode(Xfile * f)1756dc5a79c1SDavid du Colombier getmode(Xfile *f)
1757dc5a79c1SDavid du Colombier {
1758dc5a79c1SDavid du Colombier Iobuf *ibuf;
1759dc5a79c1SDavid du Colombier long mode;
1760dc5a79c1SDavid du Colombier
1761dc5a79c1SDavid du Colombier ibuf = getbuf(f->xf, f->bufaddr);
1762dc5a79c1SDavid du Colombier if( !ibuf )
1763dc5a79c1SDavid du Colombier return -1;
1764dc5a79c1SDavid du Colombier mode = (((Inode *)ibuf->iobuf) + f->bufoffset)->i_mode;
1765dc5a79c1SDavid du Colombier putbuf(ibuf);
1766dc5a79c1SDavid du Colombier return mode;
1767dc5a79c1SDavid du Colombier }
1768dc5a79c1SDavid du Colombier void
CleanSuper(Xfs * xf)1769dc5a79c1SDavid du Colombier CleanSuper(Xfs *xf)
1770dc5a79c1SDavid du Colombier {
1771dc5a79c1SDavid du Colombier Ext2 es;
1772dc5a79c1SDavid du Colombier
1773dc5a79c1SDavid du Colombier es = getext2(xf, EXT2_SUPER, 0);
1774dc5a79c1SDavid du Colombier es.u.sb->s_state = EXT2_VALID_FS;
1775dc5a79c1SDavid du Colombier dirtyext2(es);
1776dc5a79c1SDavid du Colombier putext2(es);
1777dc5a79c1SDavid du Colombier }
1778dc5a79c1SDavid du Colombier int
test_bit(int i,void * data)1779dc5a79c1SDavid du Colombier test_bit(int i, void *data)
1780dc5a79c1SDavid du Colombier {
1781dc5a79c1SDavid du Colombier char *pt = (char *)data;
1782dc5a79c1SDavid du Colombier
1783dc5a79c1SDavid du Colombier return pt[i>>3] & (0x01 << (i&7));
1784dc5a79c1SDavid du Colombier }
1785dc5a79c1SDavid du Colombier
1786dc5a79c1SDavid du Colombier int
set_bit(int i,void * data)1787dc5a79c1SDavid du Colombier set_bit(int i, void *data)
1788dc5a79c1SDavid du Colombier {
1789dc5a79c1SDavid du Colombier char *pt;
1790dc5a79c1SDavid du Colombier
1791dc5a79c1SDavid du Colombier if( test_bit(i, data) )
1792dc5a79c1SDavid du Colombier return 1; /* bit already set !!! */
1793dc5a79c1SDavid du Colombier
1794dc5a79c1SDavid du Colombier pt = (char *)data;
1795dc5a79c1SDavid du Colombier pt[i>>3] |= (0x01 << (i&7));
1796dc5a79c1SDavid du Colombier
1797dc5a79c1SDavid du Colombier return 0;
1798dc5a79c1SDavid du Colombier }
1799dc5a79c1SDavid du Colombier
1800dc5a79c1SDavid du Colombier int
clear_bit(int i,void * data)1801dc5a79c1SDavid du Colombier clear_bit(int i, void *data)
1802dc5a79c1SDavid du Colombier {
1803dc5a79c1SDavid du Colombier char *pt;
1804dc5a79c1SDavid du Colombier
1805dc5a79c1SDavid du Colombier if( !test_bit(i, data) )
1806dc5a79c1SDavid du Colombier return 1; /* bit already clear !!! */
1807dc5a79c1SDavid du Colombier
1808dc5a79c1SDavid du Colombier pt = (char *)data;
1809dc5a79c1SDavid du Colombier pt[i>>3] &= ~(0x01 << (i&7));
1810dc5a79c1SDavid du Colombier
1811dc5a79c1SDavid du Colombier return 0;
1812dc5a79c1SDavid du Colombier }
1813dc5a79c1SDavid du Colombier void *
memscan(void * data,int c,int count)1814dc5a79c1SDavid du Colombier memscan( void *data, int c, int count )
1815dc5a79c1SDavid du Colombier {
1816dc5a79c1SDavid du Colombier char *pt = (char *)data;
1817dc5a79c1SDavid du Colombier
1818dc5a79c1SDavid du Colombier while( count ){
1819dc5a79c1SDavid du Colombier if( *pt == c )
1820dc5a79c1SDavid du Colombier return (void *)pt;
1821dc5a79c1SDavid du Colombier count--;
1822dc5a79c1SDavid du Colombier pt++;
1823dc5a79c1SDavid du Colombier }
1824dc5a79c1SDavid du Colombier return (void *)pt;
1825dc5a79c1SDavid du Colombier }
1826dc5a79c1SDavid du Colombier
1827dc5a79c1SDavid du Colombier int
find_first_zero_bit(void * data,int count)1828dc5a79c1SDavid du Colombier find_first_zero_bit( void *data, int count /* in byte */)
1829dc5a79c1SDavid du Colombier {
1830dc5a79c1SDavid du Colombier char *pt = (char *)data;
1831dc5a79c1SDavid du Colombier int n, i;
1832dc5a79c1SDavid du Colombier
1833dc5a79c1SDavid du Colombier n = 0;
1834dc5a79c1SDavid du Colombier
1835dc5a79c1SDavid du Colombier while( n < count ){
1836dc5a79c1SDavid du Colombier for(i=0 ; i < 8 ; i++)
1837dc5a79c1SDavid du Colombier if( !(*pt & (0x01 << (i&7))) )
1838dc5a79c1SDavid du Colombier return (n<<3) + i;
1839dc5a79c1SDavid du Colombier n++; pt++;
1840dc5a79c1SDavid du Colombier }
1841dc5a79c1SDavid du Colombier return n << 3;
1842dc5a79c1SDavid du Colombier }
1843dc5a79c1SDavid du Colombier
1844dc5a79c1SDavid du Colombier int
find_next_zero_bit(void * data,int count,int where)1845dc5a79c1SDavid du Colombier find_next_zero_bit( void *data, int count /* in byte */, int where)
1846dc5a79c1SDavid du Colombier {
1847dc5a79c1SDavid du Colombier char *pt = (((char *)data) + (where >> 3));
1848dc5a79c1SDavid du Colombier int n, i;
1849dc5a79c1SDavid du Colombier
1850dc5a79c1SDavid du Colombier n = where >> 3;
1851dc5a79c1SDavid du Colombier i = where & 7;
1852dc5a79c1SDavid du Colombier
1853dc5a79c1SDavid du Colombier while( n < count ){
1854dc5a79c1SDavid du Colombier for(; i < 8 ; i++)
1855dc5a79c1SDavid du Colombier if( !(*pt & (0x01 << (i&7))) )
1856dc5a79c1SDavid du Colombier return (n<<3) + i;
1857dc5a79c1SDavid du Colombier n++; pt++; i=0;
1858dc5a79c1SDavid du Colombier }
1859dc5a79c1SDavid du Colombier return n << 3;
1860dc5a79c1SDavid du Colombier }
1861dc5a79c1SDavid du Colombier int
ffz(int x)1862dc5a79c1SDavid du Colombier ffz( int x )
1863dc5a79c1SDavid du Colombier {
1864dc5a79c1SDavid du Colombier int c = 0;
1865dc5a79c1SDavid du Colombier while( x&1 ){
1866dc5a79c1SDavid du Colombier c++;
1867dc5a79c1SDavid du Colombier x >>= 1;
1868dc5a79c1SDavid du Colombier }
1869dc5a79c1SDavid du Colombier return c;
1870dc5a79c1SDavid du Colombier }
1871