Blame


1 0c98da8b 2005-07-13 devnull #include <u.h>
2 0c98da8b 2005-07-13 devnull #include <libc.h>
3 0c98da8b 2005-07-13 devnull #include <thread.h>
4 0c98da8b 2005-07-13 devnull #include <sunrpc.h>
5 0c98da8b 2005-07-13 devnull #include <nfs3.h>
6 0c98da8b 2005-07-13 devnull #include <diskfs.h>
7 0c98da8b 2005-07-13 devnull #include "ext2.h"
8 0c98da8b 2005-07-13 devnull
9 e77222a4 2006-05-04 devnull #define debug 0
10 0c98da8b 2005-07-13 devnull
11 0c98da8b 2005-07-13 devnull static int ext2sync(Fsys*);
12 0c98da8b 2005-07-13 devnull static void ext2close(Fsys*);
13 0c98da8b 2005-07-13 devnull static Block* ext2blockread(Fsys*, u64int);
14 0c98da8b 2005-07-13 devnull
15 0c98da8b 2005-07-13 devnull static Nfs3Status ext2root(Fsys*, Nfs3Handle*);
16 0c98da8b 2005-07-13 devnull static Nfs3Status ext2getattr(Fsys*, SunAuthUnix *au, Nfs3Handle*, Nfs3Attr*);
17 0c98da8b 2005-07-13 devnull static Nfs3Status ext2lookup(Fsys*, SunAuthUnix *au, Nfs3Handle*, char*, Nfs3Handle*);
18 0c98da8b 2005-07-13 devnull static Nfs3Status ext2readfile(Fsys*, SunAuthUnix *au, Nfs3Handle*, u32int, u64int, uchar**, u32int*, u1int*);
19 0c98da8b 2005-07-13 devnull static Nfs3Status ext2readlink(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, char **link);
20 0c98da8b 2005-07-13 devnull static Nfs3Status ext2readdir(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int, u64int, uchar**, u32int*, u1int*);
21 0c98da8b 2005-07-13 devnull static Nfs3Status ext2access(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int want, u32int *got, Nfs3Attr *attr);
22 0c98da8b 2005-07-13 devnull
23 0c98da8b 2005-07-13 devnull Fsys*
24 0c98da8b 2005-07-13 devnull fsysopenext2(Disk *disk)
25 0c98da8b 2005-07-13 devnull {
26 0c98da8b 2005-07-13 devnull Ext2 *fs;
27 0c98da8b 2005-07-13 devnull Fsys *fsys;
28 0c98da8b 2005-07-13 devnull
29 0c98da8b 2005-07-13 devnull fsys = emalloc(sizeof(Fsys));
30 0c98da8b 2005-07-13 devnull fs = emalloc(sizeof(Ext2));
31 0c98da8b 2005-07-13 devnull fs->disk = disk;
32 0c98da8b 2005-07-13 devnull fsys->priv = fs;
33 0c98da8b 2005-07-13 devnull fs->fsys = fsys;
34 0c98da8b 2005-07-13 devnull fsys->type = "ext2";
35 0c98da8b 2005-07-13 devnull fsys->_readblock = ext2blockread;
36 0c98da8b 2005-07-13 devnull fsys->_sync = ext2sync;
37 0c98da8b 2005-07-13 devnull fsys->_root = ext2root;
38 0c98da8b 2005-07-13 devnull fsys->_getattr = ext2getattr;
39 0c98da8b 2005-07-13 devnull fsys->_access = ext2access;
40 0c98da8b 2005-07-13 devnull fsys->_lookup = ext2lookup;
41 0c98da8b 2005-07-13 devnull fsys->_readfile = ext2readfile;
42 0c98da8b 2005-07-13 devnull fsys->_readlink = ext2readlink;
43 0c98da8b 2005-07-13 devnull fsys->_readdir = ext2readdir;
44 a51dffd3 2006-11-20 devnull fsys->_close = ext2close;
45 0c98da8b 2005-07-13 devnull
46 0c98da8b 2005-07-13 devnull if(ext2sync(fsys) < 0)
47 0c98da8b 2005-07-13 devnull goto error;
48 0c98da8b 2005-07-13 devnull
49 0c98da8b 2005-07-13 devnull return fsys;
50 0c98da8b 2005-07-13 devnull
51 0c98da8b 2005-07-13 devnull error:
52 0c98da8b 2005-07-13 devnull ext2close(fsys);
53 0c98da8b 2005-07-13 devnull return nil;
54 0c98da8b 2005-07-13 devnull }
55 0c98da8b 2005-07-13 devnull
56 0c98da8b 2005-07-13 devnull static void
57 0c98da8b 2005-07-13 devnull ext2close(Fsys *fsys)
58 0c98da8b 2005-07-13 devnull {
59 0c98da8b 2005-07-13 devnull Ext2 *fs;
60 0c98da8b 2005-07-13 devnull
61 0c98da8b 2005-07-13 devnull fs = fsys->priv;
62 0c98da8b 2005-07-13 devnull free(fs);
63 0c98da8b 2005-07-13 devnull free(fsys);
64 0c98da8b 2005-07-13 devnull }
65 0c98da8b 2005-07-13 devnull
66 0c98da8b 2005-07-13 devnull static Group*
67 0c98da8b 2005-07-13 devnull ext2group(Ext2 *fs, u32int i, Block **pb)
68 0c98da8b 2005-07-13 devnull {
69 0c98da8b 2005-07-13 devnull Block *b;
70 0c98da8b 2005-07-13 devnull u64int addr;
71 0c98da8b 2005-07-13 devnull Group *g;
72 0c98da8b 2005-07-13 devnull
73 0c98da8b 2005-07-13 devnull if(i >= fs->ngroup)
74 0c98da8b 2005-07-13 devnull return nil;
75 0c98da8b 2005-07-13 devnull
76 0c98da8b 2005-07-13 devnull addr = fs->groupaddr + i/fs->descperblock;
77 0c98da8b 2005-07-13 devnull b = diskread(fs->disk, fs->blocksize, addr*fs->blocksize);
78 0c98da8b 2005-07-13 devnull if(b == nil)
79 0c98da8b 2005-07-13 devnull return nil;
80 0c98da8b 2005-07-13 devnull g = (Group*)(b->data+i%fs->descperblock*GroupSize);
81 0c98da8b 2005-07-13 devnull *pb = b;
82 0c98da8b 2005-07-13 devnull return g;
83 0c98da8b 2005-07-13 devnull }
84 0c98da8b 2005-07-13 devnull
85 0c98da8b 2005-07-13 devnull static Block*
86 0c98da8b 2005-07-13 devnull ext2blockread(Fsys *fsys, u64int vbno)
87 0c98da8b 2005-07-13 devnull {
88 0c98da8b 2005-07-13 devnull Block *bitb;
89 0c98da8b 2005-07-13 devnull Group *g;
90 0c98da8b 2005-07-13 devnull Block *gb;
91 0c98da8b 2005-07-13 devnull uchar *bits;
92 c1a4592d 2006-06-15 devnull u32int bno, boff, bitblock;
93 c1a4592d 2006-06-15 devnull u64int bitpos;
94 0c98da8b 2005-07-13 devnull Ext2 *fs;
95 0c98da8b 2005-07-13 devnull
96 0c98da8b 2005-07-13 devnull fs = fsys->priv;
97 0c98da8b 2005-07-13 devnull if(vbno >= fs->nblock)
98 0c98da8b 2005-07-13 devnull return nil;
99 0c98da8b 2005-07-13 devnull bno = vbno;
100 0c98da8b 2005-07-13 devnull if(bno != vbno)
101 0c98da8b 2005-07-13 devnull return nil;
102 0c98da8b 2005-07-13 devnull
103 0c98da8b 2005-07-13 devnull /*
104 0c98da8b 2005-07-13 devnull if(bno < fs->firstblock)
105 0c98da8b 2005-07-13 devnull return diskread(fs->disk, fs->blocksize, (u64int)bno*fs->blocksize);
106 0c98da8b 2005-07-13 devnull */
107 0c98da8b 2005-07-13 devnull if(bno < fs->firstblock)
108 0c98da8b 2005-07-13 devnull return nil;
109 0c98da8b 2005-07-13 devnull
110 0c98da8b 2005-07-13 devnull bno -= fs->firstblock;
111 0c98da8b 2005-07-13 devnull if((g = ext2group(fs, bno/fs->blockspergroup, &gb)) == nil){
112 0c98da8b 2005-07-13 devnull if(debug)
113 0c98da8b 2005-07-13 devnull fprint(2, "loading group: %r...");
114 0c98da8b 2005-07-13 devnull return nil;
115 0c98da8b 2005-07-13 devnull }
116 e77222a4 2006-05-04 devnull /*
117 c1a4592d 2006-06-15 devnull if(debug)
118 c1a4592d 2006-06-15 devnull fprint(2, "ext2 group %d: bitblock=%ud inodebitblock=%ud inodeaddr=%ud freeblocks=%ud freeinodes=%ud useddirs=%ud\n",
119 c1a4592d 2006-06-15 devnull (int)(bno/fs->blockspergroup),
120 c1a4592d 2006-06-15 devnull g->bitblock,
121 c1a4592d 2006-06-15 devnull g->inodebitblock,
122 c1a4592d 2006-06-15 devnull g->inodeaddr,
123 c1a4592d 2006-06-15 devnull g->freeblockscount,
124 c1a4592d 2006-06-15 devnull g->freeinodescount,
125 c1a4592d 2006-06-15 devnull g->useddirscount);
126 e77222a4 2006-05-04 devnull if(debug)
127 e77222a4 2006-05-04 devnull fprint(2, "group %d bitblock=%d...", bno/fs->blockspergroup, g->bitblock);
128 e77222a4 2006-05-04 devnull */
129 c1a4592d 2006-06-15 devnull bitblock = g->bitblock;
130 c1a4592d 2006-06-15 devnull bitpos = (u64int)bitblock*fs->blocksize;
131 9bbcb80d 2006-06-15 devnull blockput(gb);
132 0c98da8b 2005-07-13 devnull
133 9bbcb80d 2006-06-15 devnull if((bitb = diskread(fs->disk, fs->blocksize, bitpos)) == nil){
134 0c98da8b 2005-07-13 devnull if(debug)
135 0c98da8b 2005-07-13 devnull fprint(2, "loading bitblock: %r...");
136 0c98da8b 2005-07-13 devnull return nil;
137 0c98da8b 2005-07-13 devnull }
138 0c98da8b 2005-07-13 devnull bits = bitb->data;
139 0c98da8b 2005-07-13 devnull boff = bno%fs->blockspergroup;
140 0c98da8b 2005-07-13 devnull if((bits[boff>>3] & (1<<(boff&7))) == 0){
141 0c98da8b 2005-07-13 devnull if(debug)
142 c1a4592d 2006-06-15 devnull fprint(2, "block %d not allocated in group %d: bitblock %d/%lld bits[%d] = %#x\n",
143 c1a4592d 2006-06-15 devnull boff, bno/fs->blockspergroup,
144 c1a4592d 2006-06-15 devnull (int)bitblock,
145 c1a4592d 2006-06-15 devnull bitpos,
146 c1a4592d 2006-06-15 devnull boff>>3,
147 c1a4592d 2006-06-15 devnull bits[boff>>3]);
148 0c98da8b 2005-07-13 devnull blockput(bitb);
149 0c98da8b 2005-07-13 devnull return nil;
150 0c98da8b 2005-07-13 devnull }
151 9bbcb80d 2006-06-15 devnull blockput(bitb);
152 0c98da8b 2005-07-13 devnull
153 0c98da8b 2005-07-13 devnull bno += fs->firstblock;
154 0c98da8b 2005-07-13 devnull return diskread(fs->disk, fs->blocksize, (u64int)bno*fs->blocksize);
155 0c98da8b 2005-07-13 devnull }
156 0c98da8b 2005-07-13 devnull
157 0c98da8b 2005-07-13 devnull static Block*
158 0c98da8b 2005-07-13 devnull ext2datablock(Ext2 *fs, u32int bno, int size)
159 0c98da8b 2005-07-13 devnull {
160 3330e5bf 2005-10-29 devnull USED(size);
161 e77222a4 2006-05-04 devnull return ext2blockread(fs->fsys, bno);
162 0c98da8b 2005-07-13 devnull }
163 0c98da8b 2005-07-13 devnull
164 0c98da8b 2005-07-13 devnull static Block*
165 0c98da8b 2005-07-13 devnull ext2fileblock(Ext2 *fs, Inode *ino, u32int bno, int size)
166 0c98da8b 2005-07-13 devnull {
167 0c98da8b 2005-07-13 devnull int ppb;
168 0c98da8b 2005-07-13 devnull Block *b;
169 0c98da8b 2005-07-13 devnull u32int *a;
170 b109049f 2007-03-25 devnull u32int obno, pbno;
171 0c98da8b 2005-07-13 devnull
172 0c98da8b 2005-07-13 devnull obno = bno;
173 0c98da8b 2005-07-13 devnull if(bno < NDIRBLOCKS){
174 0c98da8b 2005-07-13 devnull if(debug)
175 0c98da8b 2005-07-13 devnull fprint(2, "fileblock %d -> %d...",
176 0c98da8b 2005-07-13 devnull bno, ino->block[bno]);
177 0c98da8b 2005-07-13 devnull return ext2datablock(fs, ino->block[bno], size);
178 0c98da8b 2005-07-13 devnull }
179 0c98da8b 2005-07-13 devnull bno -= NDIRBLOCKS;
180 0c98da8b 2005-07-13 devnull ppb = fs->blocksize/4;
181 0c98da8b 2005-07-13 devnull
182 0c98da8b 2005-07-13 devnull /* one indirect */
183 0c98da8b 2005-07-13 devnull if(bno < ppb){
184 0c98da8b 2005-07-13 devnull b = ext2datablock(fs, ino->block[INDBLOCK], fs->blocksize);
185 0c98da8b 2005-07-13 devnull if(b == nil)
186 0c98da8b 2005-07-13 devnull return nil;
187 0c98da8b 2005-07-13 devnull a = (u32int*)b->data;
188 b109049f 2007-03-25 devnull bno = a[bno];
189 0c98da8b 2005-07-13 devnull blockput(b);
190 0c98da8b 2005-07-13 devnull return ext2datablock(fs, bno, size);
191 0c98da8b 2005-07-13 devnull }
192 0c98da8b 2005-07-13 devnull bno -= ppb;
193 0c98da8b 2005-07-13 devnull
194 0c98da8b 2005-07-13 devnull /* one double indirect */
195 0c98da8b 2005-07-13 devnull if(bno < ppb*ppb){
196 0c98da8b 2005-07-13 devnull b = ext2datablock(fs, ino->block[DINDBLOCK], fs->blocksize);
197 0c98da8b 2005-07-13 devnull if(b == nil)
198 0c98da8b 2005-07-13 devnull return nil;
199 0c98da8b 2005-07-13 devnull a = (u32int*)b->data;
200 b109049f 2007-03-25 devnull pbno = a[bno/ppb];
201 b109049f 2007-03-25 devnull bno = bno%ppb;
202 0c98da8b 2005-07-13 devnull blockput(b);
203 b109049f 2007-03-25 devnull b = ext2datablock(fs, pbno, fs->blocksize);
204 0c98da8b 2005-07-13 devnull if(b == nil)
205 0c98da8b 2005-07-13 devnull return nil;
206 0c98da8b 2005-07-13 devnull a = (u32int*)b->data;
207 b109049f 2007-03-25 devnull bno = a[bno];
208 0c98da8b 2005-07-13 devnull blockput(b);
209 0c98da8b 2005-07-13 devnull return ext2datablock(fs, bno, size);
210 0c98da8b 2005-07-13 devnull }
211 0c98da8b 2005-07-13 devnull bno -= ppb*ppb;
212 0c98da8b 2005-07-13 devnull
213 0c98da8b 2005-07-13 devnull /* one triple indirect */
214 0c98da8b 2005-07-13 devnull if(bno < ppb*ppb*ppb){
215 0c98da8b 2005-07-13 devnull b = ext2datablock(fs, ino->block[TINDBLOCK], fs->blocksize);
216 0c98da8b 2005-07-13 devnull if(b == nil)
217 0c98da8b 2005-07-13 devnull return nil;
218 0c98da8b 2005-07-13 devnull a = (u32int*)b->data;
219 b109049f 2007-03-25 devnull pbno = a[bno/(ppb*ppb)];
220 b109049f 2007-03-25 devnull bno = bno%(ppb*ppb);
221 0c98da8b 2005-07-13 devnull blockput(b);
222 b109049f 2007-03-25 devnull b = ext2datablock(fs, pbno, fs->blocksize);
223 0c98da8b 2005-07-13 devnull if(b == nil)
224 0c98da8b 2005-07-13 devnull return nil;
225 0c98da8b 2005-07-13 devnull a = (u32int*)b->data;
226 b109049f 2007-03-25 devnull pbno = a[bno/ppb];
227 b109049f 2007-03-25 devnull bno = bno%ppb;
228 0c98da8b 2005-07-13 devnull blockput(b);
229 b109049f 2007-03-25 devnull b = ext2datablock(fs, pbno, fs->blocksize);
230 0c98da8b 2005-07-13 devnull if(b == nil)
231 0c98da8b 2005-07-13 devnull return nil;
232 0c98da8b 2005-07-13 devnull a = (u32int*)b->data;
233 b109049f 2007-03-25 devnull bno = a[bno];
234 0c98da8b 2005-07-13 devnull blockput(b);
235 0c98da8b 2005-07-13 devnull return ext2datablock(fs, bno, size);
236 0c98da8b 2005-07-13 devnull }
237 0c98da8b 2005-07-13 devnull
238 3330e5bf 2005-10-29 devnull fprint(2, "ext2fileblock %ud: too big\n", obno);
239 0c98da8b 2005-07-13 devnull return nil;
240 0c98da8b 2005-07-13 devnull }
241 0c98da8b 2005-07-13 devnull
242 0c98da8b 2005-07-13 devnull static int
243 0c98da8b 2005-07-13 devnull checksuper(Super *super)
244 0c98da8b 2005-07-13 devnull {
245 0c98da8b 2005-07-13 devnull if(super->magic != SUPERMAGIC){
246 0c98da8b 2005-07-13 devnull werrstr("bad magic 0x%ux wanted 0x%ux", super->magic, SUPERMAGIC);
247 0c98da8b 2005-07-13 devnull return -1;
248 0c98da8b 2005-07-13 devnull }
249 0c98da8b 2005-07-13 devnull return 0;
250 0c98da8b 2005-07-13 devnull }
251 0c98da8b 2005-07-13 devnull
252 0c98da8b 2005-07-13 devnull static int
253 0c98da8b 2005-07-13 devnull ext2sync(Fsys *fsys)
254 0c98da8b 2005-07-13 devnull {
255 0c98da8b 2005-07-13 devnull int i;
256 0c98da8b 2005-07-13 devnull Group *g;
257 0c98da8b 2005-07-13 devnull Block *b;
258 0c98da8b 2005-07-13 devnull Super *super;
259 0c98da8b 2005-07-13 devnull Ext2 *fs;
260 0c98da8b 2005-07-13 devnull Disk *disk;
261 0c98da8b 2005-07-13 devnull
262 0c98da8b 2005-07-13 devnull fs = fsys->priv;
263 0c98da8b 2005-07-13 devnull disk = fs->disk;
264 0c98da8b 2005-07-13 devnull if((b = diskread(disk, SBSIZE, SBOFF)) == nil)
265 0c98da8b 2005-07-13 devnull goto error;
266 0c98da8b 2005-07-13 devnull super = (Super*)b->data;
267 0c98da8b 2005-07-13 devnull if(checksuper(super) < 0)
268 0c98da8b 2005-07-13 devnull goto error;
269 0c98da8b 2005-07-13 devnull fs->blocksize = MINBLOCKSIZE<<super->logblocksize;
270 0c98da8b 2005-07-13 devnull fs->nblock = super->nblock;
271 0c98da8b 2005-07-13 devnull fs->ngroup = (super->nblock+super->blockspergroup-1)
272 0c98da8b 2005-07-13 devnull / super->blockspergroup;
273 0c98da8b 2005-07-13 devnull fs->inospergroup = super->inospergroup;
274 0c98da8b 2005-07-13 devnull fs->blockspergroup = super->blockspergroup;
275 0c98da8b 2005-07-13 devnull fs->inosperblock = fs->blocksize / InodeSize;
276 0c98da8b 2005-07-13 devnull if(fs->blocksize == SBOFF)
277 0c98da8b 2005-07-13 devnull fs->groupaddr = 2;
278 0c98da8b 2005-07-13 devnull else
279 0c98da8b 2005-07-13 devnull fs->groupaddr = 1;
280 0c98da8b 2005-07-13 devnull fs->descperblock = fs->blocksize / GroupSize;
281 0c98da8b 2005-07-13 devnull fs->firstblock = super->firstdatablock;
282 0c98da8b 2005-07-13 devnull blockput(b);
283 0c98da8b 2005-07-13 devnull
284 0c98da8b 2005-07-13 devnull fsys->blocksize = fs->blocksize;
285 0c98da8b 2005-07-13 devnull fsys->nblock = fs->nblock;
286 0c98da8b 2005-07-13 devnull fprint(2, "ext2 %d %d-byte blocks, first data block %d, %d groups of %d\n",
287 0c98da8b 2005-07-13 devnull fs->nblock, fs->blocksize, fs->firstblock, fs->ngroup, fs->blockspergroup);
288 0c98da8b 2005-07-13 devnull
289 0c98da8b 2005-07-13 devnull if(0){
290 0c98da8b 2005-07-13 devnull for(i=0; i<fs->ngroup; i++)
291 0c98da8b 2005-07-13 devnull if((g = ext2group(fs, i, &b)) != nil){
292 0c98da8b 2005-07-13 devnull fprint(2, "grp %d: bitblock=%d\n", i, g->bitblock);
293 0c98da8b 2005-07-13 devnull blockput(b);
294 0c98da8b 2005-07-13 devnull }
295 0c98da8b 2005-07-13 devnull }
296 0c98da8b 2005-07-13 devnull return 0;
297 0c98da8b 2005-07-13 devnull
298 0c98da8b 2005-07-13 devnull error:
299 0c98da8b 2005-07-13 devnull blockput(b);
300 0c98da8b 2005-07-13 devnull return -1;
301 0c98da8b 2005-07-13 devnull }
302 0c98da8b 2005-07-13 devnull
303 0c98da8b 2005-07-13 devnull static void
304 0c98da8b 2005-07-13 devnull mkhandle(Nfs3Handle *h, u64int ino)
305 0c98da8b 2005-07-13 devnull {
306 0c98da8b 2005-07-13 devnull h->h[0] = ino>>24;
307 0c98da8b 2005-07-13 devnull h->h[1] = ino>>16;
308 0c98da8b 2005-07-13 devnull h->h[2] = ino>>8;
309 0c98da8b 2005-07-13 devnull h->h[3] = ino;
310 0c98da8b 2005-07-13 devnull h->len = 4;
311 0c98da8b 2005-07-13 devnull }
312 0c98da8b 2005-07-13 devnull
313 0c98da8b 2005-07-13 devnull static u32int
314 0c98da8b 2005-07-13 devnull byte2u32(uchar *p)
315 0c98da8b 2005-07-13 devnull {
316 0c98da8b 2005-07-13 devnull return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
317 0c98da8b 2005-07-13 devnull }
318 0c98da8b 2005-07-13 devnull
319 0c98da8b 2005-07-13 devnull static Nfs3Status
320 0c98da8b 2005-07-13 devnull handle2ino(Ext2 *fs, Nfs3Handle *h, u32int *pinum, Inode *ino)
321 0c98da8b 2005-07-13 devnull {
322 0c98da8b 2005-07-13 devnull int i;
323 0c98da8b 2005-07-13 devnull uint ioff;
324 0c98da8b 2005-07-13 devnull u32int inum;
325 0c98da8b 2005-07-13 devnull u32int addr;
326 0c98da8b 2005-07-13 devnull Block *gb, *b;
327 0c98da8b 2005-07-13 devnull Group *g;
328 0c98da8b 2005-07-13 devnull
329 0c98da8b 2005-07-13 devnull if(h->len != 4)
330 0c98da8b 2005-07-13 devnull return Nfs3ErrBadHandle;
331 0c98da8b 2005-07-13 devnull inum = byte2u32(h->h);
332 0c98da8b 2005-07-13 devnull if(pinum)
333 0c98da8b 2005-07-13 devnull *pinum = inum;
334 0c98da8b 2005-07-13 devnull i = (inum-1) / fs->inospergroup;
335 0c98da8b 2005-07-13 devnull if(i >= fs->ngroup)
336 0c98da8b 2005-07-13 devnull return Nfs3ErrBadHandle;
337 0c98da8b 2005-07-13 devnull ioff = (inum-1) % fs->inospergroup;
338 0c98da8b 2005-07-13 devnull if((g = ext2group(fs, i, &gb)) == nil)
339 0c98da8b 2005-07-13 devnull return Nfs3ErrIo;
340 0c98da8b 2005-07-13 devnull addr = g->inodeaddr + ioff/fs->inosperblock;
341 0c98da8b 2005-07-13 devnull blockput(gb);
342 0c98da8b 2005-07-13 devnull if((b = diskread(fs->disk, fs->blocksize, (u64int)addr*fs->blocksize)) == nil)
343 0c98da8b 2005-07-13 devnull return Nfs3ErrIo;
344 0c98da8b 2005-07-13 devnull *ino = ((Inode*)b->data)[ioff%fs->inosperblock];
345 0c98da8b 2005-07-13 devnull blockput(b);
346 0c98da8b 2005-07-13 devnull return Nfs3Ok;
347 0c98da8b 2005-07-13 devnull }
348 0c98da8b 2005-07-13 devnull
349 0c98da8b 2005-07-13 devnull static Nfs3Status
350 0c98da8b 2005-07-13 devnull ext2root(Fsys *fsys, Nfs3Handle *h)
351 0c98da8b 2005-07-13 devnull {
352 3330e5bf 2005-10-29 devnull USED(fsys);
353 0c98da8b 2005-07-13 devnull mkhandle(h, ROOTINODE);
354 0c98da8b 2005-07-13 devnull return Nfs3Ok;
355 b109049f 2007-03-25 devnull }
356 b109049f 2007-03-25 devnull
357 b109049f 2007-03-25 devnull static u64int
358 b109049f 2007-03-25 devnull inosize(Inode* ino)
359 b109049f 2007-03-25 devnull {
360 b109049f 2007-03-25 devnull u64int size;
361 b109049f 2007-03-25 devnull
362 b109049f 2007-03-25 devnull size = ino->size;
363 b109049f 2007-03-25 devnull if((ino->mode&IFMT)==IFREG)
364 b109049f 2007-03-25 devnull size |= (u64int)ino->diracl << 32;
365 b109049f 2007-03-25 devnull return size;
366 0c98da8b 2005-07-13 devnull }
367 0c98da8b 2005-07-13 devnull
368 0c98da8b 2005-07-13 devnull static Nfs3Status
369 0c98da8b 2005-07-13 devnull ino2attr(Ext2 *fs, Inode *ino, u32int inum, Nfs3Attr *attr)
370 0c98da8b 2005-07-13 devnull {
371 0c98da8b 2005-07-13 devnull u32int rdev;
372 0c98da8b 2005-07-13 devnull
373 0c98da8b 2005-07-13 devnull attr->type = -1;
374 0c98da8b 2005-07-13 devnull switch(ino->mode&IFMT){
375 0c98da8b 2005-07-13 devnull case IFIFO:
376 0c98da8b 2005-07-13 devnull attr->type = Nfs3FileFifo;
377 0c98da8b 2005-07-13 devnull break;
378 0c98da8b 2005-07-13 devnull case IFCHR:
379 0c98da8b 2005-07-13 devnull attr->type = Nfs3FileChar;
380 0c98da8b 2005-07-13 devnull break;
381 0c98da8b 2005-07-13 devnull case IFDIR:
382 0c98da8b 2005-07-13 devnull attr->type = Nfs3FileDir;
383 0c98da8b 2005-07-13 devnull break;
384 0c98da8b 2005-07-13 devnull case IFBLK:
385 0c98da8b 2005-07-13 devnull attr->type = Nfs3FileBlock;
386 0c98da8b 2005-07-13 devnull break;
387 0c98da8b 2005-07-13 devnull case IFREG:
388 0c98da8b 2005-07-13 devnull attr->type = Nfs3FileReg;
389 0c98da8b 2005-07-13 devnull break;
390 0c98da8b 2005-07-13 devnull case IFLNK:
391 0c98da8b 2005-07-13 devnull attr->type = Nfs3FileSymlink;
392 0c98da8b 2005-07-13 devnull break;
393 0c98da8b 2005-07-13 devnull case IFSOCK:
394 0c98da8b 2005-07-13 devnull attr->type = Nfs3FileSocket;
395 0c98da8b 2005-07-13 devnull break;
396 0c98da8b 2005-07-13 devnull case IFWHT:
397 0c98da8b 2005-07-13 devnull default:
398 0c98da8b 2005-07-13 devnull return Nfs3ErrBadHandle;
399 0c98da8b 2005-07-13 devnull }
400 0c98da8b 2005-07-13 devnull
401 0c98da8b 2005-07-13 devnull attr->mode = ino->mode&07777;
402 0c98da8b 2005-07-13 devnull attr->nlink = ino->nlink;
403 0c98da8b 2005-07-13 devnull attr->uid = ino->uid;
404 0c98da8b 2005-07-13 devnull attr->gid = ino->gid;
405 b109049f 2007-03-25 devnull attr->size = inosize(ino);
406 b109049f 2007-03-25 devnull attr->used = (u64int)ino->nblock*fs->blocksize;
407 0c98da8b 2005-07-13 devnull if(attr->type==Nfs3FileBlock || attr->type==Nfs3FileChar){
408 0c98da8b 2005-07-13 devnull rdev = ino->block[0];
409 0c98da8b 2005-07-13 devnull attr->major = (rdev>>8)&0xFF;
410 0c98da8b 2005-07-13 devnull attr->minor = rdev & 0xFFFF00FF;
411 0c98da8b 2005-07-13 devnull }else{
412 0c98da8b 2005-07-13 devnull attr->major = 0;
413 0c98da8b 2005-07-13 devnull attr->minor = 0;
414 0c98da8b 2005-07-13 devnull }
415 0c98da8b 2005-07-13 devnull attr->fsid = 0;
416 0c98da8b 2005-07-13 devnull attr->fileid = inum;
417 0c98da8b 2005-07-13 devnull attr->atime.sec = ino->atime;
418 0c98da8b 2005-07-13 devnull attr->atime.nsec = 0;
419 0c98da8b 2005-07-13 devnull attr->mtime.sec = ino->mtime;
420 0c98da8b 2005-07-13 devnull attr->mtime.nsec = 0;
421 0c98da8b 2005-07-13 devnull attr->ctime.sec = ino->ctime;
422 0c98da8b 2005-07-13 devnull attr->ctime.nsec = 0;
423 0c98da8b 2005-07-13 devnull return Nfs3Ok;
424 0c98da8b 2005-07-13 devnull }
425 0c98da8b 2005-07-13 devnull
426 0c98da8b 2005-07-13 devnull static int
427 0c98da8b 2005-07-13 devnull ingroup(SunAuthUnix *au, uint gid)
428 0c98da8b 2005-07-13 devnull {
429 0c98da8b 2005-07-13 devnull int i;
430 0c98da8b 2005-07-13 devnull
431 0c98da8b 2005-07-13 devnull for(i=0; i<au->ng; i++)
432 0c98da8b 2005-07-13 devnull if(au->g[i] == gid)
433 0c98da8b 2005-07-13 devnull return 1;
434 0c98da8b 2005-07-13 devnull return 0;
435 0c98da8b 2005-07-13 devnull }
436 0c98da8b 2005-07-13 devnull
437 0c98da8b 2005-07-13 devnull static Nfs3Status
438 0c98da8b 2005-07-13 devnull inoperm(Inode *ino, SunAuthUnix *au, int need)
439 0c98da8b 2005-07-13 devnull {
440 0c98da8b 2005-07-13 devnull int have;
441 0c98da8b 2005-07-13 devnull
442 0c98da8b 2005-07-13 devnull if(allowall)
443 0c98da8b 2005-07-13 devnull return Nfs3Ok;
444 0c98da8b 2005-07-13 devnull
445 0c98da8b 2005-07-13 devnull have = ino->mode&0777;
446 0c98da8b 2005-07-13 devnull if(ino->uid == au->uid)
447 0c98da8b 2005-07-13 devnull have >>= 6;
448 0c98da8b 2005-07-13 devnull else if(ino->gid == au->gid || ingroup(au, ino->gid))
449 0c98da8b 2005-07-13 devnull have >>= 3;
450 0c98da8b 2005-07-13 devnull
451 0c98da8b 2005-07-13 devnull if((have&need) != need)
452 0c98da8b 2005-07-13 devnull return Nfs3ErrNotOwner; /* really EPERM */
453 0c98da8b 2005-07-13 devnull return Nfs3Ok;
454 0c98da8b 2005-07-13 devnull }
455 0c98da8b 2005-07-13 devnull
456 0c98da8b 2005-07-13 devnull static Nfs3Status
457 0c98da8b 2005-07-13 devnull ext2getattr(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, Nfs3Attr *attr)
458 0c98da8b 2005-07-13 devnull {
459 0c98da8b 2005-07-13 devnull Inode ino;
460 0c98da8b 2005-07-13 devnull u32int inum;
461 0c98da8b 2005-07-13 devnull Ext2 *fs;
462 0c98da8b 2005-07-13 devnull Nfs3Status ok;
463 0c98da8b 2005-07-13 devnull
464 0c98da8b 2005-07-13 devnull fs = fsys->priv;
465 0c98da8b 2005-07-13 devnull if((ok = handle2ino(fs, h, &inum, &ino)) != Nfs3Ok)
466 0c98da8b 2005-07-13 devnull return ok;
467 0c98da8b 2005-07-13 devnull
468 0c98da8b 2005-07-13 devnull USED(au); /* anyone can getattr */
469 0c98da8b 2005-07-13 devnull return ino2attr(fs, &ino, inum, attr);
470 0c98da8b 2005-07-13 devnull }
471 0c98da8b 2005-07-13 devnull
472 0c98da8b 2005-07-13 devnull static Nfs3Status
473 0c98da8b 2005-07-13 devnull ext2access(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int want, u32int *got, Nfs3Attr *attr)
474 0c98da8b 2005-07-13 devnull {
475 0c98da8b 2005-07-13 devnull int have;
476 0c98da8b 2005-07-13 devnull Inode ino;
477 0c98da8b 2005-07-13 devnull u32int inum;
478 0c98da8b 2005-07-13 devnull Ext2 *fs;
479 0c98da8b 2005-07-13 devnull Nfs3Status ok;
480 0c98da8b 2005-07-13 devnull
481 0c98da8b 2005-07-13 devnull fs = fsys->priv;
482 0c98da8b 2005-07-13 devnull if((ok = handle2ino(fs, h, &inum, &ino)) != Nfs3Ok)
483 0c98da8b 2005-07-13 devnull return ok;
484 0c98da8b 2005-07-13 devnull
485 0c98da8b 2005-07-13 devnull have = ino.mode&0777;
486 0c98da8b 2005-07-13 devnull if(ino.uid == au->uid)
487 0c98da8b 2005-07-13 devnull have >>= 6;
488 0c98da8b 2005-07-13 devnull else if(ino.gid == au->gid || ingroup(au, ino.gid))
489 0c98da8b 2005-07-13 devnull have >>= 3;
490 0c98da8b 2005-07-13 devnull
491 0c98da8b 2005-07-13 devnull *got = 0;
492 0c98da8b 2005-07-13 devnull if((want&Nfs3AccessRead) && (have&AREAD))
493 0c98da8b 2005-07-13 devnull *got |= Nfs3AccessRead;
494 0c98da8b 2005-07-13 devnull if((want&Nfs3AccessLookup) && (ino.mode&IFMT)==IFDIR && (have&AEXEC))
495 0c98da8b 2005-07-13 devnull *got |= Nfs3AccessLookup;
496 0c98da8b 2005-07-13 devnull if((want&Nfs3AccessExecute) && (ino.mode&IFMT)!=IFDIR && (have&AEXEC))
497 0c98da8b 2005-07-13 devnull *got |= Nfs3AccessExecute;
498 0c98da8b 2005-07-13 devnull
499 0c98da8b 2005-07-13 devnull return ino2attr(fs, &ino, inum, attr);
500 0c98da8b 2005-07-13 devnull }
501 0c98da8b 2005-07-13 devnull
502 0c98da8b 2005-07-13 devnull static Nfs3Status
503 0c98da8b 2005-07-13 devnull ext2lookup(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, char *name, Nfs3Handle *nh)
504 0c98da8b 2005-07-13 devnull {
505 0c98da8b 2005-07-13 devnull u32int nblock;
506 0c98da8b 2005-07-13 devnull u32int i;
507 0c98da8b 2005-07-13 devnull uchar *p, *ep;
508 0c98da8b 2005-07-13 devnull Dirent *de;
509 0c98da8b 2005-07-13 devnull Inode ino;
510 0c98da8b 2005-07-13 devnull Block *b;
511 0c98da8b 2005-07-13 devnull Ext2 *fs;
512 0c98da8b 2005-07-13 devnull Nfs3Status ok;
513 0c98da8b 2005-07-13 devnull int len, want;
514 0c98da8b 2005-07-13 devnull
515 0c98da8b 2005-07-13 devnull fs = fsys->priv;
516 0c98da8b 2005-07-13 devnull if((ok = handle2ino(fs, h, nil, &ino)) != Nfs3Ok)
517 0c98da8b 2005-07-13 devnull return ok;
518 0c98da8b 2005-07-13 devnull
519 0c98da8b 2005-07-13 devnull if((ino.mode&IFMT) != IFDIR)
520 0c98da8b 2005-07-13 devnull return Nfs3ErrNotDir;
521 0c98da8b 2005-07-13 devnull
522 0c98da8b 2005-07-13 devnull if((ok = inoperm(&ino, au, AEXEC)) != Nfs3Ok)
523 0c98da8b 2005-07-13 devnull return ok;
524 0c98da8b 2005-07-13 devnull
525 0c98da8b 2005-07-13 devnull len = strlen(name);
526 0c98da8b 2005-07-13 devnull nblock = (ino.size+fs->blocksize-1) / fs->blocksize;
527 0c98da8b 2005-07-13 devnull if(debug) fprint(2, "%d blocks in dir...", nblock);
528 0c98da8b 2005-07-13 devnull for(i=0; i<nblock; i++){
529 0c98da8b 2005-07-13 devnull if(i==nblock-1)
530 0c98da8b 2005-07-13 devnull want = ino.size % fs->blocksize;
531 0c98da8b 2005-07-13 devnull else
532 0c98da8b 2005-07-13 devnull want = fs->blocksize;
533 0c98da8b 2005-07-13 devnull b = ext2fileblock(fs, &ino, i, want);
534 0c98da8b 2005-07-13 devnull if(b == nil){
535 0c98da8b 2005-07-13 devnull if(debug) fprint(2, "empty block...");
536 0c98da8b 2005-07-13 devnull continue;
537 0c98da8b 2005-07-13 devnull }
538 0c98da8b 2005-07-13 devnull p = b->data;
539 0c98da8b 2005-07-13 devnull ep = p+b->len;
540 0c98da8b 2005-07-13 devnull while(p < ep){
541 0c98da8b 2005-07-13 devnull de = (Dirent*)p;
542 0c98da8b 2005-07-13 devnull if(de->reclen == 0){
543 0c98da8b 2005-07-13 devnull if(debug)
544 0c98da8b 2005-07-13 devnull fprint(2, "reclen 0 at offset %d of %d\n", (int)(p-b->data), b->len);
545 0c98da8b 2005-07-13 devnull break;
546 0c98da8b 2005-07-13 devnull }
547 0c98da8b 2005-07-13 devnull p += de->reclen;
548 0c98da8b 2005-07-13 devnull if(p > ep){
549 0c98da8b 2005-07-13 devnull if(debug)
550 0c98da8b 2005-07-13 devnull fprint(2, "bad len %d at offset %d of %d\n", de->reclen, (int)(p-b->data), b->len);
551 0c98da8b 2005-07-13 devnull break;
552 0c98da8b 2005-07-13 devnull }
553 0c98da8b 2005-07-13 devnull if(de->ino == 0)
554 0c98da8b 2005-07-13 devnull continue;
555 0c98da8b 2005-07-13 devnull if(4+2+2+de->namlen > de->reclen){
556 0c98da8b 2005-07-13 devnull if(debug)
557 0c98da8b 2005-07-13 devnull fprint(2, "bad namelen %d at offset %d of %d\n", de->namlen, (int)(p-b->data), b->len);
558 0c98da8b 2005-07-13 devnull break;
559 0c98da8b 2005-07-13 devnull }
560 0c98da8b 2005-07-13 devnull if(de->namlen == len && memcmp(de->name, name, len) == 0){
561 0c98da8b 2005-07-13 devnull mkhandle(nh, de->ino);
562 0c98da8b 2005-07-13 devnull blockput(b);
563 0c98da8b 2005-07-13 devnull return Nfs3Ok;
564 0c98da8b 2005-07-13 devnull }
565 0c98da8b 2005-07-13 devnull }
566 0c98da8b 2005-07-13 devnull blockput(b);
567 0c98da8b 2005-07-13 devnull }
568 0c98da8b 2005-07-13 devnull return Nfs3ErrNoEnt;
569 0c98da8b 2005-07-13 devnull }
570 0c98da8b 2005-07-13 devnull
571 0c98da8b 2005-07-13 devnull static Nfs3Status
572 0c98da8b 2005-07-13 devnull ext2readdir(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int count, u64int cookie, uchar **pdata, u32int *pcount, u1int *peof)
573 0c98da8b 2005-07-13 devnull {
574 0c98da8b 2005-07-13 devnull u32int nblock;
575 0c98da8b 2005-07-13 devnull u32int i;
576 0c98da8b 2005-07-13 devnull int off, done;
577 0c98da8b 2005-07-13 devnull uchar *data, *dp, *dep, *p, *ep, *ndp;
578 0c98da8b 2005-07-13 devnull Dirent *de;
579 0c98da8b 2005-07-13 devnull Inode ino;
580 0c98da8b 2005-07-13 devnull Block *b;
581 0c98da8b 2005-07-13 devnull Ext2 *fs;
582 0c98da8b 2005-07-13 devnull Nfs3Status ok;
583 0c98da8b 2005-07-13 devnull Nfs3Entry e;
584 0c98da8b 2005-07-13 devnull int want;
585 0c98da8b 2005-07-13 devnull
586 0c98da8b 2005-07-13 devnull fs = fsys->priv;
587 0c98da8b 2005-07-13 devnull if((ok = handle2ino(fs, h, nil, &ino)) != Nfs3Ok)
588 0c98da8b 2005-07-13 devnull return ok;
589 0c98da8b 2005-07-13 devnull
590 0c98da8b 2005-07-13 devnull if((ino.mode&IFMT) != IFDIR)
591 0c98da8b 2005-07-13 devnull return Nfs3ErrNotDir;
592 0c98da8b 2005-07-13 devnull
593 0c98da8b 2005-07-13 devnull if((ok = inoperm(&ino, au, AREAD)) != Nfs3Ok)
594 0c98da8b 2005-07-13 devnull return ok;
595 0c98da8b 2005-07-13 devnull
596 0c98da8b 2005-07-13 devnull if(cookie >= ino.size){
597 0c98da8b 2005-07-13 devnull *pcount = 0;
598 0c98da8b 2005-07-13 devnull *pdata = 0;
599 0c98da8b 2005-07-13 devnull return Nfs3Ok;
600 0c98da8b 2005-07-13 devnull }
601 0c98da8b 2005-07-13 devnull
602 0c98da8b 2005-07-13 devnull dp = malloc(count);
603 0c98da8b 2005-07-13 devnull data = dp;
604 0c98da8b 2005-07-13 devnull if(dp == nil)
605 0c98da8b 2005-07-13 devnull return Nfs3ErrNoMem;
606 0c98da8b 2005-07-13 devnull dep = dp+count;
607 0c98da8b 2005-07-13 devnull *peof = 0;
608 0c98da8b 2005-07-13 devnull nblock = (ino.size+fs->blocksize-1) / fs->blocksize;
609 0c98da8b 2005-07-13 devnull i = cookie/fs->blocksize;
610 0c98da8b 2005-07-13 devnull off = cookie%fs->blocksize;
611 0c98da8b 2005-07-13 devnull done = 0;
612 0c98da8b 2005-07-13 devnull for(; i<nblock && !done; i++){
613 0c98da8b 2005-07-13 devnull if(i==nblock-1)
614 0c98da8b 2005-07-13 devnull want = ino.size % fs->blocksize;
615 0c98da8b 2005-07-13 devnull else
616 0c98da8b 2005-07-13 devnull want = fs->blocksize;
617 0c98da8b 2005-07-13 devnull b = ext2fileblock(fs, &ino, i, want);
618 0c98da8b 2005-07-13 devnull if(b == nil)
619 0c98da8b 2005-07-13 devnull continue;
620 0c98da8b 2005-07-13 devnull p = b->data;
621 0c98da8b 2005-07-13 devnull ep = p+b->len;
622 0c98da8b 2005-07-13 devnull memset(&e, 0, sizeof e);
623 0c98da8b 2005-07-13 devnull while(p < ep){
624 0c98da8b 2005-07-13 devnull de = (Dirent*)p;
625 0c98da8b 2005-07-13 devnull if(de->reclen == 0){
626 0c98da8b 2005-07-13 devnull if(debug) fprint(2, "reclen 0 at offset %d of %d\n", (int)(p-b->data), b->len);
627 0c98da8b 2005-07-13 devnull break;
628 0c98da8b 2005-07-13 devnull }
629 0c98da8b 2005-07-13 devnull p += de->reclen;
630 0c98da8b 2005-07-13 devnull if(p > ep){
631 0c98da8b 2005-07-13 devnull if(debug) fprint(2, "reclen %d at offset %d of %d\n", de->reclen, (int)(p-b->data), b->len);
632 0c98da8b 2005-07-13 devnull break;
633 0c98da8b 2005-07-13 devnull }
634 0c98da8b 2005-07-13 devnull if(de->ino == 0){
635 0c98da8b 2005-07-13 devnull if(debug) fprint(2, "zero inode\n");
636 0c98da8b 2005-07-13 devnull continue;
637 0c98da8b 2005-07-13 devnull }
638 0c98da8b 2005-07-13 devnull if(4+2+2+de->namlen > de->reclen){
639 0c98da8b 2005-07-13 devnull if(debug) fprint(2, "bad namlen %d reclen %d at offset %d of %d\n", de->namlen, de->reclen, (int)(p-b->data), b->len);
640 0c98da8b 2005-07-13 devnull break;
641 0c98da8b 2005-07-13 devnull }
642 e77222a4 2006-05-04 devnull if(debug) print("%.*s/%d ", de->namlen, de->name, (int)de->ino);
643 0c98da8b 2005-07-13 devnull if((uchar*)de - b->data < off)
644 0c98da8b 2005-07-13 devnull continue;
645 0c98da8b 2005-07-13 devnull e.fileid = de->ino;
646 0c98da8b 2005-07-13 devnull e.name = de->name;
647 e77222a4 2006-05-04 devnull e.namelen = de->namlen;
648 0c98da8b 2005-07-13 devnull e.cookie = (u64int)i*fs->blocksize + (p - b->data);
649 0c98da8b 2005-07-13 devnull if(nfs3entrypack(dp, dep, &ndp, &e) < 0){
650 0c98da8b 2005-07-13 devnull done = 1;
651 0c98da8b 2005-07-13 devnull break;
652 0c98da8b 2005-07-13 devnull }
653 0c98da8b 2005-07-13 devnull dp = ndp;
654 0c98da8b 2005-07-13 devnull }
655 0c98da8b 2005-07-13 devnull off = 0;
656 0c98da8b 2005-07-13 devnull blockput(b);
657 0c98da8b 2005-07-13 devnull }
658 0c98da8b 2005-07-13 devnull if(i==nblock)
659 0c98da8b 2005-07-13 devnull *peof = 1;
660 0c98da8b 2005-07-13 devnull
661 0c98da8b 2005-07-13 devnull *pcount = dp - data;
662 0c98da8b 2005-07-13 devnull *pdata = data;
663 0c98da8b 2005-07-13 devnull return Nfs3Ok;
664 0c98da8b 2005-07-13 devnull }
665 0c98da8b 2005-07-13 devnull
666 0c98da8b 2005-07-13 devnull static Nfs3Status
667 0c98da8b 2005-07-13 devnull ext2readfile(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int count,
668 0c98da8b 2005-07-13 devnull u64int offset, uchar **pdata, u32int *pcount, u1int *peof)
669 0c98da8b 2005-07-13 devnull {
670 0c98da8b 2005-07-13 devnull uchar *data;
671 0c98da8b 2005-07-13 devnull Block *b;
672 0c98da8b 2005-07-13 devnull Ext2 *fs;
673 fa5af687 2006-06-15 devnull int skip1, tot, want, fragcount;
674 0c98da8b 2005-07-13 devnull Inode ino;
675 0c98da8b 2005-07-13 devnull Nfs3Status ok;
676 b109049f 2007-03-25 devnull u64int size;
677 0c98da8b 2005-07-13 devnull
678 0c98da8b 2005-07-13 devnull fs = fsys->priv;
679 0c98da8b 2005-07-13 devnull if((ok = handle2ino(fs, h, nil, &ino)) != Nfs3Ok)
680 0c98da8b 2005-07-13 devnull return ok;
681 0c98da8b 2005-07-13 devnull
682 0c98da8b 2005-07-13 devnull if((ok = inoperm(&ino, au, AREAD)) != Nfs3Ok)
683 0c98da8b 2005-07-13 devnull return ok;
684 0c98da8b 2005-07-13 devnull
685 b109049f 2007-03-25 devnull size = inosize(&ino);
686 b109049f 2007-03-25 devnull if(offset >= size){
687 0c98da8b 2005-07-13 devnull *pdata = 0;
688 0c98da8b 2005-07-13 devnull *pcount = 0;
689 0c98da8b 2005-07-13 devnull *peof = 1;
690 0c98da8b 2005-07-13 devnull return Nfs3Ok;
691 0c98da8b 2005-07-13 devnull }
692 b109049f 2007-03-25 devnull if(offset+count > size)
693 b109049f 2007-03-25 devnull count = size-offset;
694 0c98da8b 2005-07-13 devnull
695 0c98da8b 2005-07-13 devnull data = malloc(count);
696 0c98da8b 2005-07-13 devnull if(data == nil)
697 0c98da8b 2005-07-13 devnull return Nfs3ErrNoMem;
698 fa5af687 2006-06-15 devnull memset(data, 0, count);
699 0c98da8b 2005-07-13 devnull
700 fa5af687 2006-06-15 devnull skip1 = offset%fs->blocksize;
701 fa5af687 2006-06-15 devnull offset -= skip1;
702 fa5af687 2006-06-15 devnull want = skip1+count;
703 0c98da8b 2005-07-13 devnull
704 fa5af687 2006-06-15 devnull /*
705 fa5af687 2006-06-15 devnull * have to read multiple blocks if we get asked for a big read.
706 fa5af687 2006-06-15 devnull * Linux NFS client assumes that if you ask for 8k and only get 4k
707 fa5af687 2006-06-15 devnull * back, the remaining 4k is zeros.
708 fa5af687 2006-06-15 devnull */
709 fa5af687 2006-06-15 devnull for(tot=0; tot<want; tot+=fragcount){
710 fa5af687 2006-06-15 devnull b = ext2fileblock(fs, &ino, (offset+tot)/fs->blocksize, fs->blocksize);
711 fa5af687 2006-06-15 devnull fragcount = fs->blocksize;
712 fa5af687 2006-06-15 devnull if(b == nil)
713 fa5af687 2006-06-15 devnull continue;
714 fa5af687 2006-06-15 devnull if(tot+fragcount > want)
715 fa5af687 2006-06-15 devnull fragcount = want - tot;
716 fa5af687 2006-06-15 devnull if(tot == 0)
717 fa5af687 2006-06-15 devnull memmove(data, b->data+skip1, fragcount-skip1);
718 fa5af687 2006-06-15 devnull else
719 fa5af687 2006-06-15 devnull memmove(data+tot-skip1, b->data, fragcount);
720 0c98da8b 2005-07-13 devnull blockput(b);
721 0c98da8b 2005-07-13 devnull }
722 fa5af687 2006-06-15 devnull count = tot - skip1;
723 fa5af687 2006-06-15 devnull
724 b109049f 2007-03-25 devnull *peof = (offset+count == size);
725 0c98da8b 2005-07-13 devnull *pcount = count;
726 0c98da8b 2005-07-13 devnull *pdata = data;
727 0c98da8b 2005-07-13 devnull return Nfs3Ok;
728 0c98da8b 2005-07-13 devnull }
729 0c98da8b 2005-07-13 devnull
730 0c98da8b 2005-07-13 devnull static Nfs3Status
731 0c98da8b 2005-07-13 devnull ext2readlink(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, char **link)
732 0c98da8b 2005-07-13 devnull {
733 0c98da8b 2005-07-13 devnull Ext2 *fs;
734 0c98da8b 2005-07-13 devnull Nfs3Status ok;
735 0c98da8b 2005-07-13 devnull int len;
736 0c98da8b 2005-07-13 devnull Inode ino;
737 0c98da8b 2005-07-13 devnull Block *b;
738 0c98da8b 2005-07-13 devnull
739 0c98da8b 2005-07-13 devnull fs = fsys->priv;
740 0c98da8b 2005-07-13 devnull if((ok = handle2ino(fs, h, nil, &ino)) != Nfs3Ok)
741 0c98da8b 2005-07-13 devnull return ok;
742 0c98da8b 2005-07-13 devnull if((ok = inoperm(&ino, au, AREAD)) != Nfs3Ok)
743 0c98da8b 2005-07-13 devnull return ok;
744 0c98da8b 2005-07-13 devnull
745 0c98da8b 2005-07-13 devnull if(ino.size > 1024)
746 0c98da8b 2005-07-13 devnull return Nfs3ErrIo;
747 0c98da8b 2005-07-13 devnull len = ino.size;
748 0c98da8b 2005-07-13 devnull
749 0c98da8b 2005-07-13 devnull if(ino.nblock != 0){
750 0c98da8b 2005-07-13 devnull /* BUG: assumes symlink fits in one block */
751 0c98da8b 2005-07-13 devnull b = ext2fileblock(fs, &ino, 0, len);
752 0c98da8b 2005-07-13 devnull if(b == nil)
753 0c98da8b 2005-07-13 devnull return Nfs3ErrIo;
754 0c98da8b 2005-07-13 devnull if(memchr(b->data, 0, len) != nil){
755 0c98da8b 2005-07-13 devnull blockput(b);
756 0c98da8b 2005-07-13 devnull return Nfs3ErrIo;
757 0c98da8b 2005-07-13 devnull }
758 0c98da8b 2005-07-13 devnull *link = malloc(len+1);
759 0c98da8b 2005-07-13 devnull if(*link == 0){
760 0c98da8b 2005-07-13 devnull blockput(b);
761 0c98da8b 2005-07-13 devnull return Nfs3ErrNoMem;
762 0c98da8b 2005-07-13 devnull }
763 0c98da8b 2005-07-13 devnull memmove(*link, b->data, len);
764 0c98da8b 2005-07-13 devnull (*link)[len] = 0;
765 0c98da8b 2005-07-13 devnull blockput(b);
766 0c98da8b 2005-07-13 devnull return Nfs3Ok;
767 0c98da8b 2005-07-13 devnull }
768 0c98da8b 2005-07-13 devnull
769 0c98da8b 2005-07-13 devnull if(len > sizeof ino.block)
770 0c98da8b 2005-07-13 devnull return Nfs3ErrIo;
771 0c98da8b 2005-07-13 devnull
772 0c98da8b 2005-07-13 devnull *link = malloc(len+1);
773 0c98da8b 2005-07-13 devnull if(*link == 0)
774 0c98da8b 2005-07-13 devnull return Nfs3ErrNoMem;
775 0c98da8b 2005-07-13 devnull memmove(*link, ino.block, ino.size);
776 0c98da8b 2005-07-13 devnull (*link)[len] = 0;
777 0c98da8b 2005-07-13 devnull return Nfs3Ok;
778 0c98da8b 2005-07-13 devnull }
779 0c98da8b 2005-07-13 devnull