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