· 5 years ago · Jul 04, 2020, 10:18 AM
1/** Central JTMOS File System aka JTMFS **/
2#include "kernel32.h"
3#include "jtmfs.h"
4#include "jtmfat.h"
5#include "flexFat.h"
6#include "createfat.h"
7#include "dir.h"
8#include "dirdb.h"
9#include "dirdbAccess.h" // DIRDB access functions
10#include "dirdbWalk.h" // DIRDB dir walking functions
11#include "writeDir.h"
12#include "dirdbAccess.h" // DIRDB access functions
13#include "dirdbInformation.h"
14#include "dirdbWalk.h"
15#include "dirdbCorruption.h"
16#include "dirdbFind.h"
17#include "dirdbInformation.h"
18//
19#include "sysmem.h"
20#include "macrodef.h"
21#include "int.h"
22#include "pit.h"
23#include "keyb.h"
24#include "syssh.h"
25#include "cmos.h"
26#include "floppy.h"
27#include "buildnr.h"
28// ---- #include "fileapi.h"
29#include "ramdisk.h"
30#include "jtmfs.h"
31#include "fswalk.h"
32#include "fsadd.h"
33#include "fsdos.h"
34#include "fname_translation.h"
35// ---- #include "fileapi.h"
36#include "ramdisk.h"
37#include "jtmfs.h"
38#include "fswalk.h"
39#include "fsaddblocks.h"
40#include "fsdos.h"
41#include "filedes.h" // From kernel32/fs (the generic file system, and its File System Support Submodules)
42#include "fsfind.h"
43#include "DirDB.h"
44
45#define ddprintk dprintk
46//#define ddprintk printk
47#include "fswalk.h"
48#include "fslast.h"
49#include "jtmfat.h"
50// ---- #include "fileapi.h"
51#include "jtmfs.h"
52#include "fswalk.h"
53#include "fsadd.h"
54#include "fsdos.h"
55#include "fname_translation.h"
56#include "jtmfsAccess.h"
57#include "jtmfsAccessInit.h"
58
59#include "sysmem.h"
60
61#include "fname_translation.h" // tell_fname
62#include "root.h"
63#include "jtmfsAccess.h"
64#include "jtmfsPath.h"
65#include "ReadChain.h"
66#include "WriteChain.h"
67#include "jtmfsAccessInit.h"
68#include "jtmfsAccess.h"
69#include "jtmfsPath.h"
70#include "dir.h"
71#include "flexCorruption.h"
72#include "ReadChain.h"
73#include "fsdos.h"
74#include "fname_translation.h" // tell_fname
75#include "root.h"
76#include "mount.h"
77//
78JTMFSACCESS jtmfsAccess;
79
80//
81int roll=0;
82//
83DIRDB dirdb;
84
85//=====================================================================================
86// Create FAT - FAT & info block creation.
87//
88// (C) 2003 by Jari Tuominen
89//
90// Note: The largest block size the FAT system can handle is 16K,
91// Formatting drives with larger than 16K blocks will lead into
92// corruption of the file system.
93// New: Now also creates more detailed information block,
94// which contains specific information about the file system,
95// kernel and boot loader configuration.
96// The present createfat also automatically detects standard
97// BIOS drives, e.g. A:, B:, C:, D: drives and writes
98// boot loader on the drive with appropriate configuration.
99//=====================================================================================
100
101// FAT CREATION
102// ------------
103//
104// - Allocates & writes a boot loader on the drive if is bootable.
105// - If drive is bootable, a 512K kernel region is reserved on the drive.
106// - Updates boot record.
107// - Updates information block.
108// - Creates a blank FAT table, JTMOS stylish.
109//
110// This function makes sure that most of it's writes and
111// works get done properly.
112//
113int jtmfat_createfat(int dnr)
114{
115 int i,i2,i3,i4,l,data1,v1,v2,
116 tick,tick2,trigger,trigger2;
117 BYTE *tmp,*p;
118 char *s,*s2;
119 int bytes_per_entry=4,bdrv;
120 BYTE *vali;
121 char devname[50];
122 JTMFAT_INFOBLOCK *inf;
123
124 //---------------------------------------------------------------------------------------------
125 if(jtmfat_ready!=TRUE)
126 return 10;
127
128 //
129 if(!isValidDevice(dnr))
130 {
131 printk("jtmfat_createfat: Invalid device %d.\n",
132 dnr);
133 return 11;
134 }
135
136 //
137 if( !getsize(dnr) )
138 {
139 panic("jtmfat_createfat: Size of the specified device is zero blocks.");
140 return 12;
141 }
142
143 //---------------------------------------------------------------------------------------------
144 // Get device name
145 driver_getdevicename(dnr, devname);
146
147 //////// FIRST FLUSH CACHE THEN WORK ///////////
148 printk("Flushing cache ...\n");
149 driver_TriggerCacheFlush();
150
151 //////////////////////////////////////////////////////////////////////////////////////////
152
153 // Convert to BIOS drive.
154 bdrv = DetermineBootdrv(devname);
155
156 // Which BIOS drive.
157 switch(bdrv)
158 {
159 //
160 case 0:
161 case 1:
162 printk("%s: is a floppy disk drive in BIOS standards.\n",
163 devname);
164 break;
165
166 //
167 case 0x80:
168 case 0x81:
169 case 0x82:
170 case 0x83:
171 printk("%s: is an IDE hard disk drive in BIOS standards.\n",
172 devname);
173 break;
174
175 //
176 default:
177 break;
178 }
179
180
181
182 // -------------------------------------------------------
183 // And now we need to store all this information on
184 // the bootblock.
185 // There is a slight problem, if the disk will be made
186 // bootable, it still needs to be JTMOS complaint,
187 // or it will not be accessible from JTMOS,
188 // so probably whetever a bootdisk will be accessed
189 // it'll always return invalid values because of
190 // the incorrect bootblock.
191 // However, the problem is not that big since,
192 // many bootdisks often only contain just the kernel image
193 // and perhaps a root ramdisk on it too, or on another disk.
194 // Perhaps this problem will be fixed in the future.
195 // For example slackware comes with two disks,
196 // boot(kernel) disk and the ramdisk image disk.
197
198 // Install boot loader.
199 InstallBootLoader(dnr, bdrv);
200
201 // Build information block.
202 inf = BuildInfoBlock(dnr, bdrv);
203 // Write on drive.
204 WriteInformationBlock(dnr, inf);
205
206 // -------------------------------------------------------
207
208 // We need to refresh the drive, to update boot block cache.
209 // DiskChange should not be called unless really needed,
210 // e.g. it causes current cached FAT to be lost,
211 // currently cached directories for the directory to be lost,
212 // everything will basically have to be re-read from the disk.
213 // Now before calling DiskChange, always a devapi flush should
214 // be called, to make sure the cache is flushed properly.
215 printk("Refreshing drive ...\n");
216 driver_TriggerCacheFlush();
217 DiskChange(dnr);
218
219 //
220 printk("Detection string(detstr) = '%s'.\n",
221 fatsys->bb[dnr]->detstr);
222
223 // ------ ALLOCATE SYSTEM AREA
224 // Allocate system area for system use only:
225 //
226 printk("Allocating system area 0-%d.\n", fatsys->bb[dnr]->sysarea_length);
227 l = fatsys->bb[dnr]->sysarea_length;
228 FastSetBlocks(dnr, 0,l, 0xFFFFFFF7);
229 // Verify.
230 for(i=0; i<l; i++)
231 {
232 // Peek for value.
233 if(jtmfat_getblock(dnr,i)!=0xFFFFFFF7)
234 {
235 // Wrong value detected:
236 printk("PASS I ERROR: FAT creation failed, could not write values on FAT table.\n");
237 return 1978;
238 }
239 }
240 // ------- SELF-DIAGNOSTIC 1
241 //
242 printk("System area reserved OK.\n");
243
244 // ------ FREE DATA AREA
245 // Free rest of blocks:
246 // Define range.
247 v1 = fatsys->bb[dnr]->sysarea_length;
248 v2 = getsize(dnr);
249 // This alittle long, so we have a percent done meter as well.
250 printk("Setting blocks free on FAT %d-%d.\n",
251 v1,v2);
252 FastSetBlocks(dnr, v1,v2, 0);
253 // Verify.
254 for(i=v1; i<v2; i++)
255 {
256 // Peek for value.
257 if(jtmfat_getblock(dnr,i)!=0)
258 {
259 // Wrong value detected:
260 printk("PASS II ERROR: FAT creation failed, could not write values on FAT table.\n");
261 return 1978;
262 }
263 }
264
265 // RELEASE A BLOCK FOR ROOT DIR...
266 // However, we will need to release the first block of the root directory
267 // for use(createdirectory will expect this from us)
268 printk("Releasing a block from FAT for rootdir on block #%d.\n", jtmfat_getrootdir(dnr));
269 jtmfat_setblock(dnr, jtmfat_getrootdir(dnr), 0);
270 //
271 driver_TriggerCacheFlush();
272
273 //
274 return 0;
275}
276
277// Build information block for a specified drive
278// on system boot block and return PTR to it.
279JTMFAT_INFOBLOCK *BuildInfoBlock(int dnr, int bdrv)
280{
281 int i,i2,i3,i4,l,data1,v1,v2,
282 tick,tick2,trigger,trigger2;
283 BYTE *tmp,*p;
284 char *s,*s2;
285 int bytes_per_entry=4;
286 BYTE *vali;
287 JTMFAT_INFOBLOCK *inf;
288
289 // BUILD INFO BLOCK, SPECIFY PARAMETERS
290 // ------------------------------------
291
292 //
293 if(getsize(dnr)<10)
294 {
295 return NULL;
296 }
297
298 //
299 inf = fatsys->bb[dnr];
300 memset(inf, 0, sizeof(JTMFAT_INFOBLOCK));
301
302 // Define boot area size in blocks.
303 inf->bootblock_size = (FAT_BOOT_SECTION_LEN_K*1024)/getblocksize(dnr);
304
305 // If we're building a system disk for hda, we also add
306 // 512K (1024 sectors) kernel image space.
307 if( (bdrv&0xF0)==0x80 )
308 {
309 // Reserve kernel image region.
310 inf->bootblock_size += KERNEL_LEN_K*1024/getblocksize(dnr);
311
312 // Specify kernel location.
313 inf->kernel_offs = FAT_BOOT_SECTION_LEN_K*1024/getblocksize(dnr);
314 }
315 else
316 // No kernel on this drive.
317 inf->kernel_offs = 0;
318
319 // FAT LENGTH (blocks)
320 // *X because one entry takes X bytes.
321 // Now we need to determine how many blocks the whole table for
322 // N sectors will take in blocks, we will add one/or more to it,
323 // so it will take at least the last possible half block space too.
324 inf->fat_length =
325 ((getsize(dnr)*bytes_per_entry)
326 / getblocksize(dnr)) + 2;
327 // 2 blocks for safety (minimum = 1)
328 // Max. FAT entry value allowed.
329 inf->max_val = getsize(dnr);
330
331 // SYSTEM AREA LENGTH (blocks).
332 inf->sysarea_length =
333 inf->bootblock_size + inf->fat_length + 10;
334
335 // FAT TABLE OFFSET (blocks)
336 // FAT begins after the boot block(offset=block offset=block #).
337 inf->fat_offs = inf->bootblock_size;
338
339 // DATA AREA OFFSET (blocks)
340 // Data area begins after the FAT area.
341 // (IS THE ROOT DIRECTORY AREA! -OR- _OPTIONALLY_ SOMETHING ELSE)
342 // data_offs = offset to the root directory.
343 inf->data_offs =
344 inf->fat_length + inf->bootblock_size + 9;
345 // 9 is a fixed number, see +10 above
346
347 // Store identifier.
348 strcpy(inf->detstr, "JTMFS");
349
350 //////////////////////////////////////////////////////////////////////////////////////////
351 // Display values
352/* ReportMessage("[:- FAT creation: fat_length=%d, sysarea_length=%d,
353 fat_offs=%d, data_offs=%d]\n",
354 inf->fat_length,
355 inf->sysarea_length,
356 inf->fat_offs,
357 inf->data_offs);*/
358
359 //
360 s = inf->detstr;
361 ReportMessage("Detection string(detstr) = '%s'.\n",
362 s);
363
364 // Error check
365 if(
366 inf->fat_length>getsize(dnr) ||
367 inf->sysarea_length>getsize(dnr) ||
368 inf->fat_offs>getsize(dnr) ||
369 inf->data_offs>getsize(dnr))
370 {
371 //
372 printk("FATAL LOGIC FAILURE: FAT CREATION FAILED, INVALID PARAMETERS DETECTED!\n");
373 return NULL;
374 }
375
376 //
377 return inf;
378}
379
380// Set correct values on a boot record.
381void BuildBootRecord(int dnr, BOOTRECORD *br, int bdrv)
382{
383 int i;
384
385 // Store offset to "kernel image on HD".
386 // Used by HD boot loader to locate kernel
387 // on the hard disk.
388 i = FAT_BOOT_SECTION_LEN_K*1024;
389 br->boot_len_k = i;
390 // Define drive CHS parameters
391 // (we should make a call to hard disk driver
392 // to figure out the correct parameters here!)
393 br->cylinders = 895;
394 br->heads = 5;
395 br->sectors = 55;
396 // Store boot drive variable.
397 br->bootdrv = bdrv;
398 // Store boot sector signature.
399 br->signature = 0xAA55;
400}
401
402// Determine which BIOS drive the device name refers to.
403int DetermineBootdrv(const char *devname)
404{
405 int bd;
406
407 // Determine BIOS boot drive.
408 if(!strcmp(devname,"hda"))
409 bd = 0x80;
410 else
411 if(!strcmp(devname,"hdb"))
412 bd = 0x81;
413 else
414 if(!strcmp(devname,"hdc"))
415 bd = 0x82;
416 else
417 if(!strcmp(devname,"hdd"))
418 bd = 0x83;
419 else
420 if(!strcmp(devname,"floppy"))
421 bd = 0;
422 else
423 if(!strcmp(devname,"floppy2"))
424 bd = 1;
425 else
426 {
427 // Default to floppy A: if unknown
428 // (boot sector loader will be not used on
429 // this media anyway, probably!)
430 bd = 0xFF;
431 printk("Note: This is a non-BIOS drive, therefore it does not support system boot up feature.\n");
432 }
433
434 //
435 return bd;
436}
437
438// Update information block on drive.
439void WriteInformationBlock(int dnr, JTMFAT_INFOBLOCK *inf)
440{
441 BYTE *tmp,*p;
442 int i,i2,i3,i4;
443
444 //
445 tmp = malloc(65536);
446
447 // Read block.
448 readblock(dnr, FAT_INFO_BLOCK_OFFS/getblocksize(dnr), tmp);
449 //
450 p=inf;
451 // Copy info block data to tmp.
452 i2 = FAT_INFO_BLOCK_OFFS % getblocksize(dnr);
453 for(i=0; i<sizeof(JTMFAT_INFOBLOCK); i++)tmp[i+i2]=p[i];
454
455 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
456 printk("%s: writeblock(DNR=%d, %d, tmp=0x%x)\n",
457 __FUNCTION__,
458 dnr, 0, tmp);
459 // Write info block data on disk(block #0).
460 if( writeblock(dnr, FAT_INFO_BLOCK_OFFS/getblocksize(dnr), tmp) )
461 {
462 //
463 printk("FAT creation failed: Could not write boot block.\n");
464 return 1987;
465 }
466 else
467 {
468 printk("Boot block written succesfully.\n");
469 }
470
471 //
472 free(tmp);
473}
474
475// Read information block from drive.
476void ReadInformationBlock(int dnr, JTMFAT_INFOBLOCK *inf)
477{
478 BYTE *tmp,*p;
479 int i,i2,i3,i4;
480
481 //
482 tmp = malloc(16384);
483
484 // Read block.
485 readblock(dnr, FAT_INFO_BLOCK_OFFS/getblocksize(dnr), tmp);
486 //
487 p=inf;
488 // Copy info block data to tmp.
489 i2 = FAT_INFO_BLOCK_OFFS % getblocksize(dnr);
490 for(i=0; i<sizeof(JTMFAT_INFOBLOCK); i++)p[i] = tmp[i+i2];
491
492 //
493 free(tmp);
494}
495
496// Set kernel checksum value on master boot record.
497void SetKernelChecksum(int dnr, WORD checksum)
498{
499 BYTE *tmp;
500 BOOTRECORD *br;
501 int i,i2,i3,i4;
502
503 // Allocate temporary memory.
504 tmp = malloc(1024*64);
505 memset(tmp, 0, 1024*64);
506 br = tmp;
507
508 //
509 readblock(dnr, 0, tmp);
510 tmp[512-11] = checksum&255;
511 tmp[512-10] = checksum>>8&255;
512 writeblock(dnr, 0, tmp);
513
514 //
515 free(tmp);
516}
517
518// Install boot loader.
519void InstallBootLoader(int dnr, int bdrv)
520{
521 BYTE *tmp,*p;
522 int i,i2,i3,i4;
523
524 // Allocate temporary memory.
525 tmp = malloc(1024*64);
526 memset(tmp, 0, 1024*64);
527
528 // Write boot loader on disk.
529 // --------------------------
530
531 // It's parameters will be changed later on this code.
532 memcpy(tmp, boot_bin, boot_bin_length);
533
534 // Correct 16-bit kernel checksum.
535 // (we don't know of any kernel yet, so we set it to zero).
536 tmp[512-11] = 0;
537 tmp[512-10] = 0;
538
539 // Store offset to "kernel image on HD".
540 // Used by HD boot loader to locate kernel
541 // on the hard disk.
542 i = FAT_BOOT_SECTION_LEN_K*1024;
543 tmp[512-9] = i &255;
544 tmp[512-8] = i >>8;
545 // Define drive CHS parameters
546 // (we should make a call to hard disk driver
547 // to figure out the correct parameters here!)
548 tmp[512-7] = 895 &255;
549 tmp[512-6] = 895 >>8;
550 tmp[512-5] = 5;
551 tmp[512-4] = 55;
552 // Store boot drive variable.
553 tmp[512-3] = bdrv;
554 // Store boot sector signature.
555 tmp[512-2] = 0x55;
556 tmp[512-1] = 0xAA;
557
558 // Write boot loader: Write block by block on disk.
559 for(i=(boot_bin_length/getblocksize(dnr))+1,p=tmp,i2=0; i; p+=getblocksize(dnr),i2++,i--)
560 {
561 writeblock(dnr, i2, p);
562 }
563
564 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
565 // FREE TMP
566 free(tmp);
567}
568
569// Writes kernel image on specified drive.
570void WriteKernel(int dnr, void *ker)
571{
572 int i,i2,l;
573 void *p;
574
575 // Write kernel on specified drive.
576 l = (1024*512) / getblocksize(dnr);
577 i2 = (FAT_BOOT_SECTION_LEN_K*1024) / getblocksize(dnr);
578 ReportMessage("Writing kernel on system drive . . ");
579 for(i=0,p=ker; i<l; i++,p+=getblocksize(dnr))
580 {
581 writeblock(dnr, i+i2, p);
582 }
583 ReportMessage("\n");
584 ReportMessage("%d blocks written.\n",
585 i);
586}
587
588// Determine 16-bit kernel checksum.
589WORD DetermineKernelChecksum(BYTE *buf, int len)
590{
591 WORD sum;
592 int i;
593
594 //
595 for(i=0,sum=0; i<len; i++)
596 sum+=buf[i];
597 return sum;
598}
599
600// Copy kernel from drive SRC to drive DST.
601// (currently source drive can be only the 1.44M system boot disk!!)
602int CopyKernel(const char *src, const char *dst)
603{
604 int dnr,sdnr,ad;
605 int i,i2,i3,i4,l;
606 void *p,*ker;
607
608 // Get output drive.
609 dnr = driver_getdevicenrbyname(dst);
610 if(dnr<=0)
611 return 1;
612
613 // Get source drive.
614 sdnr = driver_getdevicenrbyname(src);
615 if(sdnr<=0)
616 return 2;
617
618 //------------------------------------------------------------------------
619 //
620 ad = (FAT_BOOT_SECTION_LEN_K*1024) / getblocksize(dnr);
621
622 // Allocate temporary buffer for kernel image.
623 ker = malloc(1024*512);
624 memset(ker, 0, 1024*512);
625
626 // Read kernel from source.
627 l = (1024*512) / 512;
628 ReportMessage("Reading 512K kernel from boot floppy . . ");
629 for(i=0,p=ker; i<l; i++,p+=512)
630 {
631 if( readblock(sdnr, i+18, p) )
632 break;
633 }
634 ReportMessage("\n");
635
636 // Write kernel on drive.
637 WriteKernel(dnr, ker);
638
639 // Set new kernel checksum for boot loader.
640 SetKernelChecksum(dnr, DetermineKernelChecksum(ker, 1024*512));
641
642 // Free temporary space.
643 free(ker);
644
645 //
646 return 0;
647}
648
649
650
651//--------------------------------------------------------------------------------------------
652// Directory displayer kernel mode application.
653//--------------------------------------------------------------------------------------------
654// Dir function (ls)
655// -----------------
656//
657// This function outputs directory from specified block(linear) to stdout.
658int jtmfs_dir(int dnr, int which)
659{
660 BYTE *buf,*p;
661 WORD *wp;
662 DWORD *dwp,i,i2,i3,i4,ii,ii2,ii3,ii4,l;
663 JTMFS_FILE_ENTRY *fe;
664 int k;
665 DWORD ad;
666 int current_block;
667 char *str,*str2,*res1,*res2;
668 int totalBytes,totalFiles,totalDirs;
669 DIRWALK *dw;
670 int lastone;
671
672 //
673 dw = malloc(sizeof(DIRWALK));
674
675 // (TODO: add a dnr validity check here)
676 //
677 // JTMFS required
678 if(!jtmfat_isJTMFS(dnr))
679 {
680 //
681 printk("Looks like the drive is not JTMFS formatted.\n");
682 return 1;
683 }
684
685
686 // Note: this must be freed afterwards:
687 buf=malloc(16384);
688 //
689 str = malloc(256); str2 = malloc(256);
690 res1 = malloc(256); res2 = malloc(256);
691
692 // Begin walking
693 if( jtmfs_ffirst(dnr, which, dw) )return 1;
694
695 //
696 for(i=0,totalFiles=0,totalBytes=0,totalDirs=0,lastone=0;
697 ; i++)
698 {
699 // Get current dir entry
700 fe = dw->fe;
701
702 // Give user a possibility to stop the directory listing
703 if( (k = getch1())==27 )break;
704
705 // Is it a ghost?->continue without notifying it (deleted file)
706 // (ghost : length == -1 )
707 if( fe->length==-1 ) goto emptyEntry;
708
709 // Empty filename? -> End of dir.
710 if( !strlen(fe->name) )
711 {
712 break;
713 }
714
715 // --------- Start output string creation here: ----------
716 strcpy(res1,""); strcpy(res2,"");
717
718 //
719 switch(fe->type)
720 {
721 // DIRECTORY
722 case JTMFS_ID_DIRECTORY:
723 strcat(res1, "[");
724 break;
725 // FILE
726 default:
727 break;
728 }
729
730 // PRINT FILENAME
731 //
732 // Note: I show filename so that all spaces show correctly,
733 // this requires putting the filename inside '"'s.
734 sprintf(str, "%s", fe->name);
735 strcat(res1, str);
736
737 //
738 switch(fe->type)
739 {
740 // DIRECTORY
741 case JTMFS_ID_DIRECTORY:
742 totalDirs++;
743 strcat(res1, "]");
744 break;
745 // FILE
746 default:
747 totalFiles++;
748 totalBytes += fe->length;
749 sprintf(res2, "%d bytes", fe->length);
750 break;
751 }
752
753 // Print strings in a style
754 StretchPrint(res1, 30);
755 StretchPrint(res2, 15);
756 //
757 printk("\n");
758
759emptyEntry:
760 //
761 if( jtmfs_fnext(dnr, dw) )
762 break;
763 }
764
765 //
766 StretchPrint("", 10);
767 sprintf(res1, "%d File(s)", totalFiles);
768 StretchPrint(res1, 15);
769 sprintf(res1, "%d bytes", totalBytes);
770 StretchPrint(res1, 15);
771 printk("\n");
772 StretchPrint("", 10);
773 sprintf(res1, "%d Dir(s)", totalDirs);
774 StretchPrint(res1, 15);
775 sprintf(res1, "%d bytes", totalBytes);
776 StretchPrint(res1, 15);
777 printk("\n");
778 //
779 //printk("End of directory.\n");
780
781 //
782 free(buf); free(str); free(str2);
783 free(res1); free(res2);
784
785 //
786 free(dw);
787
788 //
789 return 0;
790}
791
792// ======================================================================
793// Enhanced directory cache database system,
794// aka EDCDS system.
795// (C) 2002-2005 by Jari Tuominen.
796//
797// This file contains only the init routine
798// and some few functions.
799// Other functions are located in seperate
800// dirdb* files.
801// ======================================================================
802
803//
804int dirdb_inited=0;
805
806//
807void pause(const char *s)
808{
809 printk(s);
810 ESCLOCK();
811}
812
813// Initialise DIRDB
814int dirdb_init(void)
815{
816 // --------------------------------------
817 int i,i2,i3,i4;
818
819 //
820 if(dirdb_inited)return 1;
821 dirdb_inited = 1;
822
823 // --------------------------------------
824 // Clear structure
825 memset(&dirdb, 0, sizeof(DIRDB));
826
827 // Set amount of directories in cache
828 dirdb.total = MAX_DIRS_CACHED;
829
830 // Set entries amount to zero
831 dirdb.n_entries = 0;
832
833 // Set state to free(for concurrency handling)
834 dirdb.state = 0;
835
836 // Set all directory entries free
837 for(i=0; i<dirdb.total; i++)
838 {
839 // Set guard variable
840 dirdb.dir[i].guard = DIRDB_GUARD;
841 // Set entry free
842 dirdb.dir[i].isfree = 1;
843 // Allocate data for dir data buffer
844 dirdb.dir[i].buf = malloc(MAX_BYTES_PER_DIR);
845 dirdb.dir[i].l_buf = MAX_BYTES_PER_DIR;
846 // Set type to directory
847 dirdb.dir[i].type = ID_DIRECTORY;
848 }
849
850 // No cache flush request at the start up.
851 dirdb.cacheFlushRec = 0;
852
853 //
854 return 0;
855}
856
857
858// =====================================================================
859// Directory Database Access Functions - EDCDS DATABASE ACCESS FUNCTIONS.
860// (C) 2002-2005 by Jari Tuominen.
861// =====================================================================
862
863// This function is called upon disk
864// changes(removable storage devices).
865void dirdb_DiskChange(int dnr)
866{
867 //
868 dirdb_clearCacheForDNR(dnr);
869}
870
871// Clears DIRDB cache for a specified DNR
872// This funtion is called by e.g. IRQ handlers,
873// therefore it must be kept quick and simple.
874void dirdb_clearCacheForDNR(int dnr)
875{
876 DIR *d;
877 int i,i2,i3,i4;
878 int flags;
879
880 //
881 DIRDEBUG
882
883 // Find all DNR's entries and deallocate these
884 for(i=0; i<dirdb.n_entries; i++)
885 {
886 //
887 d = &dirdb.dir[i];
888
889 //
890 if( d->dnr==dnr )
891 {
892 d->isfree = 1;
893 d->dnr = -1;
894 d->db = -1;
895 }
896 }
897}
898
899//
900void dirdb_clearCacheForDBEx(int dnr, int db)
901{
902 DIR *d;
903
904 //
905 DIRDEBUG
906
907 // Check validity
908 if(dnr<0 || db<0)return;
909
910 // Type 0 means = Any
911 if( (d=dbGiveDir(dnr, db, 0)) )
912 {
913 d->isfree = 1;
914 d->dnr = -1;
915 d->db = -1;
916 }
917}
918
919//
920void dirdb_clearCacheForDB(int dnr, int db)
921{
922 //
923 DIRDEBUG
924
925 // Check validity
926 if(!isValidDevice(dnr) || db<0)
927 return;
928
929 //
930 if(dbGiveDir(dnr,db,0)) // Type 0 = Any
931 {
932 FlushAll(); // ?????????? Is this allowed?
933 dirdb_clearCacheForDBEx(dnr, db);
934 }
935}
936
937//
938int getAlreadyFreeDBEntry(void)
939{
940 static int i,i2,i3,i4,id,req;
941
942 //
943 DIRDEBUG
944
945 // Warning: a possible endless loop.
946 i4=roll&3; roll++;
947retry:
948 //
949 for(i=0; i<dirdb.n_entries; i++)
950 {
951 if(dirdb.dir[i].isfree)
952 return i;
953 }
954
955 // Already too much allocated?
956 if(dirdb.n_entries>=MAX_DIRS_CACHED/2)
957 {
958 // Determine a fair requirement, 1/3 of space must be free
959 req = dirdb.n_entries/3; if(!req)req++;
960 // Make some space, deallocate ~10 entries
961 for(i=0,i2=0; i<dirdb.n_entries && i2<req; i++)
962 {
963 if(!dirdb.dir[i].isfree && !dirdb.dir[i].flushRequired
964 && ((i+i4)&3)==0)
965 {
966 free(dirdb.dir[i].buf);
967 dirdb.dir[i].l_buf=0;
968 dirdb.dir[i].isfree=1;
969 i2++;
970 }
971 }
972
973 //
974 i4++;
975 if(i4>=10) goto alloc;
976 goto retry;
977 }
978
979alloc:
980 // In cases when we afford to suggest allocation, we do so:
981 return -1;
982}
983
984//
985int reserveNewDBEntry(void)
986{
987 static int i;
988
989 //
990 DIRDEBUG
991
992 //
993 if(dirdb.n_entries>=dirdb.total)
994 {
995 panic("reserveNewDBEntry: TODO #1.");
996 }
997
998 //
999 i = dirdb.n_entries;
1000 dirdb.n_entries++;
1001 return i;
1002}
1003
1004// New: now deallocates a few entries if none is found.
1005int getFreeDBEntry(void)
1006{
1007 static int i,id;
1008
1009 //
1010 DIRDEBUG
1011
1012 //
1013 id = getAlreadyFreeDBEntry();
1014 if(id==-1)
1015 {
1016 // Reserve new entry
1017 id = reserveNewDBEntry();
1018 }
1019 return id;
1020}
1021
1022// touchDir dnr, db
1023//
1024// This function "touches" a directory on the database,
1025// if it does not exist on the database then it'll get it,
1026// so it is there on the fly, this makes it look for
1027// the caller like the directory would've been
1028// there all the time.
1029DIR *touchDir(int dnr, int db, int type)
1030{
1031 static DIR *d;
1032
1033 //
1034 DIRDEBUG
1035
1036 //
1037 dirdbCorruptionCheck();
1038
1039 // If not valid device, just return NULL
1040 if(!isValidDevice(dnr))return NULL;
1041
1042 // Check for corruption
1043 FFCHECK
1044
1045 //
1046 if( (d=dbGiveDir(dnr, db, type))==NULL )
1047 {
1048 //
1049 ddprintk("%s: Caching directory %d/%d\n",
1050 __FUNCTION__,
1051 dnr,db);
1052 return copyDirToDB(dnr,db, type);
1053 }
1054
1055 //
1056 return d;
1057}
1058
1059// Returns NULL if dir is not in the database.
1060DIR *dbGiveDir(int dnr, int db, int type)
1061{
1062 static int i;
1063 static DIR *d;
1064
1065 // If not valid device, just return NULL
1066 if(!isValidDevice(dnr)) return NULL;
1067
1068 //
1069 FFCHECK
1070 DIRDEBUG
1071
1072 //
1073 ddprintk("%s: Searching through cache (%d entries) for %d/%d\n",
1074 __FUNCTION__,
1075 dirdb.n_entries,
1076 dnr,db);
1077
1078 //
1079 for(i=0; i<dirdb.n_entries; i++)
1080 {
1081 d = &dirdb.dir[i];
1082 if(!d->isfree
1083 &&
1084 d->dnr==dnr
1085 &&
1086 d->db==db
1087 &&
1088 (d->type==type || type==0)) // type 0 = Any type
1089 {
1090 ddprintk("%s: Found entry %d,%d\n",
1091 __FUNCTION__,
1092 d->dnr, d->db);
1093 return d;
1094 }
1095 }
1096 ddprintk("%s: Entry %d,%d not found\n",
1097 __FUNCTION__,
1098 dnr, db);
1099 return NULL;
1100}
1101
1102// Copy [file or directory] to database
1103DIR *copyDirToDB(int dnr, int db, int type)
1104{
1105 DIR *d;
1106 static int i,i2,i3,i4;
1107
1108 DIRDEBUG
1109
1110 //
1111 if( !isValidDevice(dnr) ) return NULL;
1112
1113 // Check if it is there already
1114 if( (d=dbGiveDir(dnr, db, type))!=NULL )
1115 {
1116 return d;
1117 }
1118
1119 // Find free entry in database
1120 i = getFreeDBEntry();
1121
1122 // Get the structure PTR
1123 d = &dirdb.dir[i];
1124
1125 // Set it as reserved
1126 d->isfree=0;
1127 // Specify location
1128 d->dnr = dnr;
1129 d->db = db;
1130 // Specify type
1131 d->type = type;
1132
1133 // Clear the buffer first
1134 memset(d->buf, 0, d->l_buf);
1135
1136 // Read directory/file contents
1137 readDir(d);
1138
1139 // Return directory PTR
1140 return d;
1141}
1142
1143//
1144int db_ReadDirectory(int dnr,int db,
1145 BYTE *buf,int l_buf)
1146{
1147 BYTE *tmp;
1148 int l_tmp;
1149 int i,i2,i3,i4,ad,ad2,lba,x,bsz;
1150
1151 // Device configuration...
1152 if(!isOK(dnr)) { return 0; }
1153 bsz = getblocksize(dnr);
1154
1155 //
1156 tmp = malloc(65536);
1157
1158 //
1159 for(lba=db,ad=0; ; )
1160 {
1161 //
1162 readblock(dnr,lba,tmp);
1163
1164 //
1165 for(x=0; x<bsz && ad<l_buf; x++)
1166 {
1167 buf[ad++] = tmp[x];
1168 }
1169
1170 //
1171 if(ad>=l_buf) break;
1172
1173 //
1174 lba = jtmfat_getblock(dnr,lba);
1175 if( jtmfs_LastBlock(lba) ) break;
1176 }
1177
1178 //
1179}
1180
1181
1182// Reads directory into a DIR* structure.
1183int readDir(DIR *d)
1184{
1185 int blocks_read;
1186
1187 DIRDEBUG
1188
1189 //
1190 if(d==NULL)
1191 return 1;
1192
1193 //
1194 ddprintk("%s: Reading directory dnr=%d, db=%d, buf=0x%x\n",
1195 __FUNCTION__,
1196 d->dnr, d->db,
1197 d->buf);
1198
1199 // For files, do some modifications:
1200 if(d->type==ID_FILE)
1201 {
1202 // Make some space for a file
1203 if(d->l_buf < MAX_CACHED_FILE_SIZE)
1204 {
1205 if(d->buf!=NULL) free(d->buf);
1206 d->buf = malloc(1024*128);
1207 d->l_buf = 1024*128;
1208 }
1209 }
1210
1211 // Read directory from chain
1212 memset(d->buf, 0, d->l_buf);
1213 blocks_read = db_ReadDirectory(d->dnr,d->db, d->buf,d->l_buf);
1214 // d->buf, d->dnr, d->db, d->l_buf, 0);
1215 // jtmfs_ReadFileChain
1216
1217 // Define amount of blocks cached
1218 d->blocks = blocks_read;
1219
1220 // Determine amount of entries directory has
1221 if(d->type=ID_DIRECTORY)
1222 {
1223 d->n_entries = countEntries(d);
1224 ReportMessage("%s: %d entries detected for this directory.\n",
1225 __FUNCTION__,
1226 d->n_entries);
1227 dsleep(1);
1228 }
1229
1230 //
1231 return 0;
1232}
1233
1234// Flush directory database as needed
1235int dirdbFlush(void)
1236{
1237 int i,i2,c;
1238 DIR *d;
1239
1240 DIRDEBUG
1241
1242 // Wait until ready
1243 disable();
1244 while(1)
1245 {
1246 // Some prg currently using db?
1247 if(dirdb.state!=1)break;
1248 SwitchToThread();
1249 }
1250 // Save old state
1251 dirdb.l_state = dirdb.state;
1252 // Set state as "flush"
1253 dirdb.state = 2;
1254 //
1255 enable();
1256
1257 // Flush all dirs that are needed to
1258 for(i=0,c=0; i<dirdb.n_entries; i++)
1259 {
1260 d = &dirdb.dir[i];
1261 if(!d->isfree
1262 &&
1263 d->flushRequired)
1264 {
1265 // Flush only if it is allocated, otherwise report it
1266 if(!d->isfree)
1267 writeDir(d);
1268 else
1269 ddprintk("%s: WARNING! Can't flush freed entry.\n",
1270 __FUNCTION__);
1271 c++;
1272 d->flushRequired=0;
1273 }
1274 }
1275
1276 //
1277 ddprintk("%d dir(s) flushed.\n", c);
1278
1279 // Restore state
1280 dirdb.state = dirdb.l_state;
1281
1282 // OK
1283 return 0;
1284}
1285
1286// countEntries d
1287//
1288// This function determines how many
1289// directory entries there are
1290// and returns the amount as an integer.
1291int countEntries(DIR *d)
1292{
1293 int i;
1294 char *p,*e;
1295 JTMFS_FILE_ENTRY *fe;
1296
1297 DIRDEBUG
1298
1299 //
1300 if(d==NULL) return 0;
1301
1302 // Determine location of end of the buffer
1303 e = d->buf; e+=d->l_buf;
1304 // Count entries
1305 for(p=d->buf,i=0; ; p+=sizeof(JTMFS_FILE_ENTRY),i++)
1306 {
1307 // Get fe PTR
1308 fe = p;
1309
1310 // Unexpected end?
1311 if(p>=e)break;
1312
1313 // Last entry reached?
1314 if(!fe->name[0])
1315 return i;
1316
1317 //
1318 if(fe->type==JTMFS_ID_DIRNAME)
1319 {
1320 printk(">>>> \"%s\" <<<<\n", fe->name);
1321 // sleep(10);
1322 }
1323
1324 // If magicNumber is wrong, we assume this directory
1325 // is entirely broken, we will therefore report 0 files.
1326 // The caller of this function should understand
1327 // "Return Value 0" as an indication of the fact that
1328 // the directory is corrupted, and therfore should be
1329 // ignored and/or fixed.
1330 if(fe->magicNumber!=0xFCE2E37B)
1331 {
1332 // Corrupted directory detected:
1333 return 0;
1334 }
1335 }
1336 return 0;
1337}
1338
1339//
1340void dirdbCorruptionCheck(void)
1341{
1342}
1343
1344
1345
1346//======================================================
1347// EDCDS DATABASE WALKING FUNCTIONS
1348// (C) 2002-2005 by Jari Tuominen(jari@vunet.org).
1349//======================================================
1350
1351// Search for a regular file or directory.
1352int dirdb_ffindfile(int dnr,
1353 const char *fname, int db, DIRWALK *dw)
1354{
1355 //
1356 return dirdb_ffindfileEx(dnr, fname, db, dw, 0);
1357}
1358
1359// Search for a deleted file entry.
1360int dirdb_ffindghostfile(int dnr,
1361 const char *fname, int db, DIRWALK *dw)
1362{
1363 //
1364 return dirdb_ffindfileEx(dnr, fname, db, dw, 1);
1365}
1366
1367// Search for directory name definition,
1368// which indicates directory name.
1369// (parameter fname is ignored, use NULL) DIRWALK *dw
1370int dirdb_ffinddirname(int dnr, const char *name, int db, DIRWALK *dw)
1371{
1372 //
1373 return dirdb_ffindfileEx(dnr, NULL, db, dw, 2);
1374}
1375
1376// Search for a specified file or directory.
1377// ghost=0 means: Search for non-deleted files only.
1378// ghost=1 means: Search for deleted files only.
1379// ghost=2 means: Search for directory names only.
1380// Return value: zero if not found...
1381int dirdb_ffindfileEx(int dnr,
1382 const char *fname, int db, DIRWALK *dw,
1383 int ghost)
1384{
1385 static char *p,*p2;
1386 static DIR *dir;
1387 static int i,i2;
1388 static JTMFS_FILE_ENTRY *fe;
1389
1390 // Get directory
1391 dir = touchDir(dnr, db, ID_DIRECTORY);
1392 if(dir==NULL)return 0;
1393
1394 // Go through all entries and look for requested file
1395 for(i=0,p=dir->buf; *p; p+=sizeof(JTMFS_FILE_ENTRY))
1396 {
1397 //
1398 fe = p;
1399
1400 //
1401 if( fname!=NULL && !strcmp(fe->name, fname) )
1402 {
1403 // Ignore this directory name indicator.
1404 if( fe->type==JTMFS_ID_DIRNAME )
1405 continue;
1406
1407 // Ghost filter:
1408 // If searching for scratched files and entry is not scratched, then skip it.
1409 if( ghost && fe->length!=-1 ) continue;
1410 // Disallow using DIRNAME entry, even if it is marked deleted(it is really not :).
1411 if( fe->type==JTMFS_ID_DIRNAME && ghost!=2 ) continue;
1412 // If not searching for special entries and file is scratched, then skip it.
1413 if( !ghost && fe->length==-1 ) continue;
1414
1415 // Found requested file:
1416 // --------------------------------------
1417 if(dw!=NULL)
1418 {
1419 // Init dw structure.
1420 jtmfs_ffirst(dnr,db, dw);
1421 // Modify structure to point to this find.
1422 dw->d = dir;
1423 dw->fe = fe;
1424 }
1425 //
1426 printk("<<%s!>>", fe->name);
1427 // Return:
1428 return 1;
1429 }
1430
1431 }
1432
1433 // Requested file not found:
1434 return 0;
1435}
1436
1437// Figure out what is the name of the directory at specified location.
1438// Return value: FALSE if not found, TRUE if found.
1439int dirdb_GetDirName(int dnr,int db, char *dest_name)
1440{
1441 static char *p,*p2;
1442 static DIR *dir;
1443 static int i,i2;
1444 static JTMFS_FILE_ENTRY *fe;
1445
1446 // Get directory
1447 dir = touchDir(dnr, db, ID_DIRECTORY);
1448 if(dir==NULL)
1449 return FALSE;
1450
1451 // Go through all entries and look for requested file
1452 for(i=0,p=dir->buf; *p; p+=sizeof(JTMFS_FILE_ENTRY))
1453 {
1454 //
1455 fe = p;
1456
1457 //
1458 if(fe->type==JTMFS_ID_DIRNAME)
1459 {
1460 //
1461 printk("%s: Found DIRNAME entry for %d/%d, content='%s'(0x%x), type=0x%x.\n",
1462 __FUNCTION__, dnr,db,
1463 fe->name,fe->name, fe->type);
1464 printk("size of JTMFS_FILE_ENTRY = %d bytes\n",
1465 sizeof(JTMFS_FILE_ENTRY));
1466
1467 // Found requested file:
1468 // --------------------------------------
1469 strcpy(dest_name, fe->name);
1470
1471 // Return:
1472 return TRUE;
1473 }
1474
1475 //
1476 }
1477
1478 // Requested file not found:
1479 return FALSE;
1480}
1481
1482
1483// ========================================
1484// ENHANCED DIRECTORY CACHE DATABASE SYSTEM
1485// AKA EDCDS SYSTEM
1486// (C) 2002-2004 by Jari Tuominen.
1487//
1488// This file contains only the init routine
1489// and some few functions.
1490// Other functions are located in seperate
1491// dirdb* files.
1492// ========================================
1493
1494// Show DIRDB information
1495int dirdbInformation(void)
1496{
1497 int i,i2;
1498 DIR *d;
1499 char str[100];
1500
1501 //
1502 printk("----------------------------------------------------------\n");
1503 printk("EDCDS CACHE SYSTEM REPORT\n");
1504 printk("%d directories cached\n",
1505 dirdb.n_entries);
1506
1507 //
1508 for(i=0; i<dirdb.n_entries; i++)
1509 {
1510 //
1511 d = &dirdb.dir[i];
1512
1513 //
1514 driver_getdevicename(d->dnr, str);
1515
1516 //
1517 printk("%d: Drive %s: (%d/%d) contains %d dir entries guard=%s\n",
1518 i,
1519 str,
1520 d->dnr,
1521 d->db,
1522 countEntries(d),
1523 d->guard==DIRDB_GUARD ? "valid" : "INVALID");
1524 }
1525
1526 //
1527 printk("End of list.\n");
1528
1529 //
1530 return 0;
1531}
1532
1533
1534// =====================================================
1535// EDCDS DATABASE WALKING FUNCTIONS
1536// (C) 2002-2005 by Jari Tuominen(jari@vunet.org).
1537// =====================================================
1538
1539// Marks directory currently being assigned
1540// as one that contains changed data within.
1541int dirdb_flushRequirement(DIRWALK *dw)
1542{
1543 DIRDEBUG
1544
1545 //
1546 if(dw!=NULL && dw->d)
1547 {
1548 dw->d->flushRequired=1;
1549 }
1550 else
1551 {
1552 printk("%s: CANNOT SETUP FLUSH REQUIREMENT BIT\n",
1553 __FUNCTION__);
1554 printk("%s: dw=0x%x, dw->d=0x%x (either one is NULL)\n",
1555 __FUNCTION__,
1556 dw, dw->d);
1557 dsleep(1);
1558 }
1559 return 0;
1560}
1561
1562// Steps over a dir entry
1563// (Moves to next entry)
1564// Return value: Returns nonzero
1565// if attempting to exceed the block boundary.
1566int dirdb_stepover(int dnr, DIRWALK *dw)
1567{
1568 char *e,*p;
1569
1570 //
1571 if(dw==NULL || !dw->isWalking) return 2;
1572
1573 //
1574 DIRDEBUG
1575
1576 // Exceeding allowed amount of entries?
1577 if(dw->entry>=MAX_ENTRIES_PER_DIR)
1578 {
1579 // Already skipped too far!:
1580 return 1;
1581 }
1582
1583 // Determine end
1584 e = dw->d->buf; e+=dw->d->l_buf;
1585 // Advance
1586 p = dw->fe;
1587 p+=sizeof(JTMFS_FILE_ENTRY);
1588 dw->fe=p;
1589 dw->current_offset+=sizeof(JTMFS_FILE_ENTRY);
1590
1591 // Next entry #
1592 dw->entry++;
1593
1594 // End of area?
1595 if(p>=e) return 2;
1596
1597 //
1598 return 0;
1599}
1600
1601// Valid Return Values are:
1602// ------------------------
1603// 1=End of dir and chain.
1604// 2=End of dir(entry is zero based)
1605// 0=New entry loaded
1606//
1607// Returns end on last entry,
1608// the last entry is delivered with
1609// the return value 2,
1610// meaning last entry on the directory.
1611int dirdb_fnext(int dnr, DIRWALK *dw)
1612{
1613 char *p,*e;
1614 JTMFS_FILE_ENTRY *fe;
1615
1616 //
1617 if(dw==NULL || !dw->isWalking) return 2;
1618
1619 //
1620 DIRDEBUG
1621
1622 // Try to step over, if not possible then return end
1623 if( dirdb_stepover(dnr, dw) ) return 2;
1624
1625 // -> Check what location contains(CHECK 1/2)
1626 // End on following conditions:
1627 // - file name is empty
1628 // - magicNumber mistach
1629 if(dw->fe->name[0]==0 || dw->fe->magicNumber!=0xFCE2E37B)
1630 {
1631 // End of directory.
1632 return 2;
1633 }
1634
1635/* // Check what next location contains II
1636 p=dw->fe; p+=sizeof(JTMFS_FILE_ENTRY); fe=p;
1637 if(fe->name[0]==0)
1638 {
1639 return 2;
1640 }*/
1641
1642 // OK
1643 return 0;
1644}
1645
1646// Not needed to be emulated.
1647/* void dirdb_fend(DIRWALK *dw) { } */
1648
1649// walks to the first dir entry and receives it
1650// note: will return nonzero on error
1651//
1652// new feature: if dirblock == -1 then
1653// the dirwalking will be resetted
1654// back to the starting block dw->start_block
1655//
1656int dirdb_ffirst(int dnr,
1657 int dirblock, DIRWALK *dw)
1658{
1659 int block;
1660
1661 //
1662 if(!isValidDevice(dnr) || dw==NULL)
1663 return 1;
1664
1665 //
1666 if(dirblock==-1)
1667 {
1668 block = dw->start_block;
1669 }
1670 else block = dirblock;
1671
1672 //
1673 DIRDEBUG
1674
1675 // Get directory
1676 dw->d = touchDir(dnr, block, ID_DIRECTORY);
1677
1678 // Go to the first entry of the directory
1679 dw->fe = dw->d->buf;
1680 dw->start_block = block;
1681 dw->current_block = block;
1682
1683 // Reset offset
1684 dw->current_offset = 0;
1685
1686 // Setup walking mode
1687 dw->isWalking=1;
1688
1689 // Entry to 0
1690 dw->entry = 0;
1691
1692 // Return OK
1693 return 0;
1694}
1695
1696//
1697
1698
1699// Advanced Flex FAT: FAT Database
1700#include "kernel32.h"
1701#include "jtmfs.h"
1702#include "jtmfat.h"
1703#include "flexFat.h"
1704#include "flexCorruption.h"
1705
1706//----------------------------------------------------------------
1707// FlexFAT system report
1708//
1709void jtmfatInformation(void)
1710{
1711 int dnr;
1712
1713 // Check HDA
1714 dnr = driver_getdevicenrbyname("hda");
1715 jtmfatInformation1(&fle->FAT[dnr], "Hard Disk Drive");
1716
1717 // Check
1718 dnr = driver_getdevicenrbyname("ram");
1719 jtmfatInformation1(&fle->FAT[dnr], "RAM Disk Drive");
1720}
1721
1722// Check FAT structure's status
1723// FALSE = corrupted
1724// TRUE = uncorrupted, or information unavailable
1725int checkFat(FLEFAT *e)
1726{
1727 // Skip inactive FATs
1728 if(e->isOK==FALSE)
1729 return TRUE;
1730
1731 // Check guard DWORD
1732 if(e->guard!=FLFGUARD)
1733 return FALSE;
1734
1735/* // Check buffer #1
1736 if( fixalCheck(e->buf, e->l_buf)==FALSE )
1737 return FALSE;
1738
1739 // Check buffer #2
1740 if( fixalCheck(e->writemap, e->l_writemap)==FALSE )
1741 return FALSE;*/
1742
1743 // OK:
1744 return TRUE;
1745}
1746
1747// FlexFAT general corruption check
1748int ffCheck(const char *fn, const char *func, int line)
1749{
1750 int dnr;
1751 static char str[256],name[256];
1752 FLEFAT *e;
1753 int i;
1754 static char *drives[]={"ram","hda","*"};
1755 static int *dnrs[100]={-1};
1756
1757 //
1758 if(flexActive!=TRUE)
1759 return 1;
1760
1761 //
1762 return 0;
1763
1764 //
1765 for(i=0; strcmp(drives[i],"*"); i++)
1766 {
1767 // Check HDA
1768 if( (dnr=dnrs[i])==-1 )
1769 dnrs[i] = dnr = driver_getdevicenrbyname(drives[i]);
1770 if(dnr==-1)
1771 continue;
1772 e = &fle->FAT[dnr];
1773
1774 // Check one
1775// FLEXCHECK(e);
1776
1777 // Check two
1778 if(checkFat(e)==FALSE)
1779 {
1780 //
1781 driver_getdevicename(dnr, name);
1782 sprintf(str, "error: file %s, function %s, line %d -- FAT failure on device %s",
1783 fn, func, line,
1784 name);
1785 panic(str);
1786 }
1787 }
1788
1789 //
1790 return 0;
1791}
1792
1793// Reporter function
1794void jtmfatInformation1(FLEFAT *e, const char *name)
1795{
1796 int i,i2,i3,i4;
1797
1798 // Skip inactive FATs
1799 if(e->isOK==FALSE)
1800 return;
1801
1802 // Print descriptions
1803 printk("-------------------------------------------------------------\n");
1804 printk("REPORT FOR: %s\n", name);
1805 printk("Data PTR Data length WMAP WMAP length DNR/BNR GUARD\n");
1806
1807 // Print values
1808 printk("%x %x %x %x %d/%d %x amount=%d\n",
1809 e->buf, e->l_buf, e->writemap,
1810 e->l_writemap, e->dnr,e->bnr, e->guard,
1811 e->amount);
1812
1813 // Check guard DWORD
1814 if(e->guard!=FLFGUARD)
1815 {
1816 //
1817 printk("WARNING: entry guard variable is incorrect. This most probably indicates a corrupted FAT structure.\n");
1818 printk("%x != %x\n",
1819 e->guard, FLFGUARD);
1820 }
1821
1822/* // Check buffer #1
1823 if( fixalCheck(e->buf, e->l_buf)==FALSE )
1824 {
1825 //
1826 printk("e->buf guard is invalid, this indicates a buffer corruption.\n");
1827 }
1828
1829 // Check buffer #2
1830 if( fixalCheck(e->writemap, e->l_writemap)==FALSE )
1831 {
1832 //
1833 printk("e->writemap guard is invalid, this indicates a buffer corruption.\n");
1834 }*/
1835}
1836
1837
1838
1839// ------------------------------------------------------------------
1840// Flex FAT Main - Flexible FAT system.
1841// (C) 2002-2005 by Jari Tuominen.
1842// ------------------------------------------------------------------
1843
1844//
1845char flextmp[256];
1846
1847// Flex FAT main structure
1848FLEFATSYS *fle;
1849int flexActive=FALSE;
1850
1851//
1852void flexHealthCheck(void)
1853{
1854 int dnr,i;
1855 char *walk[]={
1856 "hda",
1857 "ram",
1858 "*"
1859 };
1860
1861 //
1862 for(i=0; strcmp(walk[i], "*"); i++)
1863 {
1864 dnr = driver_getdevicenrbyname(walk[i]);
1865 if(dnr!=-1)
1866 {
1867 AnalyzeFAT(&fle->FAT[dnr]);
1868 }
1869 }
1870}
1871
1872//----------------------------------------------------------------
1873// Initialize flex fat system
1874//
1875void flexFatInit(void)
1876{
1877 int i;
1878 FLEFAT *f;
1879
1880 //
1881 fle = procmalloc(sizeof(FLEFATSYS), 0, __FUNCTION__);
1882 if(fle==NULL)
1883 panic("NULL ptr case 12");
1884
1885 // Reset main structure
1886 memset(fle,0,sizeof(FLEFATSYS));
1887
1888 //
1889 for(i=0; i<N_MAX_FATS; i++)
1890 {
1891 //
1892 f = &fle->FAT[i];
1893
1894 //
1895 f->isOK = FALSE;
1896 }
1897
1898 //
1899 flexActive = TRUE;
1900
1901 //
1902// addPitHandler(AnalyzeFATs);
1903}
1904
1905// Flush contents of FAT cache to disk
1906void flexFlushFAT(int dnr)
1907{
1908 FLEFAT *f;
1909
1910 //
1911 DEBUGINFO
1912
1913 //
1914 f = &fle->FAT[dnr];
1915 if(f->isOK)
1916 {
1917 //
1918 printk("%s: WRITING FAT DNR = %d\n",
1919 __FUNCTION__, f->dnr);
1920// waitkey();
1921 flexRWFAT(f, WRITE);
1922 }
1923}
1924
1925// Clears contents of a FAT
1926void clearFatContents(FLEFAT *f)
1927{
1928 //
1929 if( illegal(f) )
1930 panic("NULL PTR case 11");
1931
1932 //
1933 printk("f->buf clearing\n");
1934 memset(f->buf, 0, f->l_buf);
1935 printk("f->writemap clearing\n");
1936 memset(f->writemap, 0, f->l_writemap);
1937}
1938
1939// Allocate FAT data buffers for drive.
1940int flexAllocateFat(FLEFAT *f)
1941{
1942 static char str[256];
1943
1944 //
1945 if( illegal(f) )
1946 panic("NULL ptr case 10");
1947
1948 // Buffer
1949 if(f->buf==NULL)
1950 {
1951 //
1952 f->l_buf = getsize(f->dnr)*4;
1953 if(f->l_buf >= MAX_FAT_SIZE)
1954 {
1955 // We can't allocate, FAT is too big (TODO !!).
1956 return 1982;
1957 }
1958
1959 f->buf = procmalloc(f->l_buf, 0, __FUNCTION__);
1960
1961 if( illegal(f->buf) )
1962 {
1963 sprintf(str, "%s: error alloc 1 (illegal PTR: buf = 0x%x, l_buf=%d)",
1964 __FUNCTION__, f->buf, f->l_buf);
1965 panic(str);
1966 }
1967 memset(f->buf, 0, f->l_buf);
1968 printk("%s: f->buf = 0x%x\n",
1969 __FUNCTION__, f->buf);
1970 }
1971
1972 // Write map
1973 if(f->writemap==NULL)
1974 {
1975 //
1976 f->l_writemap = (getsize(f->dnr)*4/getblocksize(f->dnr));
1977 if(f->l_writemap >= MAX_FAT_SIZE)
1978 {
1979 // We can't allocate, FAT is too big (TODO !!).
1980 return 1983;
1981 }
1982
1983 f->writemap = procmalloc(f->l_writemap, 0, __FUNCTION__);
1984
1985 if( illegal(f->writemap) )
1986 panic("error alloc 2");
1987 memset(f->writemap, 0, f->l_writemap);
1988 printk("%s: f->writemap = 0x%x\n",
1989 __FUNCTION__, f->writemap);
1990 }
1991
1992 //
1993 printk("%s: Calling clearFatContents.",
1994 __FUNCTION__);
1995 clearFatContents(f);
1996}
1997
1998// Analyze all known FATs for any corruption
1999void AnalyzeFATs(void)
2000{
2001 int dnr;
2002
2003 //
2004 dnr = driver_getdevicenrbyname("ram");
2005 AnalyzeFAT( &fle->FAT[dnr] );
2006
2007 //
2008 dnr = driver_getdevicenrbyname("hda");
2009 AnalyzeFAT( &fle->FAT[dnr] );
2010}
2011
2012// Analyze FAT table for any errors (integrity check)
2013void AnalyzeFAT(FLEFAT *f)
2014{
2015 int i,errors,sz,conti,maxconti,maxoffs,offs,key;
2016 DWORD v;
2017 char str[50];
2018
2019 //
2020 return;
2021
2022 //-----------------------------------------------------------
2023 // Is this FAT active?
2024 if( f->isOK==FALSE )
2025 return;
2026
2027 //-----------------------------------------------------------
2028 // Get actual drive size
2029 sz = getsize(f->dnr);
2030
2031 //
2032 for(i=0,errors=0,conti=0,maxconti=0; i<sz; i++)
2033 {
2034 //
2035 v = f->buf[i];
2036 if(v<0xFFFFFF00)
2037 {
2038 //
2039 if(v >= f->max_val)
2040 {
2041 // Show upto 10 errors, then stop showing
2042 // these to speed up the process...
2043 if(errors<10)
2044 {
2045 //
2046 // printk("%c%c%c%c",
2047 // v&255, v>>8&255, v>>16&255, v>>24&255);
2048 printk("reads=%x, max. allowed=%x, location=%d/%d\n",
2049 v, f->max_val, i,sz);
2050 }
2051
2052 //
2053 errors++;
2054 if(offs==0) offs = i;
2055 conti++;
2056
2057 // Fix location with SYSTEM RESERVED value.
2058 f->buf[i] = 0xFFFFFFF7;
2059 }
2060 else
2061 {
2062 //
2063 if(conti && conti>maxconti)
2064 {
2065 maxconti = conti;
2066 maxoffs = offs;
2067 }
2068 //
2069 conti=0;
2070 }
2071 }
2072 }
2073
2074 // If any errors detected
2075 if(errors)
2076 {
2077 // Get user attention
2078 Attention();
2079 // Show user what we got
2080 driver_getdevicename(f->dnr, str),
2081 printk("\n* FAT table for drive #%d(%s) is corrupted: table contains unaccepted values (%d errors detected). *\n",
2082 f->dnr, str, errors);
2083 printk("Largest contigous corrupted area = %d bytes.\n",
2084 maxconti*4);
2085
2086 //
2087 while(1)
2088 {
2089 //
2090 printk("Run global search(Y/N)?");
2091 key = getch();
2092 if(key=='Y')
2093 {
2094 // Search whole kernel memory for this pattern.
2095 GlobalSearch(&f->buf[maxoffs], maxconti*4);
2096
2097 // Wait until user hits key.
2098 getch();
2099 break;
2100 }
2101 if(key=='N')
2102 break;
2103
2104 //
2105 printk("\nPlease answer Y or N with caps.\n");
2106 }
2107
2108 //
2109 }
2110}
2111
2112
2113// Read whole FAT in memory at once.
2114// [or]
2115// Write changed FAT areas on drive.
2116// RW must equal to READ or WRITE.
2117void flexRWFAT(FLEFAT *f, int rw)
2118{
2119 static int i,i2,i3,i4,b,s,e;
2120 char *p;
2121
2122 //
2123 FLEXCHECK(f)
2124
2125 // Writing?
2126 if(rw==WRITE)
2127 {
2128 // Anything left to write?
2129 if(f->writeBack==0)
2130 {
2131 // Nothing to write.
2132 return;
2133 }
2134 // Flag write
2135 else f->writeBack=0;
2136 }
2137
2138 //
2139 FLEXCHECK(f)
2140
2141 //
2142 DEBUGINFO
2143 dprintk("%s: DNR=%d\n", f->dnr);
2144
2145 //
2146 FLEXCHECK(f)
2147
2148 // Determine the block we need
2149 s = f->bb->fat_offs;
2150 e = f->bb->fat_offs + (getsize(f->dnr)*4/getblocksize(f->dnr)) + 1;
2151 for(i=s,p=f->buf,i2=0; i<e; i++,p+=getblocksize(f->dnr),i2++)
2152 {
2153 //
2154 if( (p+getblocksize(f->dnr)) >= (f->buf+f->l_buf) )
2155 {
2156 //
2157 FLEXER(1100, "flexFat EXCEEDED BUFFER BOUNDER");
2158 }
2159
2160 //
2161 if(rw==READ)
2162 {
2163 //
2164 dprintk("<%s: readblock DNR=%d, BNR=%d, p=0x%x>\n",
2165 __FUNCTION__, f->dnr, i, p);
2166 //sleep(1);
2167 readblock(f->dnr, i, p);
2168 }
2169 else
2170 if(rw==WRITE)
2171 {
2172 //
2173 if( f->writemap[i2] )
2174 {
2175 //
2176 dprintk("<%s: writeblock DNR=%d, BNR=%d, p=0x%x>\n",
2177 __FUNCTION__, f->dnr, i, p);
2178 //sleep(1);
2179 f->writemap[i2]=0;
2180 writeblock(f->dnr, i, p);
2181 }
2182 }
2183 }
2184
2185 // Analyze FAT for any integrity errors
2186 AnalyzeFAT(f);
2187
2188 //
2189 FLEXCHECK(f)
2190
2191 //
2192 dprintk("\n");
2193}
2194
2195// Activate cache
2196// Return value: (the caller must check the return value upon return!!)
2197// 0 = Success.
2198// Non-zero = Error.
2199int flexActivateFat(int dnr)
2200{
2201 FLEFAT *f;
2202
2203 // Validity check
2204 if(!isValidDevice(dnr)){ return 1981; }
2205
2206 //
2207 f = &fle->FAT[dnr];
2208
2209 //
2210 if( (f->bb=jtmfat_getinfoblock(dnr))==NULL || (f->bb && strncmp(f->bb->detstr, "JTMFS", 5)) )
2211 {
2212 //
2213 printk("%s: The drive (%d) is not JTMFS formatted, won't activate FAT.\n",
2214 __FUNCTION__, dnr);
2215 return 1980;
2216 }
2217
2218 //
2219 f->status = INITIALIZED;
2220 f->dnr = dnr;
2221 f->guard = FLFGUARD;
2222 f->writeBack = 0;
2223 f->max_val = getsize(dnr);
2224 // Define amount of FAT values.
2225 f->amount = getsize(f->dnr);
2226 // Perform allocation.
2227 return flexAllocateFat(f);
2228}
2229
2230// Returns amount of FAT entries FAT [DNR] has.
2231int flexGetFatSize(int dnr)
2232{
2233 //
2234 return fle->FAT[dnr].amount;
2235}
2236
2237// ------------------------------------------------------------------
2238int flexTouchFat(int dnr, int FATbnr)
2239{
2240 int i,i2,newBlock,rv;
2241
2242 // Validity check
2243 if(!isValidDevice(dnr)){ FLEXER(7, "flexTouchFat: (7) invalid DNR") return 1; }
2244
2245 //
2246 DEBUGFUNC
2247
2248 // 1) Activate FAT if it is not yet activated
2249 if(fle->FAT[dnr].isOK==FALSE)
2250 {
2251 // Get hang of the boot block
2252 if( (fle->FAT[dnr].bb=jtmfat_getinfoblock(dnr))==NULL )
2253 {
2254 //
2255 FLEXER(8, "flexTouchFat: (8) getinfotblock returned NULL")
2256 printk("%s: Non-JTMFS drive ?\n",
2257 __FUNCTION__);
2258 sleep(1);
2259 // Can't get hold of boot block on this device!
2260 return 1;
2261 }
2262
2263 // Allocate FAT buffer if neccesary
2264 // (contains whole FAT at once).
2265 if(fle->FAT[dnr].buf==NULL)
2266 {
2267 //
2268 if( (rv=flexActivateFat(dnr)) )
2269 return rv;
2270 }
2271
2272 // Read FAT
2273 flexRWFAT(&fle->FAT[dnr], READ);
2274
2275 // OK now
2276 fle->FAT[dnr].isOK = TRUE;
2277 }
2278
2279 // Activation was successful:
2280 return 0;
2281}
2282
2283//
2284void flexSetWM(FLEFAT *f, int entry, int what)
2285{
2286 //
2287 f->writemap[entry] = what;
2288}
2289
2290//
2291void flexAffectWM(FLEFAT *f, int entry)
2292{
2293 int bs;
2294
2295 //
2296 bs = getblocksize(f->dnr);
2297 if(bs<=0)
2298 return;
2299
2300 //
2301 f->writeBack = 1;
2302 flexSetWM(f, (entry*4)/bs, 1);
2303}
2304
2305// Get block from FAT table
2306int _flexFatGetBlock(const char *caller, int dnr,int X)
2307{
2308 FLEFAT *f;
2309 int rv;
2310
2311 // 1A) DNR validity check
2312 if(!isValidDevice(dnr)){ FLEXER(6, "flexFatGetBlock: (6) invalid DNR") return 0; }
2313
2314 //
2315// dprintk("%s was called by %s\n",
2316// __FUNCTION__, caller);
2317
2318 // 1B) Parameter validity check
2319 if( X<0 || X>=getsize(dnr) ){ FLEXER(5, "flexFatGetBlock: if( X<0 || X>=getsize(dnr)") return 0; }
2320
2321 // 2) Get permission(will do writeBack flushes also)
2322 if( (rv=flexTouchFat(dnr, X)) ){ FLEXER(4, "flexTouchFat(dnr, X)") return 0; }
2323
2324 // 3) Receive entry
2325 return FastGetBlock(dnr, X);
2326}
2327
2328// Set block
2329int _FastSetBlock(char *fun, int dnr, int which, DWORD what)
2330{
2331 FLEFAT *f;
2332 char str[256];
2333
2334 //
2335 if( flexTouchFat(dnr, which) ){ FLEXER(1, "flexFatSetBlock: touch failed") return 0; }
2336
2337 // 1C Get PTR
2338 f = &fle->FAT[dnr];
2339
2340 // 3) Change entry
2341 if((what & 0xFFFFFFF0) == 0xFFFFFFF0 || what < f->max_val)
2342 {
2343 //
2344 f->buf[which] = what;
2345 }
2346 else
2347 {
2348 // Illegal value!
2349 sprintf(str, "Function %s is attempting to set illegal FAT value(%x, max=%x) on FAT table.",
2350 fun, what, f->max_val);
2351 panic(str);
2352 }
2353
2354
2355 // 4) Declare writeback need on writeback map
2356 flexAffectWM(f, which);
2357}
2358
2359// Set block
2360int FastSetBlocks(int dnr, int x1, int x2, int what)
2361{
2362 FLEFAT *f;
2363 int x,bs;
2364
2365 //
2366 if( flexTouchFat(dnr, x1) ){ FLEXER(1, "flexFatSetBlock: touch failed") return 0; }
2367
2368 // 1C Get PTR
2369 f = &fle->FAT[dnr];
2370
2371 // 3) Change entry
2372 for(x=x1; x<x2; x++)
2373 f->buf[x] = what;
2374
2375 // 4) Declare writeback need
2376 bs = getblocksize(f->dnr);
2377 if(bs<=0) return 1;
2378 for(x=(x1*4)/bs; x<(((x2*4)/bs)+1); x++)
2379 flexSetWM(f, x, 1);
2380 return 0;
2381}
2382
2383// Get block
2384int _FastGetBlock(char *fun, int dnr, int which)
2385{
2386 FLEFAT *f;
2387
2388 //
2389 if( flexTouchFat(dnr, which) ){ FLEXER(1, "flexFatSetBlock: touch failed") return 0; }
2390
2391 // 1C Get PTR
2392 f = &fle->FAT[dnr];
2393
2394 // 3) Change entry
2395 return f->buf[which];
2396}
2397
2398// Set block on FAT table
2399int _flexFatSetBlock(const char *caller, int dnr,int X,int VALUE)
2400{
2401 FLEFAT *f;
2402
2403 //
2404// dprintk("%s was called by %s\n",
2405// __FUNCTION__, caller);
2406
2407 // 1A) DNR validity check
2408 if(!isValidDevice(dnr)){ FLEXER(3, "flexFatSetBlock: invalid dnr") return 0; }
2409
2410 // 1B) Parameter validity check
2411 if( X<0 || X>=getsize(dnr) ){ FLEXER(2, "invalid requested block #") return 0; }
2412
2413 // 2) Get permission(will do writeBack flushes also)
2414 if( flexTouchFat(dnr, X) ){ FLEXER(1, "flexFatSetBlock: touch failed") return 0; }
2415
2416 //
2417 return FastSetBlock(dnr, X, VALUE);
2418}
2419
2420// This function is called upon disk changes
2421void flexDiskChange(int dnr)
2422{
2423 FLEFAT *f;
2424 char str[256];
2425
2426 // Get FAT PTR
2427 f = &fle->FAT[dnr];
2428
2429 //
2430 if(f->status!=INITIALIZED)
2431 {
2432 return;
2433 panic("flexDiskChange call on non-initialized FAT");
2434 }
2435
2436 // Eject FAT cache for this device
2437 f->isOK = 0;
2438 driver_getdevicename(dnr, str);
2439 printk("%s: Calling clearFatContents (device=%s).\n",
2440 __FUNCTION__, str);
2441 clearFatContents(f);
2442}
2443
2444//
2445// FILE NAME TRANSLATION FUNCTIONS FOR JTMFS
2446// (C) 2002 Jari Tuominen(jari.tuominen@kanetti.net)
2447// =================================================
2448
2449// Returns device number, -1 if no one defined.
2450int tell_fname(const char *fname, char *parsedfname)
2451{
2452 static int i,i2,i3,i4,hasdev,l;
2453 static char strdev[50];
2454
2455 l = strlen(fname);
2456 for(i=0,hasdev=0; i<l; i++)
2457 {
2458 if( fname[i]==':' )
2459 {
2460 // Copy found device to strdev
2461 for(i2=0; i2<i; i2++)
2462 strdev[i2] = fname[i2];
2463 strdev[i2]=0;
2464
2465 // Convert device string to an
2466 // interger based device identificator
2467 hasdev = driver_getdevicenrbyname(strdev);
2468 if(hasdev==-1)hasdev=0;
2469
2470 // ----------------------------------
2471 // Get the file name
2472 // skip past the ':' character
2473 i++;
2474
2475 //
2476 goto nores;
2477 }
2478 }
2479 i=0;
2480nores:
2481
2482 // Copy the file name
2483 for(i2=i,i3=0; i2<l; i2++,i3++)
2484 parsedfname[i3] = fname[i2];
2485 parsedfname[i3]=0;
2486
2487 //
2488/* printk("tell_fname: Resolved following, devnr = %d, fname = '%s'\n",
2489 hasdev, parsedfname);*/
2490
2491 // Return possible device number
2492 return hasdev;
2493}
2494
2495
2496
2497
2498/////////////////////////////////////////////////////////////////////////////////////////
2499// JTMOS FS (JTMFS) Device Drive Format Functions
2500/////////////////////////////////////////////////////////////////////////////////////////
2501
2502//-----------------------------------------------------------------------------------------
2503// What it does do :
2504// - Creates an empty FAT
2505// - Reserves system area on FAT
2506// - Creates a basic root directory
2507int jtmfs_formatdrive(int device_nr)
2508{
2509 int nr_blocks,blocksize;
2510 char str[100];
2511
2512 //----------------------------------------------------
2513 if(!isValidDevice(device_nr)) return 10;
2514
2515 //----------------------------------------------------
2516 // Inform cache system first.
2517 DiskChange(device_nr);
2518
2519 //
2520 driver_getdevicename(device_nr, str);
2521 dprintk("Formatting drive %s: ...\n",
2522 str);
2523 //
2524 nr_blocks=getsize(device_nr);
2525 blocksize=getblocksize(device_nr);
2526 //
2527 FFCHECK
2528
2529 //
2530 printk("Drive has %d blocks, each block consists of %d bytes\n",
2531 nr_blocks, blocksize);
2532
2533 //
2534 if(!nr_blocks)
2535 {
2536 //
2537 printk("Device is not suitable for a file system.\n");
2538 return 1;
2539 }
2540
2541 // Make sure we are using correct device:
2542 jtmfat_chdev(device_nr);
2543 // Do the job:
2544 jtmfat_createfat(device_nr);
2545 jtmfs_createrootdir(device_nr);
2546
2547 // Update drive contents at the end.
2548 FlushAll();
2549
2550 //
2551 dprintk("Format Complete.\n");
2552 return 0;
2553}
2554
2555/*
2556 *============================================================
2557 * JTMFS FILE SYSTEM - Add directory entry.
2558 * (C) 2002-2003 by Jari Tuominen
2559 *============================================================
2560 */
2561
2562// jtmfs_adddirentry
2563// -----------------
2564//
2565// Adds a file/directory entry to the specified directory.
2566//
2567// Description:
2568// It scrolls through existing directory tree,
2569// hunting for empty place, if empty place is
2570// found, it will use it,
2571// if no empty place is found, it will create
2572// one at the end of the directory tree,
2573// if needed it will also expand the directory
2574// size by one block so it gains needed extra
2575// space for the new directory entry.
2576//
2577// BTW, to detect an unused directory entry,
2578// try: "if length == -1 then its empty"
2579//
2580// Note: Unused directory entries are also
2581// called "ghosts".
2582//
2583//
2584// This function adds a new directory entry
2585// on a directory specified by the block number.
2586//
2587// dnr,db,type
2588//
2589// db = defines on which block the directory is located at
2590//
2591// TODO: There is still some problems with the seektolastentry using in this function,
2592// and/or the problem maybe related much to the code within this function itself as well.
2593// UPDATE: Not anymore, besides there might occur new problems afterwards, so I keep the TODO still.
2594//
2595int jtmfs_adddirentry(int dnr,int db,JTMFS_FILE_ENTRY *fe)
2596{
2597 DIRWALK dw,temp_dw;
2598 int cb,i,i2,i3,i4,expand;
2599 char *p;
2600 JTMFS_FILE_ENTRY *entry;
2601 char *src,*otp;
2602
2603 // Force magicNumber
2604 fe->magicNumber = 0xFCE2E37B;
2605
2606 // Inform
2607 dprintk("%s: dnr=%d/db=%d,fe=0x%x\n",
2608 __FUNCTION__,
2609 dnr, db, fe);
2610 dsleep(1);
2611
2612 //
2613 InitDW(&dw); InitDW(&temp_dw);
2614
2615 // TODO: add a dnr validity check here
2616 // Routine check for null pointers
2617 if(fe==NULL)
2618 {
2619 dprintk("jtmfs_adddirentry: error, NULL pointer reference for fe\n");
2620 return 111;
2621 }
2622
2623 //
2624 if( !strlen(fe->name) )
2625 {
2626 dprintk("silly error: filename's length is zero\n");
2627 return 110;
2628 }
2629
2630 //
2631 dprintk("%s: Finding file '%s'\n",
2632 __FUNCTION__, fe->name);
2633 // Make sure that the filename is not yet used:
2634 if( jtmfs_ffindfile(dnr, fe->name, db, &temp_dw) )
2635 {
2636 //
2637 ReportMessage("%s: File already exists(%s).\n",
2638 __FUNCTION__, fe->name);
2639
2640 // Bugfix: Remembered the deallocation
2641 EndDirWalk(&temp_dw);
2642 // Cannot create - Already exists!
2643 return 10;
2644 }
2645
2646 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2647 //
2648 expand=0;
2649
2650 //
2651 dprintk("%s: Finding ghost file '%s'.\n",
2652 __FUNCTION__, fe->name);
2653 // extern int jtmfs_ffindfirstghostfile(int dnr,int block_nr,DIRWALK *dw);
2654 //
2655 // First we check for a ghost file entry, which we could use instead:
2656 if( jtmfs_ffindfirstghostfile( dnr,db,&dw)==1 )
2657 {
2658 // Rearrangemable ghost entry found:
2659 // now we just pass over "the allocation of a new entry slot".
2660 dprintk("%s: Found deleted entry(%s)\n",
2661 __FUNCTION__, fe->name);
2662 }
2663 else
2664 {
2665 // If nothing appeared to be there, we just look for
2666 // the last entry and add a new one there:
2667 InitDW(&dw);
2668
2669 //
2670 dprintk("%s: ffirst\n", __FUNCTION__);
2671 // Jump to first block of the chain
2672 if( jtmfs_ffirst(dnr,db,&dw) )
2673 {
2674 // Bugfix2: Remembered the deallocation
2675 EndDirWalk(&dw);
2676 return 145;
2677 }
2678
2679 //
2680 dprintk("%s: seektolastentry.\n", __FUNCTION__);
2681 // Find the last entry.
2682 if( jtmfs_seektolastentry(dnr, &dw) )
2683 {
2684 // Directory full, don't add now.
2685 return 1005;
2686 }
2687
2688 //
2689 dprintk("%s: stepover\n", __FUNCTION__);
2690 // (adddirentry -function)
2691 // Jump over the last entry, if we break the block boundary,
2692 // we will allocate one more block for the directory chain.
2693/* if( jtmfs_stepover(dnr, &dw) )
2694 {
2695 // Error in modern walking.
2696 return 1004;
2697 }
2698 else
2699 {
2700 // Ah, we still have got space for this entry within the
2701 // current directory's block, we don't have to do anything
2702 // additionally:
2703 //
2704 }*/
2705
2706 }
2707
2708 //
2709 dprintk("%s: ffupdatefe.\n",
2710 __FUNCTION__);
2711 //
2712 jtmfs_ffupdatefe(&dw);
2713 // ----- We got a slot to copy the entry on, so here we do it then:
2714 // Now copy the entry to it's place
2715 //memcpy( dw.fe, fe, sizeof(JTMFS_FILE_ENTRY) );
2716 otp=dw.fe; src=fe; i=sizeof(JTMFS_FILE_ENTRY);
2717 for(; i; i--,src++,otp++)*otp=*src;
2718
2719#ifdef JTMFSDEBUG
2720 //
2721 dprintk("ADDING DIR ENTRY: offs=%x, block=%d, name='%s', entry=%d bytes\n",
2722 dw.current_offset, dw.current_block, dw.fe->name,
2723 sizeof(JTMFS_FILE_ENTRY));
2724
2725 //
2726 for(p=dw.d->buf; *p; p+=sizeof(JTMFS_FILE_ENTRY))
2727 {
2728 entry=p;
2729 dprintk("0x%x: name='%s', length=%d bytes\n",
2730 p,
2731 entry->name, entry->length);
2732 }
2733 entry=p;
2734 dprintk("0x%x: name='%s', length=%d bytes\n",
2735 p,
2736 entry->name, entry->length);
2737 dsleep(1);
2738// waitkey();
2739#endif
2740
2741 dprintk("%s: ffwritelocation\n",
2742 __FUNCTION__);
2743 // Then write to the disk(..)
2744 jtmfs_ffwritelocation(dnr, &dw);
2745
2746 // End walking, free the dirwalker
2747 EndDirWalk(&dw);
2748
2749 // We have done a fine job, now we can return.
2750 return 0;
2751}
2752
2753
2754
2755/*
2756 * ===========================================================
2757 * JTMFS FILE SYSTEM - Add blocks for a dir entry
2758 * (C) 2002-2003 by Jari Tuominen
2759 * ===========================================================
2760 */
2761//
2762
2763// jtmfs_add_blocks_for_entry
2764//
2765// new: now checks for available space,
2766// if it is insufficient, we'll just
2767// return an error, a non-zero value.
2768//
2769int jtmfs_add_blocks_for_entry(int device_nr,
2770 char *fname, int dblock, int amount)
2771{
2772 static int z1;
2773 static DWORD i,i2,i3,i4,db,block,new_block,amount_to_allocate,retval;
2774 static DIRWALK dw;
2775
2776 //
2777 if( !amount || amount<0 || amount>=getsize(device_nr)
2778 || !isValidDevice(device_nr) )
2779 {
2780 dprintk("%s: ERROR amount=%d, illegal amount.\n",
2781 __FUNCTION__, amount);
2782 return 10;
2783 }
2784
2785 // No error as default.
2786 retval=0;
2787 // Init DIRWALK structure
2788 InitDW(&dw);
2789
2790 //
2791 amount_to_allocate=amount;
2792
2793 // Find the file
2794 dprintk("%s: jtmfs_ffindfile -call\n", __FUNCTION__);
2795 if( !jtmfs_ffindfile(device_nr, fname, dblock, &dw) )
2796 {
2797 // Not found?
2798 dprintk("%s: File '%s' not found\n",
2799 __FUNCTION__, fname);
2800 return 1;
2801 }
2802
2803 // Does it have already a data block?
2804 if(!dw.fe->FirstDataBlock)
2805 {
2806 // No first data block allocated yet here:
2807 // =======================================
2808 if(glvar.debugMsg)
2809 dprintk("%s has no data allocated on it yet!\n", fname);
2810 // We have to do one less now
2811 amount_to_allocate--;
2812 // We don't have one yet,
2813 // so we straight away start the allocation:
2814 block = jtmfat_getfreeblock(device_nr); if(block<=0)return 10;
2815 dw.fe->FirstDataBlock = block; // define first data block
2816 dw.fe->LastDataBlock = block; // (this one is same, because there is only one)
2817 dw.fe->length += amount*getblocksize(device_nr); // file size(length in bytes) realization
2818 // Then write file entry back to the disk(..)
2819 jtmfs_ffwritelocation(device_nr, &dw);
2820 // Set "end of chain" at first block
2821 jtmfat_setblock(device_nr, block, 0xFFFFFFF8);
2822 }
2823 else
2824 {
2825 //dprintk("%s has first data block on %d\n", fname, dw.fe->FirstDataBlock);
2826 // First data block allocated already here:
2827 // ========================================
2828 block = dw.fe->FirstDataBlock;
2829 // We have already a data block, just update the size information:
2830 dw.fe->length += amount*getblocksize(device_nr); // file size(length in bytes) realization
2831 // Then write file entry back to the disk(..)
2832 jtmfs_ffwritelocation(device_nr,&dw);
2833 }
2834
2835 // OPTIMIZED ON 17.07.2002
2836 // Added use of more modern FirstDataBlock & LastDataBlock.
2837 block = dw.fe->LastDataBlock;
2838
2839 // Add more blocks to the chain
2840 for(i=0; i<amount_to_allocate; i++)
2841 {
2842 z1 = DExpandChain(device_nr, block);
2843 if( z1<=0 )
2844 {
2845 retval=3;
2846 break;
2847 }
2848 db=jtmfat_getblock(device_nr, block);
2849 block=db;
2850 }
2851
2852 // Write directory file entry back on disk
2853 dw.fe->LastDataBlock = block;
2854 jtmfs_ffwritelocation(device_nr, &dw);
2855 //dprintk("BLOCKS %d-%d\n", dw.fe->FirstDataBlock, dw.fe->LastDataBlock);
2856
2857 //
2858 return retval;
2859}
2860
2861
2862
2863// ==============================================================================================
2864// JTMOS File System Device Path Calculation.
2865//
2866// File API - Device / path determination for each process.
2867// Yes, each process has own unique path/device identifiers,
2868// and each process does not rely on other procsses current
2869// directory path.
2870//
2871// JTMOS file I/O application implementation for applications and medium level system functions
2872// (C) 2002 Jari Tuominen(jari.tuominen@kanetti.net)
2873// ==============================================================================================
2874
2875/*
2876// Returns current device that is assigned to the process to use.
2877int GetCurrentDevice(void)
2878{
2879 // THIS IS A HACK, TODO LATER!
2880 return fileapi.dnr;
2881}
2882
2883//
2884int SetCurrentDevice(int dnr)
2885{
2886 //
2887 fileapi.dnr = dnr;
2888 return 0;
2889}
2890*/
2891
2892
2893// ==============================================================================================
2894// JTMFS File System DOS Compatibility - DOS compatibility functions
2895//
2896// JTMOS file I/O application implementation for applications and medium level system functions
2897// DOS compatibility functions. For easy access.
2898//
2899// findfirst find MUST be ended with close(fd);, so that the file descriptors gets dellocated.
2900//
2901// (C) 2002-2003 Jari Tuominen(jari.tuominen@kanetti.net)
2902// ==============================================================================================
2903
2904// Copy to DOSish FFBLK structure from JTMOS file entry.
2905void FE2BLK(JTMFS_FILE_ENTRY *fe, FFBLK *blk)
2906{
2907 // Get file name.
2908 strcpy(blk->ff_name, fe->name);
2909 // Get length.
2910 blk->ff_fsize = fe->length;
2911 blk->ff_attrib = fe->type;
2912 // Rest are not supported, yet.
2913 blk->ff_fdate = 0;
2914 blk->ff_ftime = 0;
2915}
2916
2917// Copy to DOSish FFBLK structure from JTMOS file entry.
2918void NAME2BLK(const char *fname, FFBLK *blk, int sz)
2919{
2920 // Get file name.
2921 strcpy(blk->ff_name, fname);
2922 // Get length.
2923 blk->ff_fsize = sz;
2924 // Rest are not supported yet.
2925 blk->ff_attrib = 0;
2926 blk->ff_fdate = 0;
2927 blk->ff_ftime = 0;
2928}
2929
2930// findfirst
2931//
2932// Returns file descriptor(int) if OK, below or equal to 0
2933// if no matching files found or on error.
2934int findfirst(int dnr, int db, const char *path, FFBLK *blk)
2935{
2936 int fd;
2937 FILEDES *d;
2938 int rv;
2939
2940 //
2941 dprintk("%s: new_filedes\n", __FUNCTION__);
2942 fd = new_filedes(); // Get new file descriptor
2943 dprintk("%s: get_filedesptr\n", __FUNCTION__);
2944 d = get_filedesptr(fd); // Get jtm_filedes -structure pointer
2945 if(d==NULL)
2946 return -1;
2947
2948 // Try searching for exact match (device or file)
2949 if(jtmfs_Fexist(dnr, path, db)
2950 || driver_getdevicenrbyname(path)!=-1)
2951 {
2952 //
2953 NAME2BLK(path, blk, jtmfs_GetFileSize(dnr, path, db));
2954 blk->_ff_reserved[0] = 1; // single
2955 return fd;
2956 }
2957 else
2958 {
2959 //
2960 blk->_ff_reserved[0] = 0; // single
2961 }
2962
2963 //
2964 dprintk("%s: jtmfs_ffirst\n", __FUNCTION__);
2965 // first to the starting point
2966 if( (rv=jtmfs_ffirst(dnr, db, &d->dw)) )
2967 {
2968 // Not found.
2969 dprintk("%s: No file(s) found\n", __FUNCTION__);
2970 FreeFD(fd);
2971 return -rv;
2972 }
2973 else
2974 {
2975 // Found:
2976 dprintk("%s: File(s) found, fd=%d\n",
2977 __FUNCTION__, fd);
2978 FE2BLK(d->dw.fe, blk);
2979 return fd;
2980 }
2981}
2982
2983// findnext
2984// findnext(p->dnr, p->db, p->v1, p->par1)
2985//
2986// Returns 0 if OK, non-zero if end of directory on error.
2987int findnext(int dnr, int db, int fd, FFBLK *blk)
2988{
2989 FILEDES *d;
2990 int r;
2991
2992 // Check for DESPTR
2993 d = get_filedesptr(fd); // Get jtm_filedes structure pointer
2994 if(d==NULL)
2995 {
2996 dprintk("%s: bad file descriptor(%d)\n",
2997 __FUNCTION__, fd);
2998 return -3;
2999 }
3000
3001 //
3002 if(blk->_ff_reserved[0]) // single
3003 // End of directory, no more files
3004 return -2;
3005
3006 //
3007 if( (r=jtmfs_fnext(dnr, &d->dw)) )
3008 {
3009 //
3010 dprintk("%s: jtmfs_fnext returns %d\n",
3011 __FUNCTION__, r);
3012
3013 // Entry received & End of dir.
3014 //FE2BLK(d->dw.fe, blk);
3015 return r;
3016 }
3017 else
3018 {
3019 // Entry received.
3020 FE2BLK(d->dw.fe, blk);
3021 return 0;
3022 }
3023}
3024
3025
3026
3027/*
3028 *============================================================
3029 * JTMOS FS (JTMFS) Find Functinos
3030 * JTMFS FILE SYSTEM - File finder functions
3031 * (C) 2002-2005 by Jari Tuominen(jari@vunet.org).
3032 *============================================================
3033 */
3034//
3035
3036// jtmfs_ffindfile dnr,fname,db,dw
3037//
3038// 0=not found
3039// 1=found
3040// dw = your DIRWALK structure, contains the block and offset to the entry
3041// then after it has found it, if found.
3042//
3043// NEW: now ignores the ghost file entries(deleted).
3044//
3045int jtmfs_ffindfile(int dnr,
3046 const char *fname,int _db,DIRWALK *dw)
3047{
3048 //
3049 dprintk("%s: %d/%d, search for '%s'\n",
3050 __FUNCTION__,
3051 dnr,
3052 _db,
3053 fname);
3054 dsleep(1);
3055 //waitkey();
3056
3057 //
3058 return dirdb_ffindfile(dnr, fname, _db, dw);
3059}
3060
3061// Resolves a directory name of a directory.
3062// In other words, converts a DNR/DB to name string.
3063int jtmfs_ResolveDirName(int dnr,int db,DIRWALK *dw)
3064{
3065 //
3066 return dirdb_ffinddirname(dnr,NULL,db,dw);
3067}
3068
3069// jtmfs_ffindghostfile dnr,fname,db,dw
3070//
3071// 0=not found
3072// 1=found
3073// dw = your DIRWALK structure, contains the block and offset to the entry
3074// then after it has found it, if found.
3075//
3076//
3077int jtmfs_ffindghostfile(int dnr,const char *fname,int db,DIRWALK *dw)
3078{
3079 //
3080 return dirdb_ffindghostfile(dnr,fname,db,dw);
3081}
3082
3083// _jtmfs_ffindfirstghostfile dnr,db,dw
3084// 0=not found
3085// 1=found
3086// dw = your DIRWALK structure, contains the block and offset to the entry
3087// then after it has found it, if found.
3088int jtmfs_ffindfirstghostfile(int dnr,int db,DIRWALK *dw)
3089{
3090 //
3091 if(!dw)return 0;
3092
3093 //
3094 InitDW(dw);
3095
3096 // first to the starting point
3097 if(jtmfs_ffirst(dnr,db,dw))return 3;
3098
3099 // ????: Shouldn't we check the 1st entry first? TODO?
3100 return jtmfs_ffindnextghostfile(dnr, db, dw);
3101}
3102
3103// Used after ffindfirstghostfile is called.
3104// Finds next ghost entry, and returns 1 if one is found,
3105// all other return values mean that no ghost entry is found.
3106//
3107int jtmfs_ffindnextghostfile(int dnr,int db,DIRWALK *dw)
3108{
3109 //
3110 if(!dw)return 0;
3111 if(!dw->fe)return 0;
3112
3113 //
3114 while(1)
3115 {
3116 // Make sure that the file is deleted:
3117 if( dw->fe->length==-1 && dw->fe->type!=JTMFS_ID_DIRNAME )return 1;
3118 // Load next entry
3119 if( jtmfs_fnext(dnr,dw) )return 0;
3120 }
3121
3122 //
3123 return 0;
3124}
3125
3126
3127/*
3128 * ===========================================================
3129 * JTMFS FILE SYSTEM - Seek to last directory entry
3130 * (C) 2002 by Jari Tuominen
3131 * ===========================================================
3132 */
3133
3134// NOTE: the dirwalking must be already running before calling this!
3135int jtmfs_seektolastentry(long device_nr, DIRWALK *dw)
3136{
3137 int i;
3138
3139 // JTMFS required
3140 if(!jtmfat_isJTMFS(device_nr))return 1;
3141
3142 // It has to be already walking(dw)
3143 if(!dw->isWalking)
3144 {
3145#ifdef JTMFSDEBUG
3146 print("jtmfs_seektolastentry: logic failure in dirwalk structure\n");
3147 print("isn't yet walking, cannot use a non-walking structure\n");
3148 print("(structure is undefined? should contain f.e. the dir's block number)\n");
3149#endif
3150 return 2;
3151 }
3152 else
3153 {
3154 // First to the starting point
3155 if( jtmfs_ffirst(device_nr,-1,dw) )return;
3156 // Seek to the last entry available
3157 for(i=1; ; i++)
3158 {
3159 if( jtmfs_fnext(device_nr,dw) )break;
3160 }
3161 if((i+10)>=MAX_ENTRIES_PER_DIR)
3162 {
3163 // Indicate "directory full".
3164 return RV_DIRFULL;
3165 }
3166
3167#ifdef JTMFSDEBUG
3168 // Here we are at the last entry
3169 ReportMessage("seektolastentry: reached last entry, block=%d, offset=0x%x('%c' / asc %d)\n",
3170 dw->current_block, dw->current_offset,
3171 dw->buf[dw->current_offset],
3172 dw->buf[dw->current_offset]);
3173#endif
3174
3175 //
3176 return 0;
3177 }
3178
3179 //
3180 return 0;
3181}
3182
3183/*
3184 * ===========================================================
3185 * JTMFS FILE SYSTEM DIRECTORY WALKING CODE
3186 * (C) 2002-2005 by Jari Tuominen(jari@vunet.org).
3187 * ===========================================================
3188 */
3189
3190// Steps over a dir entry
3191// (Moves to next entry)
3192// return value: returns nonzero if attempting to exceed the block boundary
3193// (means, we need to load in another block.. or etc..)
3194// Special note: IT DOES NOT RETURN NONZERO ON AN EMPTY DIR ENTRY..
3195// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3196int jtmfs_stepover(int dnr, DIRWALK *dw)
3197{
3198 int i,i2;
3199
3200 //
3201 return dirdb_stepover(dnr, dw);
3202}
3203
3204
3205// jtmfs_fnext
3206// walks to next dir entry and receives it
3207// note: will return nonzero on error or on end of dir
3208// new: also updates the dw->fe pointer correctly now!
3209// new2(FIX): returns nonzero on an empty dir entry
3210// new3: loads new block if one exists
3211//
3212// Valid Return Values are:
3213// ------------------------
3214// 1=End of dir and chain.
3215// 2=End of dir(entry is zero based)
3216// 0=New entry loaded
3217//
3218int jtmfs_fnext(int dnr,
3219 DIRWALK *dw)
3220{
3221 //
3222 return dirdb_fnext(dnr, dw);
3223}
3224
3225// Ends the ffirst/fnext,
3226// frees the allocated resources, etc.
3227void jtmfs_fend(DIRWALK *dw)
3228{
3229 //
3230 dw->fe=NULL;
3231 dw->current_block = -1;
3232 dw->loaded_block = -1;
3233}
3234
3235// jtmfs_ffirst
3236// walks to the first dir entry and receives it
3237// note: will return nonzero on error
3238//
3239// new feature: if dirblock == -1 then the dirwalking will be resetted
3240// back to the starting block dw->start_block
3241//
3242int jtmfs_ffirst(int dnr,
3243 int dirblock, DIRWALK *dw)
3244{
3245 // JTMFS required
3246 if( !jtmfat_isJTMFS(dnr) )return 10;
3247
3248 //
3249 DEBUGLINE
3250
3251 //
3252 FFCHECK
3253 // TODO: Add a dnr validity check here
3254 // null pointer detector.
3255 if(dw==NULL)
3256 {
3257 //
3258 dprintk("jtmfs_ffirst: Error, dw == NULL\n");
3259 return 1;
3260 }
3261
3262 //
3263 FFCHECK
3264 DEBUGLINE
3265 // Make sure that the requested block is allocated
3266 if( dirblock!=-1 && !jtmfat_getblock(dnr, dirblock) )
3267 {
3268 //
3269 dw->current_block=-1;
3270 dw->isWalking=0;
3271 dprintk("jtmfs_ffirst: Non-existant block (%d)\n", dirblock);
3272 dprintk("dirblock=%d, FAT reads=%d\n",
3273 dirblock,
3274 jtmfat_getblock(dnr, dirblock));
3275 return 1;
3276 }
3277
3278 //
3279 DEBUGLINE
3280
3281 //
3282 return dirdb_ffirst(dnr, dirblock, dw);
3283}
3284
3285// *** IS IT JTMOS FS (JTMFS) DISK? ***
3286//
3287// This function is called when a non-JTMFS drive is detected.
3288void onNonJTMFSDrive(int dnr)
3289{
3290 // Clear all cache buffers for this drive
3291 // This is a precaution.
3292 DiskChange(dnr);
3293}
3294
3295// 0 = Non-JTMFS FS
3296// 1 = JTMFS FS
3297int isJTMFSBootBlock(int dnr, JTMFAT_INFOBLOCK *b)
3298{
3299 // FORMAT DETECTION
3300 if(
3301 b->detstr[0]=='J' &&
3302 b->detstr[1]=='T' &&
3303 b->detstr[2]=='M' &&
3304 b->detstr[3]=='F' &&
3305 b->detstr[4]=='S')
3306 {
3307 //
3308 return TRUE;
3309 }
3310 else
3311 {
3312 //
3313 onNonJTMFSDrive(dnr);
3314 return FALSE;
3315 }
3316}
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332/*
3333 * ========================================================================
3334 * JTMOS FAT is part of the JTMOS File System(JTMFS) package
3335 * This file contains only parts of JTMFAT, see flexFat.* for more.
3336 * (C) 2001-2005 by Jari Tuominen(jari.tuominen@kanetti.fi).
3337 * ========================================================================
3338 */
3339
3340/*
3341 * [FAT] (FILE ALLOCATION TABLE)
3342 * |
3343 * V
3344 * [DATA AREA] (FILESYSTEM/OTHER DATA)
3345 *
3346 *
3347 *
3348 * FAT TABLE(32-bit)
3349 *
3350 * 00000000 empty place
3351 * FFFFFFF1-FFFFFFF6 bad track marking
3352 * FFFFFFF7 system reserved area(BOOTSECTOR & FAT ..)
3353 * FFFFFFF8 used to mark end of a file chain
3354 * FFFFFFFF standard marker for end of a file chain
3355 * (!) Last cluster of a file always
3356 * contains a value of FFFFFFF8-FFFFFFFF.
3357 *
3358 * Ramdisks have got a standard sector
3359 * size of 1KB, 3.5" 1.44M floppys 512(½KB) bytes.
3360 */
3361
3362
3363//
3364int findfreeblock_last_block_nr=-1,
3365 EntranceGetrootdir=0;
3366//
3367char *TMPSPACE1=NULL, *BOOT_TMP_BUF=NULL;
3368//
3369JTMFATSYS *fatsys;
3370// Set to TRUE after jtmfat is ready to be used
3371int jtmfat_ready=FALSE;
3372//
3373USE_DEBUGTRAP
3374
3375//
3376void DebugTrap(int dnr, const char *funcStr)
3377{
3378 char *str,*str2;
3379 int i,i2;
3380 BYTE *p;
3381
3382 //
3383}
3384
3385// Calculate 32-bit checksum out of the whole FAT table
3386DWORD GetFATChecksum32(CFAT *f)
3387{
3388 int i,i2,l;
3389 BYTE *p;
3390 DWORD sum;
3391
3392 //
3393 p = f->buf; l = f->l_buf;
3394 for(i=0,sum=0; i<l; i++) { sum+=(p[i]+1); }
3395 return sum;
3396}
3397
3398// 0 = OK
3399// 1 = ERROR
3400// OTHER NUMBERS = MISC. ERROR
3401int read_fat(int dnr)
3402{
3403 //
3404 DEBUGLINE
3405 return 0;
3406}
3407
3408// Called by kernel cache flusher process only!:
3409int write_fat(int dnr)
3410{
3411 //
3412 return 0;
3413}
3414
3415int allocate_fat(int dnr)
3416{
3417 //
3418 return 0;
3419}
3420
3421// Touch on FAT it becomes alive...
3422int touch_fat(int dnr)
3423{
3424 //
3425 return 0;
3426}
3427
3428// HAS TO BE CALLED FIRST BEFORE USING JTMFAT
3429int jtmfat_init(void)
3430{
3431 static int i,i2,i3,i4;
3432
3433
3434 //
3435 if(TMPSPACE1==NULL) TMPSPACE1 = malloc(1024*64);
3436
3437 //
3438 DEBUGLINE
3439
3440 // ----------------------------------------------
3441 // GENERIC INIT
3442 // ----------------------------------------------
3443 //
3444 fatsys = malloc(sizeof(JTMFATSYS));
3445 //
3446 fatsys->virgin=1;
3447 SetMemoryName(fatsys, "fatsys:structure");
3448
3449 // Clear all the heck out first, clear table
3450 memset((void*)fatsys, 0, sizeof(JTMFATSYS));
3451
3452
3453
3454 // --------------------------------------------------------------
3455 //
3456 //
3457 dprintk("%s: Allocating sector buffers for all block devices:\n",
3458 __FUNCTION__);
3459 for(i=0; i<driver_nr(); i++)
3460 {
3461 // This is a block device?
3462 if(getsize(i)>=1)
3463 {
3464 fatsys->bb[i] = malloc(1024*32);
3465 }
3466 }
3467 dprintk("%s: Sector buffer allocation (COMPLETED OK).\n",
3468 __FUNCTION__);
3469
3470 // ----------------------------------------------
3471 //
3472 // Temporary buffer
3473 //
3474 fatsys->tbuf = malloc(1024*64);
3475 SetMemoryName(fatsys->tbuf, "fatsys:tbuf");
3476 // ----------------------------------------------
3477
3478 // Now we enable the jtmfat, after this, calls will work.
3479 jtmfat_ready=TRUE;
3480
3481 // Init FlexFAT
3482 flexFatInit();
3483
3484 //
3485// addPitHandler(jtmfatChecker);
3486}
3487
3488// Updates info block for the drive
3489// (loads a new one from drive to the drive's info block buffer).
3490int jtmfat_LoadNewInfoBlock(int dnr)
3491{
3492 void *tmp,*p;
3493 int i,i2,i3;
3494
3495 // Allocate on demand.
3496 if(fatsys->bb[dnr]==NULL)
3497 {
3498 //
3499 fatsys->bb[dnr] = malloc(getblocksize(dnr));
3500 }
3501
3502 //
3503 tmp = TMPSPACE1;
3504 //
3505 ReportMessage("%s: Reading updated info block from drive %d.\n",
3506 __FUNCTION__, dnr);
3507 // Read info block(first block on the block device).
3508 readblock(dnr, FAT_INFO_BLOCK_OFFS/getblocksize(dnr), tmp);
3509
3510 // Copy the info part to storage.
3511 p = fatsys->bb[dnr];
3512 i2 = sizeof(JTMFAT_INFOBLOCK);
3513 i3 = FAT_INFO_BLOCK_OFFS%getblocksize(dnr);
3514 memcpy(p, tmp+i3, i2);
3515
3516 // Here here.
3517 if( !strncmp(fatsys->bb[dnr]->detstr, "JTMFS", 5) )
3518 {
3519 printk("Block device #%d is not JTMFS-formatted.\n",
3520 dnr);
3521 fatsys->isJTMFS[dnr] = TRUE;
3522 }
3523 else
3524 fatsys->isJTMFS[dnr] = FALSE;
3525
3526 //
3527 return 0;
3528}
3529
3530// Loads up data to fatsys->bb[dnr]
3531// Returns non-zero if the drive is not
3532// JTMFS formatted.
3533int _jtmfat_loadinfoblock(const char *caller, int dnr)
3534{
3535 static BYTE *tmp,*p;
3536 static int i,i2;
3537
3538 //
3539 dprintk("%s was called by %s\n",
3540 __FUNCTION__, caller);
3541 DEBUGLINE
3542
3543 //------------------------------------------------------
3544 // FAT system must be active
3545 if(jtmfat_ready!=TRUE)return 1;
3546
3547 //------------------------------------------------------
3548 // Check device
3549 if(!isValidDevice(dnr))
3550 {
3551 printk("%s: Invalid device %d.\n",
3552 __FUNCTION__, dnr);
3553 return 2;
3554 }
3555
3556 //------------------------------------------------------
3557 // Get temporary data buffer PTR
3558 tmp = TMPSPACE1;
3559 if(tmp==NULL)
3560 panic("loadinfoblock TMPSPACE1==NULL.");
3561
3562 // Allocate on demand
3563 if(fatsys->bb[dnr]==NULL)
3564 {
3565 //
3566 jtmfat_LoadNewInfoBlock(dnr);
3567 }
3568
3569 //
3570 dprintk("%s: Leaving this function.\n",
3571 __FUNCTION__);
3572 return fatsys->isJTMFS[dnr];
3573}
3574
3575// Return value:
3576// Non-zero=Success, 0=Failure
3577//
3578int _jtmfat_chdev(const char *caller, long dnr)
3579{
3580 //
3581 FFCHECK
3582
3583 //-----------------------------------------------------------------------------------
3584 //
3585 if(jtmfat_ready!=TRUE)return 0;
3586
3587 //
3588 if(!isValidDevice(dnr))
3589 {
3590 dprintk("jtmfat_chdev: Invalid device %d\n",
3591 dnr);
3592 return 2;
3593 }
3594
3595 //-----------------------------------------------------------------------------------
3596 // Note: This function is called really often,
3597 // adding debug traces to this function
3598 // will lead into a big flow of debug text.
3599 dprintk("%s was called by %s\n",
3600 __FUNCTION__, caller);
3601
3602 //
3603 FFCHECK
3604 // ALWAYS load info block,
3605 // because this function is not the fast access function,
3606 // this function's job is to do the update of the info block.
3607 jtmfat_loadinfoblock(dnr);
3608 //
3609 FFCHECK
3610 //
3611 dprintk("%s: leaving this function\n",
3612 __FUNCTION__);
3613
3614 //
3615 return fatsys->isJTMFS[dnr];
3616}
3617
3618// jtmfat_getinfoblock = Fast access to boot block of DNR(for FATGET/FATSET)
3619// jtmfat_chdev = Slow access to boot block
3620// Get handle to the boot block of the specified DNR
3621JTMFAT_INFOBLOCK *jtmfat_getinfoblock(int dnr)
3622{
3623 // Let's load new boot block.
3624 if( fatsys->bb[dnr]==NULL)
3625 jtmfat_LoadNewInfoBlock(dnr);
3626
3627 // Access cache entry only.
3628 // (will be NULL if called by flexFat before activation!!!!!)
3629 return fatsys->bb[dnr];
3630}
3631
3632// Same as getrootdir1, but this one
3633// tries to retrieve the rootdir twice
3634// with two other ways.
3635int _jtmfat_getrootdir(const char *caller, int dnr)
3636{
3637 int block;
3638
3639 //
3640 dprintk("%s was called by %s\n",
3641 __FUNCTION__, caller);
3642
3643 //
3644 FFCHECK
3645
3646 //
3647 EntranceGetrootdir=1;
3648
3649 //
3650 DEBUGLINE
3651
3652 //
3653 if(!isValidDevice(dnr))
3654 {
3655 //
3656 EntranceGetrootdir=0;
3657 printk("%s: Invalid device %d\n",
3658 __FUNCTION__, dnr);
3659 return 2;
3660 }
3661
3662 //
3663 block = jtmfat_getrootdir1(dnr);
3664 if(!block)
3665 {
3666 // Try retrying twice by first trying to chdev
3667 printk("%s: Boot block = zero ??\n",
3668 __FUNCTION__);
3669 }
3670
3671 //
3672 EntranceGetrootdir=0;
3673
3674 //
3675 return block;
3676}
3677
3678// Sets specified drive to "removable drive" -mode.
3679// Causes some minimal performance loss, but provides
3680// support for removable drives and first of all support
3681// for disk change.
3682void RemovableDevice(int dnr)
3683{
3684 //
3685 fatsys->bootinf[dnr].isRemovable = TRUE;
3686}
3687
3688// Returns the block # where the root directory resides.
3689int jtmfat_getrootdir1(int dnr)
3690{
3691 int i;
3692
3693 //
3694 DEBUGLINE
3695
3696 //
3697 if(!isValidDevice(dnr))
3698 {
3699 printk("jtmfat_getrootdir1: Invalid device %d\n",
3700 dnr);
3701 return -1988;
3702 }
3703
3704 //
3705 if(jtmfat_ready!=TRUE)
3706 return -1987;
3707
3708 // Change device if it is not yet the requested one
3709 if( fatsys->bootinf[dnr].isRemovable )
3710 {
3711 // For removable drive:
3712 if( (fatsys->bb[dnr]==NULL || !fatsys->bb[dnr]->data_offs || fatsys->isJTMFS[dnr]==FALSE) ||
3713 (GetSeconds() - fatsys->bootinf[dnr].t)>=2 )
3714 {
3715 // Update reload time.
3716 fatsys->bootinf[dnr].t = GetSeconds();
3717 // Let's load new boot block.
3718 jtmfat_LoadNewInfoBlock(dnr);
3719 }
3720 }
3721 else
3722 {
3723 // For non-removable drive:
3724 if(fatsys->bb[dnr]==NULL || !fatsys->bb[dnr]->data_offs || fatsys->isJTMFS[dnr]==FALSE)
3725 {
3726 // Let's load new boot block.
3727 jtmfat_LoadNewInfoBlock(dnr);
3728 }
3729 }
3730
3731 //
3732 dprintk("%s: Root directory at block %d on drive %d.\n",
3733 __FUNCTION__,
3734 fatsys->bb[dnr]->data_offs,
3735 dnr);
3736
3737 //
3738 return fatsys->bb[dnr]->data_offs;
3739}
3740
3741// Searches for a free block and returns it
3742// NEW: Optimized to remember location for last found
3743// free block, it'll continue search on the last position.
3744// It is much possible that it'll find another empty
3745// block after it, or it is atleast much more probable
3746// to find than when starting from the beginning at every
3747// try.
3748// When the function is called first time, it'll not
3749// use the findfreeblock_last_block_nr -variable,
3750// although it'll save the block number to it after
3751// it has ran through the operation.
3752//
3753// Fixed: Won't accept block #0 as a free one ever.
3754//
3755// Returns -1 on disk full.
3756//
3757int jtmfat_getfreeblock1(long dnr)
3758{
3759 int i,i2,amount;
3760
3761 // ------------------------------------
3762 DEBUGLINE
3763
3764 //
3765 if(jtmfat_ready!=TRUE)
3766 return -3;
3767
3768 //
3769 if( !isValidDevice(dnr) )
3770 {
3771 dprintk("jtmfat_getfreeblock1: Invalid device %d\n",
3772 dnr);
3773 return 0;
3774 }
3775
3776 // ------------------------------------
3777 DEBUGTRAP
3778
3779 //
3780 amount = getsize(dnr);
3781 if(amount<10)return -2;
3782
3783 //
3784 if (findfreeblock_last_block_nr!=-1
3785 &&
3786 findfreeblock_last_block_nr>0)
3787 {
3788 i = findfreeblock_last_block_nr;
3789 }
3790 else
3791 {
3792 //
3793 i = 0;
3794 }
3795
3796 //
3797 for(i2=0; i2<amount; i2++,i++)
3798 {
3799 //
3800 if(i<=0 || i>=amount)
3801 {
3802 i=1;
3803 }
3804
3805 //
3806 if( !jtmfat_getblock(dnr,i) )
3807 {
3808 findfreeblock_last_block_nr=i;
3809 return i;
3810 }
3811 }
3812
3813 //
3814 findfreeblock_last_block_nr=i;
3815
3816 // if not found, it returns a zero.
3817 return -1;
3818}
3819
3820//
3821long jtmfat_getfreeblock(long dnr)
3822{
3823 int b;
3824
3825 //
3826 DEBUGLINE
3827
3828 //
3829 if(!isValidDevice(dnr))
3830 {
3831 dprintk("jtmfat_getfreeblock: Invalid device %d\n",
3832 dnr);
3833 return 0;
3834 }
3835
3836 // ------------------------------------
3837 DEBUGTRAP
3838
3839 //
3840 b = jtmfat_getfreeblock1(dnr);
3841 return b;
3842}
3843
3844//------------------------------------------------------------
3845//
3846long jtmfat_isJTMFS(int dnr)
3847{
3848 //---------------------------------------
3849 // Couple checks
3850 if(jtmfat_ready!=TRUE)
3851 {
3852 printk("jtmfat isn't ready yet!\n");
3853 return FALSE;
3854 }
3855
3856 //
3857 if(!isValidDevice(dnr))
3858 return FALSE;
3859
3860 //---------------------------------------
3861 // Perform
3862 jtmfat_chdev(dnr);
3863
3864 //
3865 return fatsys->isJTMFS[dnr];
3866}
3867
3868// jtmfat_getblocksfree
3869// --------------------
3870// Returns the amount of blocks free
3871// Return value: below zero on error, zero on success
3872long jtmfat_getblocksfree(long dnr)
3873{
3874 static int i,i2,i3,i4,amount,n_free,n_allocated;
3875
3876 //
3877 DEBUGLINE
3878
3879 //
3880 if( !isValidDevice(dnr) )
3881 {
3882 dprintk("jtmfat_getblocksfree: Invalid device %d\n",
3883 dnr);
3884 return -1;
3885 }
3886
3887 // ------------------------------------
3888 DEBUGTRAP
3889
3890 // Get drive size
3891 amount=getsize(dnr);
3892 // Do sanity check
3893 if(amount<10)return 1;
3894
3895 // Find free block
3896 for(i=0,n_allocated=0,n_free=0; i<amount; i++)
3897 {
3898 if( jtmfat_getblock(dnr,i) )
3899 {
3900 n_allocated++;
3901 }
3902 else
3903 {
3904 n_free++;
3905 }
3906 }
3907
3908 //
3909 return n_free;
3910}
3911
3912// jtmfat_getblocksallocated
3913// -------------------------
3914// Returns the amount of blocks free
3915// Return value: below zero on error, zero on success
3916long jtmfat_getblocksallocated(long dnr)
3917{
3918 static int i,i2,i3,i4,
3919 amount,n_free,n_allocated;
3920
3921 //
3922 DEBUGLINE
3923
3924 //
3925 if(!isValidDevice(dnr))
3926 {
3927 dprintk("jtmfat_getblocksallocated: Invalid device %d\n",
3928 dnr);
3929 return -1;
3930 }
3931
3932 //
3933 jtmfat_chdev(dnr);
3934 if(!fatsys->isJTMFS[dnr])
3935 {
3936 dprintk("jtmfat_getblocksallocated: Non-JTMFS FS\n");
3937 return -1;
3938 }
3939
3940 // ------------------------------------
3941 DEBUGTRAP
3942
3943 //
3944 amount=getsize(dnr);
3945
3946 //
3947 for(i=0,n_allocated=0,n_free=0; i<amount; i++)
3948 {
3949 if( jtmfat_getblock(dnr,i) )
3950 {
3951 n_allocated++;
3952 }
3953 else
3954 {
3955 n_free++;
3956 }
3957 }
3958
3959 //
3960 return n_allocated;
3961}
3962
3963int jtmfat_deactivateFatDNR(int dnr)
3964{
3965 //
3966 if(!isValidDevice(dnr))return 1;
3967
3968 DEBUGLINE
3969
3970 //
3971 fatsys->fat[dnr]->isActive=0;
3972 return 0;
3973}
3974
3975//
3976void _jtmfatInformation(void)
3977{
3978 //
3979}
3980
3981//
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999// ==================================================
4000// JTMOS FILE SYSTEM
4001// -----------------
4002//
4003// (C) 2001-2004 by Jari Tuominen
4004// (jari.tuominen@kanetti.fi).
4005//
4006// JTMFS is dependent on JTMFAT.
4007// JTMFAT is dependent on a block device,
4008// which varies.
4009// The block device is accessible via
4010// the BLOCK/CHAR DEVICE API implementation,
4011// which uses a caching system.
4012//
4013// jtmfsAccess.c FS plugins access layer(high)
4014// jtmfat.c JTMOS file allocation system(low)
4015// jtmfs.c JTMOS file system(low)
4016// fswalk.c Dir walking functions(low)
4017// fsfind.c File finding functions(low)
4018// fsadd.c Directory entry adding functions(low)
4019// fsaddblocks.c Allocate more blocks on for(low)
4020// file or directory
4021// fsdev.c Functions that figure out
4022// which device is currently
4023// assigned to each of the processes(low)
4024// ==================================================
4025//----------------------------------------------------------------------
4026//
4027DEBUGSTR debugstr;
4028
4029//
4030struct
4031{
4032 int try;
4033}jtmfs_structure;
4034
4035//----------------------------------------------------------------------
4036// Called by DiskChange system function.
4037int jtmfs_DiskChange(int dnr)
4038{
4039 // Indicate boot block content change.
4040 fatsys->isJTMFS[dnr]==FALSE;
4041}
4042
4043//
4044void InitDW(DIRWALK *dw)
4045{
4046 memset(dw, 0, sizeof(DIRWALK));
4047 dw->buf_length = 8192;
4048}
4049
4050//
4051void EndDirWalk(DIRWALK *dw)
4052{
4053 //
4054 dw->isWalking=0;
4055}
4056
4057//
4058void jtmfs_inc_try(void)
4059{
4060 BYTE *dummy_buf,*dummy_buf2;
4061
4062 //
4063 jtmfs_structure.try++;
4064
4065 // print out the try number
4066 print("{"); pd32(jtmfs_structure.try); print("}");
4067
4068 // make allocation system test(see if it works at all :))
4069 dummy_buf= malloc(1024*4+4368+jtmfs_structure.try);
4070 dummy_buf2=malloc(1024*4+2352+jtmfs_structure.try);
4071 free(dummy_buf);
4072 free(dummy_buf2);
4073}
4074
4075// -----------------------------------------------------------
4076//
4077void jtmfs_init(void)
4078{
4079 //
4080 jtmfs_init_try();
4081 jtmfsAccessInit();
4082}
4083
4084// -----------------------------------------------------------
4085//
4086void jtmfs_init_try(void)
4087{
4088 jtmfs_structure.try=0;
4089}
4090
4091// -----------------------------------------------------------
4092// jtmfs_ffupdatefe
4093//
4094// Updates dw->fe to point at a correct location
4095// of dw->buf, this is done by using dw->current_offset.
4096// Updating the pointer structure makes the findfirst/next
4097// functions generally much easier to use and more efficient too.
4098//
4099void jtmfs_ffupdatefe(DIRWALK *dw)
4100{
4101 // Update offset with modern walk
4102 dw->fe = dw->d->buf+dw->current_offset;
4103
4104 // For debugging :
4105#ifdef JTMFSDEBUG
4106 dprintk("%s: dw->fe=0x%x, dw->d->buf=0x%x, dw->buf=0x%x\n",
4107 __FUNCTION__,
4108 dw->fe,
4109 dw->d->buf,
4110 dw->buf);
4111#endif
4112}
4113
4114
4115
4116/* typedef struct
4117 * {
4118 * // sizeof, bytes :
4119 * // 0x00
4120 * char name[31];
4121 * unsigned short int type;
4122 * unsigned int length; (if -1 then entry is a ghost, deleted)
4123 * unsigned int protection;
4124 * unsigned char owner;
4125 * unsigned int creationdate;
4126 * unsigned int lastaccessdate;
4127 * unsigned int lastchangedate;
4128 * unsigned int track;
4129 * unsigned int block;
4130 * // 0x40 .... bingo
4131 * //
4132 * }JTMFS_FILE_ENTRY;
4133 */
4134
4135// Use this function to create a single file/dir entry!
4136int jtmfs_fentry( JTMFS_FILE_ENTRY *e,
4137 const char *name,
4138 unsigned short int type,
4139 unsigned int length,
4140 unsigned char protection,
4141 unsigned char owner,
4142 unsigned int creationdate,
4143 unsigned int lastaccessdate,
4144 unsigned int lastchangedate,
4145 unsigned int FirstDataBlock,
4146 unsigned int LastDataBlock)
4147{
4148 // If entry is NULL:
4149 if(e==NULL || name==NULL)
4150 return 1;
4151
4152 // If filename error:
4153 if(!strlen(name) || strlen(name)>31)
4154 return 2;
4155
4156 // First wipe
4157 memset(e, 0, sizeof(JTMFS_FILE_ENTRY));
4158 // Then copy
4159 strcpy(e->name, name);
4160 e->type= type; // 0x80 = directory
4161 e->length= length; // -1 = deleted / aka ghost
4162 e->FirstDataBlock= FirstDataBlock;
4163 e->LastDataBlock= LastDataBlock;
4164 e->magicNumber= 0xFCE2E37B;
4165
4166 // Return success.
4167 return 0;
4168}
4169
4170//--------------------------------------------------------------------------------
4171//
4172// Creates a directory entry.
4173//
4174int jtmfs_cedir(JTMFS_FILE_ENTRY *e,const char *name,
4175 int FirstDataBlock,int LastDataBlock)
4176{
4177 // null reference checker
4178 if(!e || !name)
4179 {
4180 panic("[Oops!] jtmfs_cedir called with e==NULL || name==NULL\n");
4181 return;
4182 }
4183
4184 // clear structure
4185 memset(e,0,sizeof(JTMFS_FILE_ENTRY));
4186
4187 // copy name
4188 strcpy(e->name, name);
4189 e->FirstDataBlock = FirstDataBlock;
4190 e->LastDataBlock = LastDataBlock;
4191 e->magicNumber = 0xFCE2E37B;
4192
4193 // type = directory(0x80)
4194 e->type = JTMFS_ID_DIRECTORY;
4195
4196 //
4197 return 0;
4198}
4199
4200// Creates end of directory
4201void jtmfs_cedirend(JTMFS_FILE_ENTRY *e)
4202{
4203 // NULL?
4204 if(e==NULL)
4205 {
4206 panic("[Oops!] jtmfs_cedirend called with e==NULL\n");
4207 return;
4208 }
4209
4210 // Clear entry
4211 memset(e, 0, sizeof(JTMFS_FILE_ENTRY));
4212}
4213
4214// jtmfs_createdirectory
4215//
4216// dblock = block where the directory are about to be stored at
4217// This fuction writes an independent directory on the disk.
4218// It is not a subdirectory, unless otherwise specified later on.
4219//
4220// Note!: the block where the directory will be made at,
4221// MUST be free, if not so, no directory will be created.
4222//
4223int jtmfs_createdirectory(int device_nr, int dblock, int backdb,
4224 const char *name)
4225{
4226 static JTMFS_FILE_ENTRY *fe[100];
4227 static unsigned char *p;
4228 static DWORD ad;
4229 static int i,i2,i3,i4,alal;
4230 static BYTE *buf; // It gotta be atleast as big as largest possible block
4231 static int flags;
4232 static char temp[65536];
4233 char dirname[256];
4234
4235 //-----------------------------------------------------------------------------
4236 //
4237 if(!isValidDevice(device_nr)) return 10;
4238 // JTMFS required
4239 if(!jtmfat_isJTMFS(device_nr))return 1;
4240 //
4241 if( illegal(name) )
4242 panic("ILLEGAL POINTER FOR NAME STRING, CREATE DIRECTROY");
4243 if( strlen(name)<=0 )
4244 {
4245 printk("%s: name string is empty!\n",
4246 __FUNCTION__);
4247 return 1;
4248 }
4249 printk("%s: (1)\n", __FUNCTION__);
4250
4251 //-----------------------------------------------------------------------------
4252 // Get only the directory name(e.g. resolve from path string).
4253 for(i=strlen(name)-1,i2=strlen(name); i>=0 && name[i]!='/' && i2; i2--,i--);
4254 i++;
4255 strcpy(dirname, name+i);
4256
4257 //
4258 alal = 0;
4259 printk("%s: (2)\n", __FUNCTION__);
4260
4261 // --------------------------------------------------------------------
4262 dirdb_clearCacheForDB(device_nr, dblock);
4263
4264 // TODO: here we should check for the validity of the device_nr
4265 //
4266 if(jtmfat_getblock(device_nr,dblock))
4267 {
4268 //
4269 alal = 1;
4270 //panic("jtmfs_createdirectory: Oops! Attempting to create directory on already allocated block");
4271 }
4272 printk("%s: (3)\n", __FUNCTION__);
4273
4274 // Warning, this must be freed afterwards:
4275 flags=get_eflags(); disable();
4276 buf = temp;
4277 set_eflags(flags);
4278
4279 // Wipe the block buffer.
4280 // Note: I didn't do this right away, the result was that
4281 // the directory was very messy... And it messed the workability of
4282 // the entire directory mechanism... :]
4283 ReportMessage("%s: memset\n", __FUNCTION__);
4284 memset(buf, 0, 16384);
4285
4286 printk("%s: (4)\n", __FUNCTION__);
4287
4288 // init the 100 entries array
4289 ReportMessage("%s: Initializing 100 entries array.\n", __FUNCTION__);
4290 for(i=0; i<100; i++)
4291 {
4292 ad=((DWORD)buf)+i*sizeof(JTMFS_FILE_ENTRY);
4293 fe[i]=((DWORD)ad);
4294 }
4295
4296 printk("%s: (5)\n", __FUNCTION__);
4297
4298 // Create few basic directory references
4299 // first last
4300 // block block
4301 ReportMessage("%s: A few cedirs...\n", __FUNCTION__);
4302 jtmfs_cedir( fe[0], ".", dblock,dblock );
4303 jtmfs_cedir( fe[1], "..", backdb,backdb );
4304 // Add directory name into directory.
4305 jtmfs_cedir( fe[2], dirname, 0,0 );
4306 fe[2]->type = JTMFS_ID_DIRNAME;
4307 fe[2]->length = -1;
4308 // Set end of directory.
4309 jtmfs_cedirend(fe[3]);
4310
4311 printk("%s: (6)\n", __FUNCTION__);
4312
4313 // Write on the drive
4314 printk("%s: writeblock(%d,%d, %x)\n", __FUNCTION__, device_nr,dblock,buf);
4315 writeblock(device_nr, dblock, buf);
4316 printk("%s: Done.\n", __FUNCTION__);
4317
4318 printk("%s: (7)\n", __FUNCTION__);
4319
4320 //
4321 ReportMessage("%s: setblock\n", __FUNCTION__);
4322 // Allocate it to the FAT(End of chain, so which means
4323 // that there is no next block)
4324 if(!alal)
4325 jtmfat_setblock(device_nr,dblock, 0xFFFFFFF8);
4326 ReportMessage("%s: Done.\n", __FUNCTION__);
4327
4328
4329 printk("%s: (8)\n", __FUNCTION__);
4330
4331
4332 //
4333 return 0;
4334}
4335
4336//
4337int jtmfs_getrootdir(int device_nr)
4338{
4339 if(!isValidDevice(device_nr)) return 0;
4340
4341 // We will just pass this request for the JTMFAT
4342 // (JTMFAT nowadays does this stuff).
4343 return jtmfat_getrootdir(device_nr);
4344}
4345
4346// Create root directory(used by formatdrive)
4347int jtmfs_createrootdir(int dnr)
4348{
4349 int rdnr;
4350 char *str_root="/";
4351
4352 // Device validity check
4353 if(!isValidDevice(dnr))
4354 {
4355 printk("%s: DNR %d is not a valid device!",
4356 __FUNCTION__, dnr);
4357 return 2;
4358 }
4359 // JTMFS required
4360 if(!jtmfat_isJTMFS(dnr))
4361 {
4362 printk("%s: DNR %d is not formatted! Cannot create directory.",
4363 __FUNCTION__, dnr);
4364 return 1;
4365 }
4366
4367 // Get root directory block #
4368 rdnr = jtmfs_getrootdir(dnr);
4369 // Root directory block validity check
4370 if(rdnr<=0)
4371 {
4372 printk("%s: Illegal root dir block = %d!\n",
4373 __FUNCTION__, rdnr);
4374 }
4375 else
4376 {
4377 // Create root directory
4378 printk("%s: Root dir block = %d\n",
4379 __FUNCTION__, rdnr);
4380 printk("%s: Creating directory on it:\n", __FUNCTION__);
4381 jtmfs_createdirectory(dnr, rdnr, 0, str_root);
4382 printk("%s: Directory creation completed.\n", __FUNCTION__);
4383 }
4384 return 0;
4385}
4386
4387// Lists root directory's contents
4388int jtmfs_dirroot(int device_nr)
4389{
4390 if(!isValidDevice(device_nr)) return 1;
4391
4392 // JTMFS required
4393 //
4394 jtmfs_dir( device_nr, jtmfs_getrootdir(device_nr) );
4395
4396 //
4397 return 0;
4398}
4399
4400// Checks if it is the last entry?
4401// Return value: non-zero if true, else zero
4402int jtmfs_ffIsLast(int device_nr,DIRWALK *dw)
4403{
4404 // JTMFS required
4405 if(!jtmfat_isJTMFS(device_nr))return 1;
4406
4407 //
4408 if( !strlen(dw->fe->name) ) return 1;
4409
4410 //
4411 return 0;
4412}
4413
4414int jtmfs_clearwbuf(int device_nr,DIRWALK *dw)
4415{
4416 //
4417 return 0;
4418}
4419
4420// EXPAND FILE OR DIRECTORY CHAIN
4421// ------------------------------
4422//
4423// This function expands a file chain, so that it will contain
4424// one more block.
4425// Return value: new block's number
4426// Negative value means error.
4427//
4428int jtmfs_expandchain(int device_nr,int block)
4429{
4430 int new_block;
4431
4432 // JTMFS required
4433 if(!jtmfat_isJTMFS(device_nr))return -1;
4434
4435 // TODO: make a device_nr validity check here
4436 if(1)
4437 {
4438 //
4439 ReportMessage(">");
4440
4441 // Is 'block' the last block in the chain?
4442 // not?->error
4443 if( jtmfat_getblock(device_nr, block)!=0xfffffff8 )
4444 {
4445 //
4446 DEBUGINFO
4447 dprintk("jtmfs_expandchain: error, the offered block is not last one in the chain\n");
4448 return -2;
4449 }
4450 else
4451 {
4452 // Get a new free block
4453 new_block = jtmfat_getfreeblock(device_nr);
4454
4455 //
4456 if(!new_block)
4457 {
4458 DEBUGINFO
4459 dprintk("jtmfs_expandchain: Out of disk space.\n");
4460 return -3;
4461 }
4462
4463 //
4464 if(new_block == block)
4465 {
4466 DEBUGINFO
4467 dprintk("jtmfs_expandchain error: new_block(%d) == block(%d).\n",new_block,block);
4468 dprintk("Perhaps this is a logic error in jtmfat_getfreeblock().\n");
4469 panic("oops");
4470 }
4471
4472 // Set 'block' to continue at 'new_block'
4473 jtmfat_setblock(device_nr, block,new_block);
4474 if( jtmfat_getblock(device_nr,block)!=new_block )
4475 {
4476 DEBUGINFO
4477 dprintk("jtmfs_expandchain: fatset failed.\n");
4478 return -6;
4479 }
4480
4481 // Then set 'end of chain marking' of chain at the 'new_block'
4482 jtmfat_setblock(device_nr,new_block, 0xFFFFFFF8);
4483
4484 //
4485 if( jtmfat_getblock(device_nr,block)!=new_block )
4486 {
4487 DEBUGINFO
4488 panic("jtmfs_expandchain: fatset failed.\n");
4489 return -4;
4490 }
4491
4492 //
4493 return new_block;
4494 }
4495 }
4496 else
4497 {
4498 DEBUGINFO
4499 print("jtmfs_expandchain: fatal error\n");
4500 return -5;
4501 }
4502
4503 //
4504 return 0;
4505}
4506
4507// Reads current block location at the buffer
4508// I tried to optimize it to load only when neccesary,
4509// but it didn't really work right :\
4510// TODO: WHY it is needed to load the block everytime?
4511int jtmfs_ffreadlocation(int device_nr,DIRWALK *dw)
4512{
4513 // JTMFS required
4514 if(!jtmfat_isJTMFS(device_nr))return 1;
4515
4516 //
4517 if(dw)
4518 {
4519 if(dw->isWalking)
4520 dirdb_flushRequirement(dw);
4521 }
4522
4523 //
4524 return 0;
4525}
4526
4527// Writes current buffer to the disk
4528int jtmfs_ffwritelocation(int device_nr, DIRWALK *dw)
4529{
4530 // JTMFS required
4531 if(!jtmfat_isJTMFS(device_nr))
4532 {
4533 dprintk("%s: DNR%d = non-JTMFS file system\n",
4534 __FUNCTION__, device_nr);
4535 return 1;
4536 }
4537
4538 //
4539 if(dw!=NULL)
4540 {
4541 dirdb_flushRequirement(dw);
4542 }
4543 else
4544 {
4545 dprintk("%s: ERROR Called with dw==NULL\n",
4546 __FUNCTION__);
4547 }
4548
4549 //
4550 return 0;
4551}
4552
4553/* typedef struct
4554 * {
4555 * // sizeof, bytes :
4556 * // 0x00
4557 * 00 char name[31];
4558 * 20 unsigned short int type;
4559 * 22 unsigned int length;
4560 * 26 unsigned int protection;
4561 * 2a unsigned char owner;
4562 * 2b unsigned int creationdate;
4563 * 2f unsigned int lastaccessdate;
4564 * 33 unsigned int lastchangedate;
4565 * 37 unsigned int track;
4566 * 3b unsigned int block;
4567 * 3f unsigned char unused;
4568 * // 0x40 .... bingo
4569 * //
4570 * }JTMFS_FILE_ENTRY;
4571 */
4572
4573//
4574int jtmfs_entryIsDeleted(JTMFS_FILE_ENTRY *fe)
4575{
4576 if(fe->length==-1)
4577 return 1;
4578 else
4579 return 0;
4580}
4581
4582// jtmfs_deletefile dnr,fname,dirblock
4583// -----------------------------------
4584//
4585// Sets the direntry of the specified file as "free",
4586// and frees all blocks that are allocated by the file,
4587// if any.
4588//
4589// New: if dirblock equals to zero, it'll be treated as
4590// the rootdirectory(default).
4591//
4592int jtmfs_deletefile(int device_nr,const char *fname,int dirblock)
4593{
4594 static DIRWALK dw;
4595 static int delete_blocknr;
4596 static int dirblock1;
4597
4598 // Sanity check
4599 if(dirblock>=getsize(device_nr))return 1;
4600
4601 // Get fixed dirblock
4602 // If dirblock is zero, get the root directory(default).
4603 if(!dirblock)
4604 dirblock1 = jtmfs_getrootdir(device_nr);
4605 else
4606 dirblock1 = dirblock;
4607
4608 //
4609 InitDW(&dw);
4610
4611 // Find the file
4612 if( !jtmfs_ffindfile(device_nr,fname,dirblock1,&dw) )
4613 {
4614 // Not found?
4615 // Note: Heh, dir walk won't be ended when it has not even started!
4616 //// EndDirWalk(&dw);
4617 return 1;
4618 }
4619
4620 // After 'ffindfile' dirblock* parameter will be not used.
4621 // Instead the structure 'fe' will be used. If any data is
4622 // allocated.
4623 if(dw.fe->FirstDataBlock)
4624 {
4625 //
4626 delete_blocknr = dw.fe->FirstDataBlock;
4627
4628 // --- Currently the deletchain seems not to work properly ---
4629 // Try to delete the chain as we are now deleting the file
4630 if( jtmfs_deletechain(device_nr,delete_blocknr) )
4631 {
4632 //
4633 EndDirWalk(&dw);
4634 // Return non-zero if not succeeded
4635 return 2;
4636 }
4637 }
4638
4639 // At this point the file should not have any reserved blocks,
4640 // so we can set the directory entry as free as well.
4641 //
4642 // Remove the entry from the directory
4643 // This is done by setting the file's length to minus one(-1).
4644 //
4645 dw.fe->length = -1;
4646
4647 // Then we write the block back.
4648 jtmfs_ffwritelocation(device_nr,&dw);
4649
4650 //
4651 EndDirWalk(&dw);
4652
4653 // We're clear!
4654 return 0;
4655}
4656
4657// ------------------------------------------------------------------------------
4658// jtmfs_renamefile(dev, "floppy:lala", "lolo", rootdir);
4659//
4660// Renames a file or files.
4661// REN [drive:][path]filename1 filename2.
4662// Note that you cannot specify a new drive or path for your destination file.
4663//
4664int jtmfs_renamefile(int device_nr,
4665 const char *OldName, const char *NewName,
4666 int dirblock)
4667{
4668 static DIRWALK dw;
4669 static int delete_blocknr;
4670 static int dirblock1;
4671
4672 // Sanity check
4673 if(dirblock>=getsize(device_nr))return 1;
4674
4675 // Get fixed dirblock
4676 // If dirblock is zero, get the root directory(default).
4677 if(!dirblock)
4678 dirblock1 = jtmfs_getrootdir(device_nr);
4679 else
4680 dirblock1 = dirblock;
4681
4682 //
4683 InitDW(&dw);
4684
4685 // Find the file
4686 if( !jtmfs_ffindfile(device_nr,OldName,dirblock1,&dw) )
4687 {
4688 // Not found?
4689 // Note: Heh, dir walk won't be ended when it has not even started!
4690 //// EndDirWalk(&dw);
4691 return 1;
4692 }
4693
4694 // MODIFY FILE NAME
4695 //
4696 strcpy(dw.fe->name, NewName);
4697
4698 // Then we write the block back.
4699 jtmfs_ffwritelocation(device_nr,&dw);
4700
4701 //
4702 EndDirWalk(&dw);
4703
4704 // We're clear!
4705 return 0;
4706}
4707
4708// ------------------------------------------------------------------------------
4709// jtmfs_setsize(dev, "floppy:lala", new_size, rootdir);
4710//
4711// Set file fixed size (in bytes).
4712//
4713// This function only sets the visible size, but does
4714// not affect the real allocated blocks amount.
4715//
4716int jtmfs_setsize(int device_nr,
4717 const char *OldName, int newSize,
4718 int dirblock)
4719{
4720 DIRWALK dw;
4721 int delete_blocknr;
4722 int dirblock1;
4723
4724 // Sanity check
4725 if(dirblock>=getsize(device_nr))return 1;
4726
4727 // Get fixed dirblock
4728 // If dirblock is zero, get the root directory(default).
4729 if(!dirblock)
4730 dirblock1 = jtmfs_getrootdir(device_nr);
4731 else
4732 dirblock1 = dirblock;
4733
4734 //
4735 InitDW(&dw);
4736
4737 // Find the file
4738 if( !jtmfs_ffindfile(device_nr, OldName, dirblock1, &dw) )
4739 {
4740 // Not found?
4741 // Note: Heh, dir walk won't be ended when it has not even started!
4742 //// EndDirWalk(&dw);
4743 printf("%s: file not found '%s'\n",
4744 __FUNCTION__, OldName);
4745 return 1;
4746 }
4747
4748 // MODIFY FILE NAME
4749 //
4750 dw.fe->length = newSize;
4751
4752 //
4753 ReportMessage("%s: '%s': File size set to %d bytes.\n",
4754 __FUNCTION__, OldName, dw.fe->length);
4755
4756 // Then we write the block back.
4757 jtmfs_ffwritelocation(device_nr, &dw);
4758
4759 //
4760 EndDirWalk(&dw);
4761
4762 // We're clear!
4763 return 0;
4764}
4765
4766// DELETECHAIN
4767// -----------
4768//
4769// Deletes a file/dir chain
4770// (frees all the blocks of the specified chain)
4771//
4772// Returns zero on success
4773// and non-zero on error
4774//
4775// NEW: now ignores chain that is allocated on block zero.
4776//
4777// ** TODO **
4778// Something wrong here, it does not delete the chain.
4779// Instead the data is left there, maybe
4780// dump of the fat table will tell what has
4781// been happended.
4782// But it definetly does not deallocate the chain.
4783//
4784int jtmfs_deletechain(int device_nr, int blocknr)
4785{
4786 DWORD i,i2,i3,i4,b,block,first;
4787
4788 // Sanity check
4789 if(blocknr>=getsize(device_nr))return 1;
4790
4791 //
4792 for(block=blocknr,first=1; ; )
4793 {
4794 // Check if the block is the last block
4795 if( (b=jtmfat_getblock(device_nr,block))==0xfffffff8 )
4796 {
4797 jtmfat_setblock(device_nr,block,0);
4798 return 0;
4799 }
4800
4801 // Nothing allocated?(First block on chain and zero block reference)
4802 if(first && !b)
4803 {
4804 dprintk("jtmfs_deletechain: nothing allocated, block=%d, blocknr=%d, b=%d, first=%d\n",
4805 block,blocknr,b,first);
4806 return 1;
4807 }
4808
4809 //
4810 first=0;
4811
4812 // Unexpected code?
4813 if(b>=0xfffffff0)
4814 {
4815 dprintk("deletechain: FAT integrity error, unexpected F-code");
4816 dsleep(1);
4817 //waitkey();
4818 }
4819
4820 // Jump to itself?
4821 if(b==block)
4822 {
4823 dprintk("deletechain: FAT integrity error infinite jump %d => %d\n",b,block);
4824 dsleep(1);
4825 return 1;
4826 }
4827
4828 // Free first block
4829 jtmfat_setblock(device_nr,block,0);
4830
4831 // Jump to next block on chian
4832 block=b;
4833 }
4834
4835 //
4836 return 0;
4837}
4838
4839// The real getfilesize function.
4840// Returns size of the file in bytes.
4841//
4842int jtmfs_getfilesize(int dnr, const char *fname, int db)
4843{
4844 static DIRWALK dw;
4845
4846 // Find the file
4847 if( !jtmfs_ffindfile(dnr,fname,db,&dw) )
4848 {
4849 return -1;
4850 }
4851
4852 return dw.fe->length;
4853}
4854
4855// Returns size of the specified file.
4856//
4857// PERFORMANCE NOTIFICATION:
4858// This is a determistic diagnostics function and it is SLOW.
4859// It is easier to just read the file entry and use it's
4860// file size identifier variable to determine size of the file.
4861//
4862int jtmfs_getfileblocksize(int device_nr, const char *fname, int dblock)
4863{
4864 static DWORD i,i2,i3,i4,db,block,new_block,amount_to_allocate,amount;
4865 static DIRWALK dw;
4866
4867 // Find the file
4868 if( !jtmfs_ffindfile(device_nr,fname,dblock,&dw) )
4869 {
4870 // Not found? HEH! RETURN ZERO IF NOT FOUND.
4871 // We simply can't return other.
4872 return 0;
4873 }
4874
4875 // Get location of the data
4876 block = dw.fe->FirstDataBlock;
4877
4878 // No data block? => return size 0
4879 if(!block)return 0;
4880
4881 // BLOCK WALK CODE
4882 // Walk until we are at the end of the chain
4883 for(amount=1; ; amount++)
4884 {
4885 //
4886 db=jtmfat_getblock(device_nr,block);
4887
4888 // End of chain? => break
4889 if(db==0xFFFFFFF8)break;
4890 // Reserved area? => break(Error situation really!)
4891 if(db==0xFFFFFFF7)break;
4892 //
4893 if(db>=0xFFFFFFF0)
4894 {
4895 dprintk("FAT error in chain(media failure?)\n");
4896 dprintk("jtmfs_getfilesize: error, unknown FAT value(0x%x) on block %d\n",db,block);
4897 dsleep(1);
4898// waitkey();
4899 EndDirWalk(&dw);
4900 return 2;
4901 }
4902 if(db==block)
4903 {
4904 dprintk("FAT error in chain(media failure?)\n");
4905 dprintk("jtmfs_getfilesize: infinite jump to itself(FAT)\n");
4906 dsleep(1);
4907// waitkey();
4908 EndDirWalk(&dw);
4909 return 3;
4910 }
4911
4912 //
4913 block=db;
4914 }
4915
4916 //
4917 EndDirWalk(&dw);
4918
4919 //
4920 return amount;
4921}
4922
4923// Return value:
4924// 0 = Entry not found.
4925// 1 = Entry found(FILE).
4926// 2 = Entry found(DIRECTORY).
4927int jtmfs_fexist(int dnr, char *fname, int dblock)
4928{
4929 static DIRWALK dw;
4930 int rv;
4931
4932 //
4933 InitDW(&dw);
4934
4935 // Is it a device name?
4936 if( driver_getdevicenrbyname(fname)!=-1 )
4937 {
4938 // Describe it as a directory:
4939 return 2;
4940 }
4941
4942 //
4943 if( jtmfs_ffindfile(dnr, fname, dblock, &dw) )
4944 {
4945 // Determine return value upon entry type
4946 switch(dw.fe->type)
4947 {
4948 // DIRECTORY
4949 case JTMFS_ID_DIRECTORY:
4950 rv = 2;
4951 break;
4952
4953 // DIRNAME
4954 case JTMFS_ID_DIRNAME:
4955 rv = 3;
4956 break;
4957
4958 // FILE
4959 default:
4960 rv = 1;
4961 break;
4962 }
4963
4964 //
4965 EndDirWalk(&dw);
4966 return rv;
4967 }
4968 else return 0;
4969}
4970
4971//
4972
4973
4974// ======================================================================================
4975// JTMOS File System functions for Postman.
4976//
4977// (C) 2002-2005 Jari Tuominen(jari@vunet.org).
4978//
4979// jtmfs_ functions now do file name translation,
4980// which includes device detection.
4981//
4982// int jtmfs_CreateFile(const char *devname,const char *fname,int blocks);
4983// jtmfs_DeleteFile dnr, name, db
4984// jtmfs_ReadFile dnr, name, db
4985// jtmfs_WriteFile dnr, name, db
4986// jtmfs_RenameFile dnr,
4987// OldName, NewName,
4988// db
4989// jtmfs_AddBlocks dnr, fname, db, amount
4990// ======================================================================================
4991
4992// Get current work directory.
4993// Converts current DNR/DB to a path string.
4994int jtmfs_GetCWD(char *path, int max_len)
4995{
4996 int dnr,db,sdnr,sdb,odnr,odb,limit;
4997 static char name[256],tmp[256],dn[256],work[256];
4998 DIR *dir;
4999 JTMFS_FILE_ENTRY *file_entry;
5000
5001 // Define current directory location.
5002 dnr = GetCurrentDNR();
5003 db = GetCurrentDB();
5004 // Specify starting directory location.
5005 sdnr=dnr; sdb=db;
5006
5007 // Get device name string.
5008 driver_getdevicename(dnr, dn);
5009
5010 // Store initial path value.
5011 // E.g. /hda.
5012 // But if the drive is a root device,
5013 // we'll just use "/".
5014 if(dnr==getRootDNR())
5015 {
5016 // It is a root drive.
5017 strcpy(path, "/");
5018 }
5019 else
5020 {
5021 // It is not root drive,
5022 // specify device seperately.
5023 sprintf(path, "/%s/",
5024 dn);
5025 }
5026
5027 //
5028 strcpy(work, "");
5029
5030 // Follow down the path.
5031 for(limit=200; limit; limit--)
5032 {
5033 //
5034 printk("%s: DNR/DB=%d/%d\n",
5035 __FUNCTION__, GetCurrentDNR(), GetCurrentDB());
5036
5037
5038 // Convert DNR/DB to name.
5039 if( jtmfs_GetDirName(GetCurrentDNR(), GetCurrentDB(), name) )
5040 {
5041 //
5042 printk("%s: Could not convert DNR/DB to name string.\n",
5043 __FUNCTION__);
5044
5045 // Failure.
5046 break;
5047 }
5048
5049 // Is this the root directory?
5050 if(!strcmp(name, "/"))
5051 {
5052 // Yes, it is the root directory.
5053 // We're done here.
5054 printk("Answer string equals %s, we're at root directory now.\n",
5055 name);
5056 printk("Breaking off now.\n");
5057 break;
5058 }
5059
5060 // Empty name string means error.
5061 if(!strcmp(name, ""))
5062 {
5063 printk("Got empty answer string.\n");
5064 printk("Breaking off now.\n");
5065 break;
5066 }
5067
5068 // Affect work path.
5069 sprintf(tmp, "%s/", name);
5070 strcat(tmp, work);
5071 strcpy(work, tmp);
5072
5073 // Store old directory location.
5074 odnr = GetCurrentDNR();
5075 odb = GetCurrentDB();
5076
5077 // Go to directory below.
5078 jtmfs_chdir("..");
5079
5080 // We are still at same place? Assume end.
5081 if(GetCurrentDNR()==odnr && GetCurrentDB()==odb)
5082 {
5083 //
5084 printk("%s: chdir('..') failed - returned same DNR/DB position.\n",
5085 __FUNCTION__);
5086 // We could also change return value here to indicate an error.
5087 // (TODO)
5088 break;
5089 }
5090 }
5091
5092 // Build up path.
5093 strcat(path, work);
5094
5095 // If string is of >1 length . .
5096 if(strlen(path)>1)
5097 {
5098 // Remove trivial '/' at the end of string.
5099 if(path[strlen(path)-1]=='/')
5100 {
5101 path[strlen(path)-1] = 0;
5102 }
5103 }
5104
5105 // We're done here.
5106 return 0;
5107}
5108
5109
5110// TRUE = Drive is formatted and works properly.
5111// FALSE = Drive is not formatted.
5112int jtmfs_isDriveReady(int dnr)
5113{
5114 //
5115 if(!isValidDevice(dnr))
5116 return FALSE;
5117 return jtmfat_isJTMFS(dnr);
5118}
5119
5120// jtmfs_GetDirName dnr db name
5121// Converts DNR/DB to directory name.
5122// Stores directory name in string pointed by name.
5123// Zero = success.
5124// Non-zero = error.
5125int jtmfs_GetDirName(int dnr,int db, char *name)
5126{
5127 static DIRWALK dw;
5128
5129 // int dirdb_GetDirName(int dnr,int db, char *dest_name)
5130 if( dirdb_GetDirName(dnr,db, name) )
5131 {
5132 return 0;
5133 }
5134 else
5135 {
5136 // Dir name could not been resolved.
5137 strcpy(name, "");
5138 return 1;
5139 }
5140}
5141
5142//
5143int jtmfs_GetFileDataBlock(int dnr, int db, const char *name)
5144{
5145 DIRWALK dw;
5146 RESOLVE r;
5147
5148 //
5149 DEBUGLINE
5150
5151 //
5152 if( !isValidString(name) ) return 0;
5153
5154 //
5155 resolveFileNamePath(name, &dnr, &db, &r);
5156 jtmfs_ffindfile(dnr, r.name, db, &dw);
5157 return dw.fe->FirstDataBlock;
5158}
5159
5160//
5161int jtmfs_DeleteFile(int dnr, const char *name, int db)
5162{
5163 RESOLVE r;
5164
5165 //
5166 DEBUGLINE
5167
5168 //
5169 if( !isValidString(name) ) return 1;
5170
5171 //
5172 resolveFileNamePath(name, &dnr, &db, &r);
5173 // Not valid device?
5174 if( !isOK(dnr) ) return 1;
5175
5176 //
5177 return jtmfs_deletefile(dnr, r.name, db);
5178}
5179
5180// jtmfs_CreateFile [dnr] [file name] [number of blocks to allocate]
5181//
5182// Non-zero = error
5183// Zero = no error
5184//
5185// Possible return values
5186// 1: Creation of file structure failed or file name not legal
5187// ....
5188//
5189// New: If file already exists by the name, it'll be deleted.
5190//
5191// "devname" can be acquired by f.e. driver_getdevicenrbyname(syssh.str_device).
5192// When "blocks" -parameter equals zero, no blocks will be added.
5193// Function is not multitasking capable.
5194//
5195int jtmfs_CreateFile(int dnr,int db,
5196 const char *name,int blocks)
5197{
5198 JTMFS_FILE_ENTRY fe;
5199 int i,i2,i3,i4,rv;
5200 RESOLVE r;
5201
5202 //
5203 DEBUGLINE
5204
5205 //
5206 if( !isValidString(name) ) return 10;
5207
5208 //
5209 if(name==NULL)return 11;
5210
5211 //
5212 resolveFileNamePath(name, &dnr, &db, &r);
5213
5214 //
5215 dprintk("%s: Device validity check.\n", __FUNCTION__);
5216 // Not valid device?
5217 if( !isOK(dnr) )
5218 return 1986;
5219
5220 //
5221 dprintk("%s: Entry creation.\n", __FUNCTION__);
5222 //
5223 if( jtmfs_fentry(&fe,
5224 r.name,0,0,
5225 0,0,
5226 0,0,0,
5227 0,0) )
5228 {
5229 return 12;
5230 }
5231
5232 //
5233 for(i=0; i<2; i++)
5234 {
5235 //
5236 dprintk("%s: Adding entry \r", __FUNCTION__);
5237 //
5238 if( (rv=jtmfs_adddirentry(dnr, db, &fe))==10 )
5239 {
5240 //
5241 dprintk("%s: File '%s' already exists, replacing.\n",
5242 __FUNCTION__, fe.name);
5243 // Aha, file already exists? => Delete.
5244 if( jtmfs_DeleteFile(dnr, r.name, db) )return 1;
5245 continue;
5246 }
5247 if(rv)
5248 // Creation failed.
5249 return 100;
5250 break;
5251 }
5252
5253 // Assign some blocks for it(grow up it's chain=file size).
5254 // But don't add any blocks if blocks equals zero.
5255 if(blocks)
5256 {
5257 dprintk("%s: jtmfs_add_blocks_for_entry \r", __FUNCTION__);
5258 jtmfs_add_blocks_for_entry(dnr, r.name,
5259 db, blocks);
5260 }
5261
5262 //
5263 dprintk("\n%s: Work done here.\n", __FUNCTION__);
5264
5265 //
5266 return 0;
5267}
5268
5269//
5270int jtmfs_LastBlock(DWORD block)
5271{
5272 //
5273 if(block>=0xFFFFFFF0)return 1;
5274 return 0;
5275}
5276
5277// Return value:
5278// 0 = Success
5279// Non-zero = Error
5280// -1 = File not found.
5281//
5282// Returns size of the specified file in bytes.
5283int jtmfs_GetFileSize(int dnr, const char *fname, int db)
5284{
5285 RESOLVE r;
5286 int d1;
5287
5288 //
5289 DEBUGLINE
5290
5291 //
5292 if( !isValidString(fname) ) return 1;
5293
5294 //--------------------------------------------------------
5295 // Is it a device?
5296 if( (d1=driver_getdevicenrbyname(fname))!=-1 )
5297 {
5298 // Get device size in bytes and set it as return value
5299 return getblocksize(d1)*getsize(d1);
5300 }
5301
5302 //
5303 resolveFileNamePath(fname, &dnr, &db, &r);
5304
5305 // Not valid device?
5306 if( !isOK(dnr) )
5307 {
5308 dprintk("%s: Invalid device %d\n",
5309 __FUNCTION__, dnr);
5310 return 0;
5311 }
5312
5313 return jtmfs_getfilesize(dnr,r.name,db);
5314}
5315
5316// Write data to file (length, offset)
5317int jtmfs_WriteFile(int dnr,
5318 const char *name,int db,
5319 BYTE *buf, char showMeter,
5320 int preciseLength,
5321 int offset)
5322{
5323 DWORD d,newd;
5324 int i,i2,i3,i4,ii,ii2,ii3,ii4,offs,expire;
5325 DIRWALK dw;
5326 char *tmp;
5327 RESOLVE r;
5328
5329 //
5330 DEBUGLINE
5331
5332 //
5333 if( !isValidString(name) ) return 0;
5334
5335 //
5336 tmp = jtmfsAccess.rwtmp;
5337
5338 //
5339 resolveFileNamePath(name, &dnr, &db, &r);
5340
5341 // Not valid device?
5342 if( !isOK(dnr) ) return 10;
5343
5344 expire=0;
5345retry:
5346 //
5347 dprintk("%s: jtmfs_ffindfile '%s'\n", __FUNCTION__, r.name);
5348 if( !jtmfs_ffindfile(dnr, r.name, db, &dw) )
5349 {
5350 // Not found => We don't create one here, return 1.
5351 return 1;
5352 }
5353
5354 // Get data block
5355 d = dw.fe->FirstDataBlock;
5356
5357 // Check that it is a data block, if not then handle the situation
5358 if(d==0)
5359 {
5360 // jtmfs_add_blocks_for_entry(int device_nr,char *fname,
5361 // int dblock,amount)
5362 // If no data blocks => Allocate required amount
5363 ReportMessage("%s: jtmfs_add_blocks_for_entry '%s' length=%d\n",
5364 __FUNCTION__, r.name, preciseLength);
5365 if( jtmfs_add_blocks_for_entry(dnr,
5366 r.name, db,
5367 ((offset+preciseLength)/getblocksize(dnr))+1 )==10 )
5368 {
5369 ReportMessage("%s: Disk full? (%s, %d bytes requested)\n",
5370 __FUNCTION__, r.name, preciseLength);
5371 return 2;
5372 }
5373 expire++;
5374 if(expire>=2)
5375 {
5376 ReportMessage("%s: Writing of file %s failed.\n",
5377 __FUNCTION__, r.name);
5378 return 3;
5379 }
5380 goto retry;
5381 }
5382
5383 //
5384 ReportMessage(" -- jtmfs_WriteFileChain:\n");
5385 return jtmfs_WriteFileChain(buf, dnr, d,
5386 preciseLength,
5387 offset);
5388}
5389
5390// Reads specified amount of blocks from the specified file
5391int _jtmfs_ReadFile(const char *caller,
5392 int dnr, const char *name,
5393 int db,
5394 BYTE *buf, char showMeter,
5395 int preciseLength,
5396 int offset)
5397{
5398 int i,i2,i3,i4,d,newd,ii,ii2,ii3,ii4,offs,amount;
5399 DIRWALK dw;
5400 char *tmp;
5401 RESOLVE r;
5402
5403 //
5404 dprintk("%s was called by %s\n",
5405 __FUNCTION__, caller);
5406
5407 //
5408 FFCHECK
5409
5410 // Estimate amount of blocks
5411 amount = (preciseLength/getblocksize(dnr))+1;
5412
5413 //
5414 FFCHECK
5415
5416 //
5417 tmp = jtmfsAccess.rwtmp;
5418
5419 //
5420 FFCHECK
5421
5422 //
5423 DEBUGLINE
5424
5425 //
5426 FFCHECK
5427
5428 //
5429 if( !isValidString(name) ) return 0;
5430
5431 //
5432 FFCHECK
5433
5434 //
5435 resolveFileNamePath(name, &dnr, &db, &r);
5436
5437 //
5438 FFCHECK
5439
5440 // Not valid device?
5441 if( !isOK(dnr) ) return 10;
5442
5443 //
5444 FFCHECK
5445
5446 //
5447 if( !jtmfs_ffindfile(dnr, r.name, db, &dw) )
5448 {
5449 // Not found => We don't create one here, return 1.
5450 return 1;
5451 }
5452
5453 //
5454 FFCHECK
5455
5456 // Get data block
5457 d = dw.fe->FirstDataBlock;
5458
5459 //
5460 return jtmfs_ReadFileChain(buf, dnr, d,
5461 preciseLength,
5462 offset);
5463}
5464
5465// Return value:
5466// 0 = OK
5467// 1 = Error
5468int jtmfs_AddBlocks(int dnr, const char *name, int db, int amount)
5469{
5470 RESOLVE r;
5471
5472 //
5473 DEBUGLINE
5474
5475 //
5476 if( !isValidString(name) ) return 1;
5477
5478 //
5479 resolveFileNamePath(name, &dnr, &db, &r);
5480 if( !isOK(dnr) ) return 1;
5481
5482 //
5483 jtmfs_add_blocks_for_entry(dnr, r.name, db, amount);
5484 return 0;
5485}
5486
5487// File existance checker.
5488int jtmfs_Fexist(int dnr, const char *name, int db)
5489{
5490 RESOLVE r;
5491
5492 //
5493 DEBUGLINE
5494
5495 //
5496/* printk("%s: loc=%d/%d, name=%s.\n",
5497 __FUNCTION__, dnr,db, name);*/
5498
5499 //
5500 if( !isValidString(name) )
5501 {
5502 printk("%s: Name is invaldi string.\n",
5503 __FUNCTION__);
5504 return 0;
5505 }
5506
5507 //
5508 resolveFileNamePath(name, &dnr, &db, &r);
5509 if( !isOK(dnr) )
5510 {
5511 printk("%s: File system is invalid for loc %d/%d.\n",
5512 __FUNCTION__, dnr,db);
5513 return 0;
5514 }
5515
5516 //
5517/* printk("%s: Calling jtmfs_fexist with jtmfs_exist(%d, %s, %d);\n",
5518 __FUNCTION__, dnr, r.name, db);*/
5519
5520 //
5521 return jtmfs_fexist(dnr, r.name, db);
5522}
5523
5524// Set file fixed size (in bytes).
5525int jtmfs_SetSize(int dnr,
5526 const char *name, int newSize,
5527 int db)
5528{
5529 RESOLVE r;
5530
5531 //
5532 DEBUGLINE
5533
5534 //
5535 if( !isValidString(name) ) return 1;
5536
5537 //
5538 resolveFileNamePath(name, &dnr, &db, &r);
5539 if( !isOK(dnr) ) return 1;
5540
5541 //
5542 return jtmfs_setsize(dnr, r.name, newSize, db);
5543}
5544
5545//
5546int jtmfs_RenameFile(int dnr,
5547 const char *OldName, const char *NewName,
5548 int db)
5549{
5550 RESOLVE rOLD;
5551 RESOLVE rNEW;
5552 int tmp;
5553
5554 //
5555 DEBUGLINE
5556
5557 //
5558 if( !isValidString(OldName) || !isValidString(NewName) )
5559 return 1;
5560
5561 //
5562 resolveFileNamePath(OldName, &dnr, &db, &rOLD);
5563 resolveFileNamePath(NewName, &tmp, &tmp, &rNEW);
5564 if( !isOK(dnr) ) return 1;
5565
5566 //
5567 return jtmfs_renamefile(dnr, rOLD.name, rNEW.name, db);
5568}
5569
5570//
5571DWORD GetCurrentDrive(void)
5572{
5573 DEBUGLINE
5574 return scall(SYS_GETCURDEV, 0,0,0, 0,0,0);
5575}
5576
5577// chdir wrapper
5578int IntelligentCHDIR(const char *path)
5579{
5580 DEBUGLINE
5581 return jtmfs_chdir(path);
5582}
5583
5584// Used by the system call "chdir"
5585// Return value:
5586// Zero = success.
5587// Non-zero = error.
5588int jtmfs_chdir(const char *pathi)
5589{
5590 char tmp[256];
5591 int i,i2,i3,i4,old_dnr,old_db;
5592
5593 //
5594 if(pathi==NULL)return 3;
5595 if(!strlen(pathi))return 4;
5596 if( !isValidString(pathi) ) return 5;
5597 DEBUGLINE
5598
5599 // Check out for root first
5600 if(pathi[0]=='/')
5601 {
5602 // Go to root, because so was adviced to be done
5603 if( _jtmfs_chdir("/") )return 2;
5604 }
5605
5606 //
5607 old_dnr = GetCurrentDNR();
5608 old_db = GetCurrentDB();
5609
5610 //
5611 for(i=0; ; )
5612 {
5613 // Skip past possible '/'
5614 for(; i<100; i++)
5615 {
5616 if(!pathi[i])goto endi;
5617 if(pathi[i]!='/'){ goto ok2; }
5618 }
5619 // Error in string(2):
5620 break;
5621ok2:
5622
5623 // Copy the directory name
5624 for(i2=0; i<100; i++,i2++)
5625 {
5626 if(!pathi[i] || pathi[i]=='/')goto ok;
5627 tmp[i2]=pathi[i];
5628 }
5629 // Error in string(1):
5630 break;
5631ok:
5632 //
5633 tmp[i2]=0;
5634
5635 // Commence chdir -operation
5636 if( _jtmfs_chdir(tmp) )
5637 {
5638 // Error! Return back to where we came from.
5639 SetThreadDNR(GetCurrentThread(), old_dnr);
5640 SetThreadDB(GetCurrentThread(), old_db);
5641 return 1;
5642 }
5643 if(i>=strlen(pathi))break;
5644 //
5645 dprintk(".");
5646 }
5647endi:
5648 return 0;
5649}
5650
5651// Change to one place at once(part of jtmfs_chdir)
5652int _jtmfs_chdir(const char *pathi)
5653{
5654 int dnr,old_dnr,old_db,acdb,rootdnr;
5655 char str[100];
5656
5657 DEBUGLINE
5658
5659 //
5660 if( !isValidString(pathi) ) return 5;
5661
5662 //
5663 old_dnr = GetCurrentDNR();
5664 old_db = GetCurrentDB();
5665
5666 //
5667 strcpy(str, pathi);
5668 if( str[strlen(str)-1]==':' )
5669 {
5670 str[strlen(str)-1] = 0;
5671 }
5672
5673 // Detect root directory
5674 if( !strcmp(str,"/") )
5675 {
5676 //
5677 ReportMessage("%s: OK I am going to root directory now\n",
5678 __FUNCTION__);
5679 ReportMessage("DNR/DB = %d/%d\n",
5680 GetCurrentDNR(),
5681 GetCurrentDB());
5682 //dsleep(1);
5683 // Move to root device, root
5684 if( jtmfs_isDriveReady(getRootDNR()) && isOK(getRootDNR()) )
5685 {
5686 dprintk("%s: Root directory is OK, that's good.\n",
5687 __FUNCTION__);
5688 dprintk("%s: SetThreadDNR( GetCurrentThread(), getRootDNR() );\n",
5689 __FUNCTION__);
5690 SetThreadDNR(GetCurrentThread(),
5691 getRootDNR());
5692 dprintk("%s: SetThreadDB( GetCurrentThread(), jtmfat_getrootdir(GetCurrentDNR()) );\n",
5693 __FUNCTION__);
5694 SetThreadDB(GetCurrentThread(),
5695 jtmfat_getrootdir(GetCurrentDNR()));
5696 }
5697 else
5698 {
5699 ReportMessage("%s: WARNING: Root drive(DNR %d) is not formatted!\n",
5700 __FUNCTION__, getRootDNR());
5701 }
5702 ReportMessage("%s: OK I am finished here.\n",
5703 __FUNCTION__);
5704 return 0;
5705 }
5706
5707 // Try device change
5708 dnr = device(str);
5709 // Device is known?
5710 if(dnr>0)
5711 {
5712 // Only change if device is OK
5713 if( jtmfs_isDriveReady(getRootDNR()) && isOK(dnr) )
5714 {
5715 dprintk("Changing to block device %d.\n", dnr);
5716 // Define as a new current device
5717 SetThreadDNR(GetCurrentThread(), dnr);
5718 // Change root directory as default
5719 SetThreadDB( GetCurrentThread(),
5720 jtmfat_getrootdir(GetCurrentDNR()) );
5721 dprintk("Change complete: DNR/DB=%d/%d.\n",
5722 GetCurrentDNR(),
5723 GetCurrentDB());
5724 return 0;
5725 }
5726 else
5727 {
5728 // Error! Return back to where we came from.
5729 SetThreadDNR(GetCurrentThread(), old_dnr);
5730 SetThreadDB(GetCurrentThread(), old_db);
5731 return 1;
5732 }
5733 }
5734 else dprintk("%s: is not a block device.\n", str);
5735
5736 // Try directory
5737 if(jtmfs_Fexist(GetCurrentDNR(), str, GetCurrentDB())==2)
5738 {
5739 //
5740 acdb = jtmfs_GetFileDataBlock(
5741 GetCurrentDNR(),
5742 GetCurrentDB(),
5743 str);
5744 if(acdb==0)
5745 {
5746 // Zero block means let's go to root drive, root directory.
5747
5748 // Get root drive.
5749 rootdnr = getRootDNR();
5750 // Switch to root drive, root directory.
5751 SetThreadDNR(GetCurrentThread(),
5752 rootdnr);
5753 SetThreadDB(GetCurrentThread(),
5754 jtmfat_getrootdir(rootdnr) );
5755 }
5756 else
5757 {
5758 // Directory exists, let's change to it
5759 SetThreadDB(GetCurrentThread(), acdb);
5760 }
5761 return 0;
5762 }
5763
5764 // Unable to handle request, report with return value 1.
5765 dprintk("%s: Unable to handle '%s'\n",
5766 __FUNCTION__,
5767 str);
5768
5769 return 1;
5770}
5771
5772// [parent_db]
5773// |
5774// \____[target_db]
5775//
5776int jtmfs_CreateDirectory(int dnr,int db, const char *dirname)
5777{
5778 JTMFS_FILE_ENTRY e;
5779 int newBlock;
5780 RESOLVE r;
5781
5782 //
5783 DEBUGLINE
5784
5785 //
5786 if( !isValidString(dirname) ) return 5;
5787
5788 //
5789 resolveFileNamePath(dirname, &dnr,&db, &r);
5790
5791 //
5792 printk(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
5793 printk("r.name = \"%s\" -- dirname = \"%s\"\n",
5794 r.name, dirname);
5795 printk(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
5796
5797 // Device must be valid ...
5798 if( !isOK(dnr) ) return 1;
5799
5800 // Reserve a new block for the new directory.
5801 newBlock = jtmfat_getfreeblock(dnr);
5802 jtmfat_setblock(dnr, newBlock, 0xFFFFFFF8);
5803
5804 // Create entry.
5805 jtmfs_cedir(&e, r.name, newBlock, 0);
5806 // Add it.
5807 jtmfs_adddirentry(dnr, db, &e);
5808 //
5809 jtmfs_createdirectory(dnr, newBlock, db, dirname);
5810
5811 // Return assumed "OK".
5812 return 0;
5813}
5814
5815// Reads FAT tables at the start up
5816void jtmfs_PreloadFATS(void)
5817{
5818 int dnr;
5819
5820 //
5821 DEBUGLINE
5822
5823 //
5824 dnr = driver_getdevicenrbyname("hda");
5825 //if(dnr!=-1) driver_TriggerCacheActivation(dnr);
5826 dnr = driver_getdevicenrbyname("ram");
5827 //if(dnr!=-1) driver_TriggerCacheActivation(dnr);
5828}
5829
5830//
5831
5832
5833
5834// jtmfsAccessInit.c
5835
5836// Initializes kernel fileapi
5837//
5838void jtmfsAccessInit(void)
5839{
5840 // Init structure
5841 memset(&jtmfsAccess, 0, sizeof(JTMFSACCESS));
5842
5843 // Path
5844 jtmfsAccess.path = malloc(1024*4);
5845 strcpy(jtmfsAccess.path,"");
5846
5847 // Temporary buffer for block access
5848 // Must be larger than any possible drive's block size could be
5849 jtmfsAccess.rwtmp = malloc(1024*64);
5850 jtmfsAccess.rwtmp2 = malloc(1024*64);
5851
5852 //
5853 jtmfsAccess.dnr = driver_getdevicenrbyname("ram");
5854}
5855
5856
5857//==========================================================================
5858// jtmfsPath - Path to DNR/DB conversion functions.
5859// (C) 2002-2005 by Jari Tuominen(jari@vunet.org).
5860// DNR = Device #
5861// DB = Directory block #
5862//==========================================================================
5863
5864// Resolves DNR/DB from a file name containing a path,
5865// also stores path and name in seperate strings.
5866int resolveFileNamePath(const char *filepath,
5867 int *dnr,int *db,
5868 RESOLVE *r)
5869{
5870 char *p,*s,*e;
5871 int i,i2,l,detected;
5872
5873 // File name contains a path?
5874 if( strstr(filepath,"/") )
5875 {
5876 // Grep the path
5877 strcpy(r->path, filepath);
5878 for(i=strlen(r->path)-1; i!=0; i--)
5879 {
5880 if(r->path[i]=='/')
5881 {
5882 r->path[i]=0;
5883 break;
5884 }
5885 }
5886
5887 // Grep the file name.
5888 // Skip '/' charcter.
5889 i++;
5890 l = strlen(filepath);
5891 // get name
5892 for(i2=0; i<l; i++,i2++)
5893 {
5894 r->name[i2] = filepath[i];
5895 }
5896 r->name[i2]=0;
5897
5898 //
5899 resolvePath(r->path, dnr,db);
5900
5901 // Declare that we did get something
5902 detected=1;
5903 }
5904 else
5905 {
5906 // Default to "no path resolved"
5907 detected=0;
5908 strcpy(r->path, "");
5909 strcpy(r->name, filepath);
5910 }
5911 return detected;
5912}
5913
5914// Resolves a plain path into DNR/DB values
5915//
5916// resolvePath("/", &dnr,&db);
5917int resolvePath(const char *path, int *dnr,int *db)
5918{
5919 int odnr,odb;
5920
5921 // Validity check
5922 if(path==NULL || dnr==NULL || db==NULL)return 1;
5923
5924 // Save old location
5925 odnr = GetCurrentDNR();
5926 odb = GetCurrentDB();
5927
5928 // Resolve path
5929 jtmfs_chdir(path);
5930 // Store resolved DNR/DB values
5931 *dnr = GetCurrentDNR();
5932 *db = GetCurrentDB();
5933
5934 // Restore old location
5935 SetThreadDNR(GetCurrentThread(), odnr);
5936 SetThreadDB(GetCurrentThread(), odb);
5937
5938 //
5939 return 0;
5940}
5941
5942//
5943
5944//==========================================================================
5945// JTMFS Path to DNR/DB conversion functions.
5946// (C) 2002-2005 by Jari Tuominen(jari@vunet.org).
5947// DNR = Device #
5948// DB = Directory block #
5949//==========================================================================
5950
5951// Resolves DNR/DB from a file name containing a path,
5952// also stores path and name in seperate strings.
5953int resolveFileNamePath(const char *filepath,
5954 int *dnr,int *db,
5955 RESOLVE *r)
5956{
5957 char *p,*s,*e;
5958 int i,i2,l,detected;
5959
5960 // File name contains a path?
5961 if( strstr(filepath,"/") )
5962 {
5963 // Grep the path
5964 strcpy(r->path, filepath);
5965 for(i=strlen(r->path)-1; i!=0; i--)
5966 {
5967 if(r->path[i]=='/')
5968 {
5969 r->path[i]=0;
5970 break;
5971 }
5972 }
5973
5974 // Grep the file name.
5975 // Skip '/' charcter.
5976 i++;
5977 l = strlen(filepath);
5978 // get name
5979 for(i2=0; i<l; i++,i2++)
5980 {
5981 r->name[i2] = filepath[i];
5982 }
5983 r->name[i2]=0;
5984
5985 //
5986 resolvePath(r->path, dnr,db);
5987
5988 // Declare that we did get something
5989 detected=1;
5990 }
5991 else
5992 {
5993 // Default to "no path resolved"
5994 detected=0;
5995 strcpy(r->path, "");
5996 strcpy(r->name, filepath);
5997 }
5998 return detected;
5999}
6000
6001// Resolves a plain path into DNR/DB values
6002//
6003// resolvePath("/", &dnr,&db);
6004int resolvePath(const char *path, int *dnr,int *db)
6005{
6006 int odnr,odb;
6007
6008 // Validity check
6009 if(path==NULL || dnr==NULL || db==NULL)return 1;
6010
6011 // Save old location
6012 odnr = GetCurrentDNR();
6013 odb = GetCurrentDB();
6014
6015 // Resolve path
6016 jtmfs_chdir(path);
6017 // Store resolved DNR/DB values
6018 *dnr = GetCurrentDNR();
6019 *db = GetCurrentDB();
6020
6021 // Restore old location
6022 SetThreadDNR(GetCurrentThread(), odnr);
6023 SetThreadDB(GetCurrentThread(), odb);
6024
6025 //
6026 return 0;
6027}
6028
6029//
6030
6031
6032///////////////////////////////////////////////////////////////////////////////////////////
6033// JTMFS READ FILE CHAIN FUNCTIONS
6034// Bug: Misses last <512 bytes of data.
6035// (upd: bug probably fixed by now)
6036///////////////////////////////////////////////////////////////////////////////////////////
6037
6038// RETURN VALUE:
6039// Returns number of blocks read.
6040//
6041// If amount equals to -1 then whole chain is read.
6042int jtmfs_ReadFileChain(BYTE *buf, int dnr, int _d,
6043 int preciseLength,
6044 int offset)
6045{
6046 static int i,i2,i3,i4,d,newd,c,
6047 ii,ii2,ii3,ii4,bsz,skipBytes;
6048 static DIRWALK dw;
6049 static char *tmp;
6050 static int Amount,skip,boffset,fixed;
6051 static BYTE *o;
6052
6053 //
6054 DEBUGLINE
6055 FFCHECK
6056
6057 //
6058 d = _d;
6059 tmp = jtmfsAccess.rwtmp;
6060
6061 // Device must be valid
6062 if( !isOK(dnr) ) return -1;
6063
6064 //
6065 if(jtmfs_LastBlock(d))return 0;
6066
6067 //---------------------------------------------------------------------
6068 //
6069 // For debugging purposes... (to see if the buffer is loaded at full length)
6070// memset(buf, 0xBD, preciseLength);
6071
6072 //
6073 Amount = (preciseLength/getblocksize(dnr))+1;
6074 // Determine amount of blocks to skip before starting writing
6075 // (according offset)
6076 skip = offset/getblocksize(dnr);
6077 // Linear offset in block sized byte radius
6078 boffset = skip*getblocksize(dnr);
6079 // How many bytes in first block to skip to get correct offset
6080 skipBytes = offset-boffset;
6081
6082 // READ DATA FROM FILE CHAIN
6083 for(i=0,c=0,o=buf; i<(Amount+1); )
6084 {
6085 //
6086 FFCHECK
6087
6088 // Get next block or End of chain...
6089 newd = jtmfat_getblock(dnr,d);
6090
6091 // Do possible skips if needed, so we get to the right offset
6092 if(skip)
6093 {
6094 skip--;
6095 goto past;
6096 }
6097
6098 //----------------------------------------------------
6099 // * READ OPERATION *
6100
6101 //
6102 bsz = getblocksize(dnr);
6103
6104 // Do operation.
6105 readblock(dnr, d, tmp);
6106
6107 // Copy to the actual buffer.
6108 for(ii2=0; ii2<bsz;
6109 ii2++)
6110 {
6111 if(skipBytes)
6112 skipBytes--;
6113 else
6114 {
6115 // Check byte boundary
6116 if(c<preciseLength)
6117 {
6118 // Store
6119 *o = tmp[ii2]; o++;
6120 // Increase amount of bytes read
6121 c++;
6122 }
6123 }
6124 }
6125
6126 //
6127/* printk("%s: buf's first two bytes = 0x%x, 0x%x -- read offset = %d\n",
6128 __FUNCTION__,
6129 o[0], o[1],
6130 offset);*/
6131 // getch();
6132
6133 // Increase the amount of blocks read
6134 i++;
6135
6136 //----------------------------------------------------
6137 // * NEXT BLOCK *
6138past:
6139 // Unexpected chain end?
6140 if( jtmfs_LastBlock(newd) )
6141 {
6142 return i;
6143 }
6144
6145 // Change to new block
6146 d = newd;
6147 }
6148enough:
6149
6150 //
6151 if(c != preciseLength)
6152 {
6153// panic("c != preciseLength");
6154 }
6155
6156 //
6157 FFCHECK
6158 return c;
6159}
6160
6161
6162
6163
6164//=============================================================
6165// Root device functions - root.c
6166// (C) 2003 by Jari Tuominen
6167//=============================================================
6168
6169// Returns current root device number
6170int getRootDNR(void)
6171{
6172 return jtmfsAccess.dnr;
6173}
6174
6175// MOUNT ROOT
6176// ----------
6177//
6178// Return values' meaning:
6179// 0=success, other values=error
6180// (1=drive does not contain a valid JTMFS file system)
6181//
6182int mount_root(int dnr)
6183{
6184 // Not valid device?
6185 if( !isValidDevice(dnr) ) return 1;
6186 jtmfsAccess.dnr=dnr;
6187 return 0;
6188}
6189
6190// UNMOUNT ROOT
6191// ------------
6192//
6193// 0=success, other values=error
6194//
6195int umount_root(void)
6196{
6197 // Already unmounted?
6198 if(jtmfsAccess.dnr==-1)return 0;
6199
6200 // Undo the registration of a root device.
6201 // Special notification:
6202 // device #0 does not exist,
6203 // all references to device #0 always mean
6204 // device "nothing".
6205// jtmfsAccess.dnr=0;
6206 jtmfsAccess.dnr = driver_getdevicenrbyname("ram");
6207
6208 //
6209 return 0;
6210}
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221 //-----------------------------------------------------------------------
6222// Write File Chain on JTMFS.
6223// (C) 2003-2005 by Jari Tuominen.
6224//-----------------------------------------------------------------------
6225
6226//
6227int jtmfs_WriteFileChain(BYTE *buf, int dnr, int _d,
6228 int preciseLength,
6229 int offset)
6230{
6231 DEBUGLINE
6232
6233 //
6234 return jtmfs_WriteFileChainEx(buf, dnr, _d, preciseLength, offset, 1);
6235}
6236
6237// jtmfs_WriteFileChainEx
6238//
6239// More blocks is allocated if the chain does not contain
6240// enough chains for the operation.
6241// New: All newly allocated blocks will be initially erased before use.
6242// RETURN VALUE:
6243// -1 means error.
6244// -2 means disk full.
6245// 0 means no error.
6246int jtmfs_WriteFileChainEx(BYTE *buf, int dnr, int _d,
6247 int preciseLength, int offset, int useCache)
6248{
6249 static DWORD i,i2,i3,i4,d,newd,c,
6250 ii,ii2,ii3,ii4,offs,new_block,bsz,skipBytes,end;
6251 static int nb;
6252 static DIRWALK dw;
6253 static BYTE *tmp,*tmp2,*s,*o;
6254 static int amount,skip,boffset,fixed,first=TRUE;
6255
6256 //
6257 DEBUGLINE
6258
6259 //
6260 bsz = getblocksize(dnr);
6261
6262 // Determine amount in blocks
6263 amount = (preciseLength/getblocksize(dnr))+1;
6264
6265 // Determine amount of blocks to skip before starting writing
6266 // (according offset)
6267 skip = offset/getblocksize(dnr);
6268 // Linear offset in bytes to beginning of read place
6269 boffset = skip*getblocksize(dnr);
6270 // Determine amount of bytes to skip
6271 skipBytes = offset-boffset;
6272
6273 // Get tmp PTRs
6274 d = _d;
6275 tmp = jtmfsAccess.rwtmp;
6276 tmp2 = jtmfsAccess.rwtmp2;
6277
6278 // Device must be valid
6279 if( !isOK(dnr) ) return -1;
6280
6281 // Check db validity
6282 if(d<0 || d>=getsize(dnr))
6283 {
6284 ReportMessage("%s: Requested block(%d) is exceeding drive limits\n",
6285 __FUNCTION__, d);
6286 return 1200;
6287 }
6288
6289 // Check last block
6290 if(jtmfs_LastBlock(d))
6291 {
6292 ReportMessage("%s: Error! The last block was proposed as dblock param(%d)\n",
6293 __FUNCTION__, d);
6294 return 1201;
6295 }
6296
6297 // READ DATA FROM FILE CHAIN
6298 for(i=0,s=buf,c=0,first=TRUE; i<(amount+1); )
6299 {
6300 // Get next block or End of chain...
6301 newd = jtmfat_getblock(dnr,d);
6302
6303 // Do possible skips if needed, so we get to the right offset
6304 if(skip)
6305 {
6306 skip--;
6307 goto past;
6308 }
6309
6310 //--------------------------------------------------
6311 // * WRITING PROCESS *
6312
6313 //
6314 if(first==TRUE || (i+1)==amount)
6315 {
6316 first = FALSE;
6317 readblock(dnr, d, tmp);
6318 }
6319 else
6320 memset(tmp, 0, bsz);
6321
6322 // Copy to the actual buffer
6323 offs = i*bsz;
6324 for(ii2=0; ii2<bsz;
6325 ii2++)
6326 {
6327 // Write at fixed boundary
6328 if(skipBytes)
6329 skipBytes--;
6330 else
6331 {
6332 // Check byte boundary
6333 if(c<preciseLength)
6334 {
6335 // Store a single byte
6336 tmp[ii2] = *s; s++;
6337 // Increase amount of bytes written
6338 c++;
6339 }
6340 else
6341 tmp[ii2] = 0xBD;
6342 }
6343 }
6344
6345 // Do operation: To DEVAPI cache or directly to the driver.
6346 writeblock(dnr, d, tmp);
6347 printk(".");
6348
6349 // Increase the amount of blocks we've written
6350 i++;
6351
6352 //---------------------------------------------------
6353 // * GO TO NEXT BLOCK *
6354past:
6355 // Unexpected chain end & demand for more blocks?
6356 if( jtmfs_LastBlock(newd) )
6357 {
6358 // ALLOCATE MORE BLOCKS
6359 new_block = jtmfat_getfreeblock(dnr);
6360 nb = new_block;
6361 if(nb==-1)
6362 {
6363 printk("%s: Disk full!\n",
6364 __FUNCTION__);
6365 return -2;
6366 }
6367 if(new_block==0 ||
6368 new_block>=0xFFFFFFF8)
6369 {
6370 // Error: Wrong kind of BLOCK #
6371 // ReportMessage (...) ...
6372 printk("%s: ERROR: getfreeblock returns obscure block (%x) - FAT system failure or disk full?\n",
6373 __FUNCTION__, new_block);
6374 AnalyzeFATs();
6375 return 1;
6376 }
6377 jtmfat_setblock(dnr, d, new_block);
6378 jtmfat_setblock(dnr, new_block,
6379 0xFFFFFFF8);
6380 dprintk("%s: Chain expansion %d -> %d\n",
6381 __FUNCTION__,
6382 d, new_block);
6383
6384 // Swap to it
6385 newd = new_block;
6386
6387 // Erase it initially(yes this is needed)
6388 memset(tmp2, 0, getblocksize(dnr));
6389 writeblock(dnr, newd, tmp2);
6390 }
6391
6392 // Change to new block
6393 d = newd;
6394 }
6395enough:
6396 ReportMessage("%s: I wrote %d block(s) (requested = %d blocks, %d bytes precise=%d bytes)\n",
6397 __FUNCTION__, i, amount, amount*getblocksize(dnr), preciseLength);
6398 return 0;
6399}
6400
6401
6402
6403
6404//================================================================
6405// Write Directory.
6406// part of DirDB
6407//================================================================
6408
6409// Write directory on drive
6410// (Used by flush function - For cache system only.)
6411// Return value:
6412// 0 on success
6413// non-zero on error
6414int writeDir(DIR *d)
6415{
6416 int blocks,x,er;
6417 static char str[256];
6418 static BYTE *tmp;
6419 static int l_tmp;
6420
6421 //
6422 DIRDEBUG
6423
6424 //
6425 if(d==NULL)
6426 return 1;
6427
6428 // Determine amount of blocks to write
6429 if(d->type==ID_DIRECTORY)
6430 {
6431 d->n_entries = countEntries(d);
6432 blocks = sizeof(JTMFS_FILE_ENTRY)*d->n_entries/getblocksize(d->dnr);
6433 blocks++;
6434 }
6435 else
6436 // ...
6437 if(d->type==ID_FILE)
6438 {
6439 //
6440 blocks = d->blocks;
6441
6442 //
6443 printk("%s: Writing file dnr=%d, db=%d, buf=0x%x.\n",
6444 __FUNCTION__,
6445 d->dnr, d->db,
6446 d->buf);
6447 }
6448 else
6449 {
6450 // Unknown type.....
6451 printf("%s: Unknown DIR->type -type (%d).\n",
6452 __FUNCTION__, d->type);
6453 return 300;
6454 }
6455
6456 // Determine amount of entries directory has
6457 if(d->type==JTMFS_ID_DIRECTORY)
6458 {
6459 //
6460 printk("%s: Writing directory dnr=%d, db=%d, buf=0x%x.\n",
6461 __FUNCTION__,
6462 d->dnr, d->db,
6463 d->buf);
6464
6465 //
6466 d->n_entries = countEntries(d);
6467 // Inform
6468 driver_getdevicename(d->dnr, str);
6469 printk("%s: Writing directory on drive %s:\n(%d entries detected for this directory)\n",
6470 __FUNCTION__,
6471 str,
6472 d->n_entries);
6473 }
6474
6475 // Allocate tmp buffer
6476 l_tmp = (blocks+1)*getblocksize(d->dnr);
6477 tmp = malloc(l_tmp);
6478 if(tmp==NULL)
6479 {
6480 printf("%s: Out of memory --- blocks=%d, bs=%d\n",
6481 __FUNCTION__,
6482 blocks, getblocksize(d->dnr));
6483 return 303;
6484 }
6485
6486repeat:
6487 //
6488 printk("%s: writing %dK bytes (%d entries)\n",
6489 __FUNCTION__,
6490 l_tmp/1024,
6491 d->n_entries);
6492 //
6493 // Write directory blocks on chain
6494 printk("0x%x, %d,%d, %d, %d\n",
6495 d->buf, d->dnr,d->db, l_tmp,0);
6496 er=jtmfs_WriteFileChain(
6497 d->buf, d->dnr, d->db,
6498 l_tmp, 0);
6499
6500 //
6501 if(er==-2)
6502 {
6503 printk("Disk full... Can't write directory.\n");
6504 return 10;
6505 }
6506 else
6507 if(er)
6508 {
6509 printk("writeDir: error %d\n", er);
6510 panic("writeDir error");
6511 }
6512
6513 // Verify
6514 jtmfs_ReadFileChain(
6515 tmp, d->dnr, d->db,
6516 l_tmp, 0);
6517
6518 // Compare
6519 for(x=0; x<l_tmp; x++)
6520 if(d->buf[x]!=tmp[x])
6521 {
6522 printf("Difference at offset 0x%x\n", x);
6523 /** printk("dirdb:\n");
6524 DisplayMemory(d->buf+x-64, 128, 0);
6525 printk("disk:\n");
6526 DisplayMemory(tmp+x-64, 128, 0); **/
6527 //getch();
6528 //goto repeat; // !!
6529 break;
6530 }
6531
6532 //
6533 free(tmp);
6534 l_tmp=0;
6535 return 0;
6536}