|
|
1.1 root 1: /*
2: dstacker_alloc.c
3:
4: DMSDOS CVF-FAT module: stacker allocation routines.
5:
6: ******************************************************************************
7: DMSDOS (compressed MSDOS filesystem support) for Linux
8: written 1995-1998 by Frank Gockel and Pavel Pisa
9:
10: (C) Copyright 1995-1998 by Frank Gockel
11: (C) Copyright 1996-1998 by Pavel Pisa
12:
13: Some code of dmsdos has been copied from the msdos filesystem
14: so there are the following additional copyrights:
15:
16: (C) Copyright 1992,1993 by Werner Almesberger (msdos filesystem)
17: (C) Copyright 1994,1995 by Jacques Gelinas (mmap code)
18: (C) Copyright 1992-1995 by Linus Torvalds
19:
20: DMSDOS was inspired by the THS filesystem (a simple doublespace
21: DS-0-2 compressed read-only filesystem) written 1994 by Thomas Scheuermann.
22:
23: The DMSDOS code is distributed under the Gnu General Public Licence.
24: See file COPYING for details.
25: ******************************************************************************
26:
27: */
28:
29: #ifdef __KERNEL__
30: #include <linux/sched.h>
31: #include <linux/ctype.h>
32: #include <linux/major.h>
33: #include <linux/blkdev.h>
34: #include <linux/fs.h>
35: #include <linux/stat.h>
36: #include <linux/locks.h>
37: #include <asm/segment.h>
38: #include <linux/mm.h>
39: #include <linux/malloc.h>
40: #include <linux/string.h>
41: #include <linux/msdos_fs.h>
42: #include <linux/errno.h>
43: #include <linux/kernel.h>
44: #include <linux/shm.h>
45: #include <linux/mman.h>
46: #include <asm/system.h>
47: #endif
48:
49: #include "dmsdos.h"
50:
51: #ifdef __DMSDOS_LIB__
52: /* some interface hacks */
53: #include"lib_interface.h"
54: #include<malloc.h>
55: #include<errno.h>
56: #endif
57:
58:
59: #ifdef DMSDOS_CONFIG_STAC
60:
61: /* initializes Stac_cwalk structure, which can be used for sequential
62: access to all sectors of cluster and when needed informs about
63: all data areas in every sector. flg parameter speedups initialization
64: when some informations are not necessarry
65: flg = 0 .. only sector numbers
66: flg = 1 .. sector numbers and data without ending suballocation
67: flg = 2 .. sector numbers and exact data areas
68: flg = 3 .. same as 2 but more checking
69: */
70: int stac_cwalk_init(Stac_cwalk *cw,struct super_block*sb,
71: int clusternr,int flg)
72: {
73: __u8 *pp;
74: unsigned u,v;
75: int i;
76: int last_sect;
77: Mdfat_entry mde;
78: struct buffer_head *bh;
79: Dblsb*dblsb=MSDOS_SB(sb)->private_data;
80: cw->finfo=NULL;
81: cw->fbh=NULL;
82: cw->sect=0;
83: cw->sb=sb;
84: cw->clusternr=clusternr;
85: /* -------------------------------------------- */
86: dbl_mdfat_value(sb,clusternr,NULL,&mde);
87: cw->start_sect=mde.sector_minus_1+1;
88: cw->sect_cnt=cw->start_len=mde.size_lo_minus_1+1;
89: cw->flags=mde.flags;
90: if(!cw->start_sect) {cw->fcnt=0;return 0;};
91: /* -------------------------------------------- */
92: cw->fcnt=1;
93: cw->flen=cw->sect_cnt=cw->start_len;
94: cw->bytes_in_clust=cw->sect_cnt*SECTOR_SIZE;
95: cw->offset=0;
96: cw->bytes=SECTOR_SIZE;
97: cw->bytes_in_last=0;
98: last_sect=cw->start_sect+cw->sect_cnt-1;
99: /* -------------------------------------------- */
100: u=(cw->flags&0xe0)>>5;
101: if(cw->start_len==dblsb->s_sectperclust) u|=0x8;
102: switch(u)
103: { case 0x0: /* ffff=000x, len<ClustSize, compressed, regular file/dir */
104: case 0x2: /* ffff=010x, deleted 0 */
105: cw->compressed=1;
106: break;
107:
108: case 0x1: /* ffff=001x, not compressed but not full size, regular file/dir */
109: case 0x3: /* ffff=011x, deleted 1 */
110: case 0x8: /* ffff=000x, len=ClustSize, not compressed, regular file/dir */
111: case 0xa: /* ffff=010x, deleted 8 */
112: case 0xc: /* ffff=100x, len=ClustSize, directory, never compressed */
113: case 0xe: /* ffff=110x, deleted c */
114: cw->compressed=0;
115: break;
116:
117: case 0x4: /* ffff=100x, len<ClustSize, fragmented, regular file/dir */
118: case 0x6: /* ffff=110x, deleted 4 */
119: bh=raw_bread(sb,cw->start_sect);
120: if(bh==NULL)return -1;
121: pp=bh->b_data;
122: if(pp[0]!=0xed) /* check fragment signature */
123: { printk(KERN_ERR "DMSDOS: stac_cwalk_init: fragment signature not found cluster=%d\n",
124: clusternr);
125: raw_brelse(sb,bh);
126: return -1;
127: }
128: cw->fcnt=pp[1]+1; /* number of pieces */
129: if((cw->fcnt>dblsb->s_sectperclust)||(cw->fcnt*4>SECTOR_SIZE))
130: { printk(KERN_ERR "DMSDOS: stac_cwalk_init: too much fragmented cluster=%d!\n",
131: clusternr);
132: raw_brelse(sb,bh);
133: return -1;
134: };
135: cw->compressed=!(pp[2]&0x80);
136: v=cw->sect_cnt;
137: cw->sect_cnt+=(pp[2]&0x3F)+1;
138: for(i=1;i<cw->fcnt;++i)
139: { pp+=4;
140: u=(pp[2]&0xf)+((pp[3]>>2)&0x30);
141: v+=u+1;
142: };
143: last_sect=pp[0]+(pp[1]<<8)+((pp[3]&0x3f)<<16)+u; /* for suballocation tests */
144: if(v!=cw->sect_cnt)
145: { printk(KERN_ERR "DMSDOS: stac_cwalk_init: sector count mismash fragmented cluster=%d!\n",
146: clusternr);
147: raw_brelse(sb,bh);
148: return -1;
149: }
150: cw->fbh=bh;
151: cw->finfo=bh->b_data+4;
152: cw->offset=4*cw->fcnt;
153: cw->bytes=SECTOR_SIZE-cw->offset;
154: cw->bytes_in_clust=(cw->sect_cnt-1)*SECTOR_SIZE+cw->bytes;
155: break;
156:
157: case 0x5: /* ffff=101x, len<ClustSize, suballocated, regular file/dir(?) */
158: case 0x7: /* ffff=111x, deleted 5 */
159: case 0xd: /* ffff=101x, len=ClustSize, suballocated, regular file/dir(?) */
160: case 0xf: /* ffff=111x, deleted d */
161: if(flg==0) {cw->bytes_in_clust=0;cw->bytes=0;return 1;};
162: bh=raw_bread(sb,cw->start_sect);
163: if(bh==NULL)return -1;
164: pp=&(bh->b_data[SECTOR_SIZE-2]);
165: if(CHS(pp)!=0x1234)
166: { printk(KERN_ERR "DMSDOS: stac_cwalk_init: suballocation signature not found cluster=%d\n",
167: clusternr);
168: raw_brelse(sb,bh);
169: return -1;
170: }
171: if(cw->start_len==1)
172: { /* short suballocation */
173: pp = &(bh->b_data[SECTOR_SIZE-6]);
174: cw->offset= CHS(pp) & (SECTOR_SIZE - 1); /* begin of area */
175: cw->compressed= !(CHS(pp) & 0x8000);
176: if(CHS(pp)&0x4000)
177: { printk(KERN_ERR "DMSDOS: stac_cwalk_init: suballocation not present, cluster %d\n",
178: clusternr);
179: raw_brelse(sb,bh); return -1;
180: };
181: pp = &(bh->b_data[SECTOR_SIZE-8]);
182: cw->bytes=CHS(pp) & (SECTOR_SIZE - 1); /* end of area */
183: /* some more paranoic checking of allocated space */
184: if (cw->bytes&&(cw->bytes<=SECTOR_SIZE-8)&&(cw->bytes>cw->offset))
185: cw->bytes-=cw->offset;
186: else
187: { printk(KERN_ERR "DMSDOS: stac_cwalk_init: count = %d < 0 in short subalocated\n", cw->bytes);
188: printk(KERN_ERR "DMSDOS: cluster %d read error\n",clusternr);
189: raw_brelse(sb,bh); return -1;
190: }
191: cw->bytes_in_clust=cw->bytes;
192: last_sect=0;
193: }
194: else
195: { /* long suballocation */
196: pp = &(bh->b_data[SECTOR_SIZE-8]);
197: cw->offset = CHS(pp) & (SECTOR_SIZE - 1);
198: cw->compressed = !(CHS(pp) & 0x8000);
199: if(CHS(pp)&0x4000)
200: { printk(KERN_ERR "DMSDOS: stac_cwalk_init: suballocation not present, cluster %d\n",
201: clusternr);
202: raw_brelse(sb,bh); return -1;
203: };
204: cw->bytes=SECTOR_SIZE-cw->offset-8;
205: cw->bytes_in_clust+=cw->bytes-SECTOR_SIZE;
206: if (cw->bytes < 0) {
207: printk(KERN_ERR "DMSDOS: stac_cwalk_init: count = %d < 0 in long subalocated\n", cw->bytes);
208: printk(KERN_ERR "DMSDOS: cluster %d read error\n",clusternr);
209: raw_brelse(sb,bh); return -1;
210: }
211: };
212: raw_brelse(sb,bh);
213: break;
214:
215: case 0x9: /* ffff=001x, contradiction ??? */
216: case 0xb: /* ffff=011x, deleted 9 */
217: default:
218: printk(KERN_ERR "DMSDOS: stac_cwalk_init: unknown flags 0x%2x cluster %d\n",
219: mde.flags,clusternr);
220: return -1;
221: };
222:
223: /* if flg>=2 we are checking subalocated end of cluster */
224: /* because of we did not know if stacker can subalocate clusters
225: which are not in order we must check nonlinear
226: suballocation */
227: /* text above is question but now I know that stacker is able to do everything
228: nonlinear suballocation regulary exist */
229: if(last_sect&&(dblsb->s_cvf_version>=STAC4)&&(flg>=2))
230: { /* check for subalocated end of cluster */
231: /* 1) check start of next cluster for linear subalocation */
232: if(clusternr<dblsb->s_max_cluster)
233: { dbl_mdfat_value(sb,clusternr+1,NULL,&mde);
234: i=(mde.sector_minus_1+1)==last_sect;
235: if(i&&((mde.flags&0xA0)!=0xA0))
236: { printk(KERN_ERR "DMSDOS: stac_cwalk_init: wrong cluster types for subalocation, cluster %d\n",
237: clusternr);
238: return -1;
239: };
240: } else i=0;
241: /* 2) check for nonlinear subalocation */
242: if((u=dbl_bitfat_value(sb,last_sect,NULL))==0) if(flg>=3)goto error1;
243: if((u>1)||(i))
244: { if((u<=1)&&(flg>=3))
245: { printk(KERN_ERR "DMSDOS: stac_cwalk_init: suballocation error 1, cluster %d\n",
246: clusternr);
247: return -1;
248: };
249: if(!i)LOG_ALLOC("DMSDOS: stac_cwalk_init: nonlinear suballocation, cluster %d\n",
250: clusternr);
251: /* now we know that our cluster is subalocated, we must find
252: number of bytes in last sector of cluster */
253: bh=raw_bread(sb,last_sect);
254: if(bh==NULL)return -1;
255: pp=&(bh->b_data[SECTOR_SIZE-2]);
256: if(CHS(pp)!=0x1234)
257: { printk(KERN_ERR "DMSDOS: stac_cwalk_init: suballocation error 2, cluster %d\n",
258: clusternr);
259: raw_brelse(sb,bh);
260: return -1;
261: };
262: pp = &(bh->b_data[SECTOR_SIZE-6]); /* begin of short suball. clust */
263: u = CHS(pp) & (SECTOR_SIZE - 1);
264: pp = &(bh->b_data[SECTOR_SIZE-8]); /* begin of long suball. clust */
265: v = CHS(pp) & (SECTOR_SIZE - 1);
266: raw_brelse(sb,bh);
267: /* u contains number of bytes of our cluster in last_sect */
268: if(v<u)
269: {
270: pp = &(bh->b_data[SECTOR_SIZE-6]);u = CHS(pp);
271: pp = &(bh->b_data[SECTOR_SIZE-8]);v = CHS(pp);
272: printk(KERN_ERR "DMSDOS: stac_cwalk_init: suballocation error 3, cluster %d, zerro offset 0x%X 0x%X\n",
273: clusternr,u,v);
274: return -1;
275: };
276: cw->bytes_in_last=u;
277: if(cw->sect_cnt>1)
278: cw->bytes_in_clust-=SECTOR_SIZE-u;
279: else if((i=cw->bytes+cw->offset-cw->bytes_in_last)>0)
280: { if((cw->bytes-=i)<=0)
281: { printk(KERN_ERR "DMSDOS: stac_cwalk_init: suballocation error 4, cluster %d\n",
282: clusternr);
283: return -1;
284: };
285: cw->bytes_in_clust-=i;
286: };
287: cw->bytes_in_last|=0x4000;
288: };
289: };
290:
291: if ((i=cw->bytes_in_clust-dblsb->s_sectperclust*SECTOR_SIZE)>0)
292: { cw->bytes_in_clust-=i;
293: if(!cw->bytes_in_last) cw->bytes_in_last=SECTOR_SIZE-i;
294: else if((cw->bytes_in_last-=i)<0x4000)
295: { error1:
296: printk(KERN_ERR "DMSDOS: stac_cwalk_init: bad bytes_in_cluster %d\n",
297: clusternr);
298: return -1;
299: };
300: };
301:
302: return cw->bytes_in_clust;
303: };
304:
305: /* returns in order all sectors of cluster */
306: /* in Stac_cwalk updates fields sect, offset and bytes */
307: int stac_cwalk_sector(Stac_cwalk *cw)
308: { if(!cw->sect)
309: { if(!cw->fcnt) return 0;
310: cw->fcnt--;
311: cw->flen--;
312: cw->sect=cw->start_sect;
313: }
314: else
315: { if(!cw->flen)
316: { if(!cw->fcnt) return 0;
317: cw->fcnt--;
318: if(cw->finfo==NULL)
319: { printk(KERN_ERR "DMSDOS: stac_cwalk_sector: finfo==NULL, cluster %d\n",
320: cw->clusternr);
321: return 0;
322: };
323: cw->sect=cw->finfo[0]+(cw->finfo[1]<<8)+((cw->finfo[3]&0x3f)<<16);
324: cw->flen=(cw->finfo[2]&0xf)+((cw->finfo[3]>>2)&0x30);
325: cw->finfo+=4;
326: }
327: else
328: { cw->sect++;
329: cw->flen--;
330: };
331: cw->offset=0;
332: if(!cw->flen&&!cw->fcnt&&cw->bytes_in_last)
333: cw->bytes=cw->bytes_in_last&(SECTOR_SIZE-1);
334: else cw->bytes=SECTOR_SIZE;
335: };
336: return cw->sect;
337: };
338:
339: void stac_cwalk_done(Stac_cwalk *cw)
340: {
341: if(cw->fbh!=NULL) raw_brelse(cw->sb,cw->fbh);
342: };
343:
344:
345: void stac_special_free(struct super_block*sb, int clusternr)
346: {
347: int val;
348: int sect;
349: Mdfat_entry newmde,dummy_mde;
350: Stac_cwalk cw;
351: Dblsb*dblsb=MSDOS_SB(sb)->private_data;
352:
353: val=stac_cwalk_init(&cw,sb,clusternr,0);
354: if(val<=0)
355: { if(val<0)
356: printk(KERN_ERR "DMSDOS: stac_special_free: alloc error in cluster %d\n", clusternr);
357: else
358: LOG_CLUST("DMSDOS: stac_special_free: already free cluster %d\n", clusternr);
359: return;
360: };
361: newmde.sector_minus_1=-1;
362: newmde.size_lo_minus_1=0;
363: newmde.size_hi_minus_1=0;
364: newmde.flags=0;
365:
366: dbl_mdfat_value(sb,clusternr,&newmde,&dummy_mde);
367: if((cw.flags&0xA0)==0xA0)
368: { /* mark part of suballocated sector as free */
369: struct buffer_head *bh;
370: bh=raw_bread(sb,cw.start_sect);
371: if(bh!=NULL)
372: { if(cw.start_len==1)
373: bh->b_data[SECTOR_SIZE-6+1] |= 0x40;
374: else
375: bh->b_data[SECTOR_SIZE-8+1] |= 0x40;
376: raw_mark_buffer_dirty(sb,bh,1);
377: raw_brelse(sb,bh);
378: }
379: }
380: /* free sectors from BITFAT */
381: while((sect=stac_cwalk_sector(&cw))>0)
382: {
383: val=dbl_bitfat_value(sb,sect,NULL);
384: if(val>0)
385: { --val;
386: dbl_bitfat_value(sb,sect,&val);
387: dblsb->s_full=0;
388: /* adapt s_free_sectors, -1 unknown */
389: /*if(val==0&&dblsb->s_free_sectors>=0) dblsb->s_free_sectors++;*/
390: /* Hi Pavel,
391: I have commented this out since free sector count is now
392: maintained in dbl_bitfat_value.
393: */
394: } else LOG_CLUST("DMSDOS: stac_special_free: sector not alocated\n");
395: }
396:
397: stac_cwalk_done(&cw);
398:
399: }
400:
401: /* replaces an existing cluster for stacker;
402: this unusual function must be called before rewriting any file cluster;
403: *** size must be known (encoded in mde) ***
404: it does nothing if called too often;
405: returns first sector nr
406: */
407:
408: int stac_replace_existing_cluster(struct super_block*sb, int cluster,
409: int near_sector,
410: Mdfat_entry*mde)
411: { Mdfat_entry old_mde,new_mde,dummy;
412: int i;
413: int newval;
414: int sector;
415: int old_sector;
416: int old_size;
417: int new_size;
418: Dblsb*dblsb=MSDOS_SB(sb)->private_data;
419:
420: lock_mdfat_alloc(dblsb);
421:
422: LOG_ALLOC("DMSDOS: stac_replace_existing_cluster cluster=%d near_sector=%d\n",
423: cluster,near_sector);
424: dbl_mdfat_value(sb,cluster,NULL,&old_mde);
425: old_size=old_mde.size_lo_minus_1+1;
426: old_sector=old_mde.sector_minus_1+1;
427: new_size=mde->size_lo_minus_1+1;
428: if(old_mde.flags&2)
429: {
430: /* stacker routines always replace mdfat entry */
431: newval=0;
432: LOG_ALLOC("DMSDOS: stac_replace_existing_cluster: freeing old sectors...\n");
433: stac_special_free(sb,cluster);
434: LOG_ALLOC("DMSDOS: stac_replace_existing_cluster: freeing finished\n");
435: }
436: LOG_ALLOC("DMSDOS: stac_replace_existing_cluster: call find_free_bitfat...\n");
437: sector=find_free_bitfat(sb,near_sector,new_size);
438: LOG_ALLOC("DMSDOS: stac_replace_existing_cluster: find_free_bitfat returned %d\n",
439: sector);
440: if(sector<=0)
441: { if(old_mde.flags&2)
442: { /* Stacker routines don't have an undo list for now.
443: We cannot restore the state before. Sorry data are lost now. */
444: new_mde.sector_minus_1=0;
445: new_mde.size_lo_minus_1=0;
446: new_mde.size_hi_minus_1=0;
447: new_mde.flags=mde->flags=0;
448: LOG_ALLOC("DMSDOS: stac_replace_existing_cluster: deleting mdfat entry...\n");
449: dbl_mdfat_value(sb,cluster,&new_mde,&dummy);
450: }
451: unlock_mdfat_alloc(dblsb);
452: return -ENOSPC; /* disk full */
453: }
454: /* check whether really free (bug supposed in find_free_bitfat) */
455: for(i=0;i<new_size;++i)
456: { if(dbl_bitfat_value(sb,sector+i,NULL))
457: { printk(KERN_EMERG "DMSDOS: find_free_bitfat returned sector %d size %d but they are not all free!\n",
458: sector,new_size);
459: unlock_mdfat_alloc(dblsb);
460: panic("DMSDOS: stac_replace_existing_cluster: This is a bug - reboot and check filesystem\n");
461: return -EIO;
462: }
463: }
464: newval=1;
465: LOG_ALLOC("DMSDOS: stac_replace_existing_cluster: allocating in bitfat...\n");
466: for(i=0;i<new_size;++i)dbl_bitfat_value(sb,sector+i,&newval);
467:
468: new_mde.sector_minus_1=sector-1;
469: new_mde.size_lo_minus_1=mde->size_lo_minus_1;
470: new_mde.size_hi_minus_1=mde->size_hi_minus_1;
471: new_mde.flags=mde->flags|2;
472: LOG_ALLOC("DMSDOS: stac_replace_existing_cluster: writing mdfat...\n");
473: dbl_mdfat_value(sb,cluster,&new_mde,&dummy);
474: unlock_mdfat_alloc(dblsb);
475: return sector; /* okay */
476: }
477:
478: #endif /* DMSDOS_CONFIG_STAC */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.