1 #ifdef FSYS_AFFS
2 #include "shared.h"
3 #include "filesys.h"
4 
5 /******************************** RDB definitions */
6 #define RDB_LOCATION_LIMIT 16
7 #define IDNAME_RIGIDDISK   0x5244534B  /* 'RDSK' */
8 
9 struct RigidDiskBlock
10 {
11     unsigned long   rdb_ID;
12     unsigned long   rdb_SummedLongs;
13     long            rdb_ChkSum;
14     unsigned long   rdb_HostID;
15     unsigned long   rdb_BlockBytes;
16     unsigned long   rdb_Flags;
17     unsigned long   rdb_BadBlockList;
18     unsigned long   rdb_PartitionList;
19     unsigned long   rdb_FileSysHeaderList;
20     unsigned long   rdb_DriveInit;
21     unsigned long   rdb_Reserved1[6];
22     unsigned long   rdb_Cylinders;
23     unsigned long   rdb_Sectors;
24     unsigned long   rdb_Heads;
25     unsigned long   rdb_Interleave;
26     unsigned long   rdb_Park;
27     unsigned long   rdb_Reserved2[3];
28     unsigned long   rdb_WritePreComp;
29     unsigned long   rdb_ReducedWrite;
30     unsigned long   rdb_StepRate;
31     unsigned long   rdb_Reserved3[5];
32     unsigned long   rdb_RDBBlocksLo;
33     unsigned long   rdb_RDBBlocksHi;
34     unsigned long   rdb_LoCylinder;
35     unsigned long   rdb_HiCylinder;
36     unsigned long   rdb_CylBlocks;
37     unsigned long   rdb_AutoParkSeconds;
38     unsigned long   rdb_HighRDSKBlock;
39     unsigned long   rdb_Reserved4;
40     char    rdb_DiskVendor[8];
41     char    rdb_DiskProduct[16];
42     char    rdb_DiskRevision[4];
43     char    rdb_ControllerVendor[8];
44     char    rdb_ControllerProduct[16];
45     char    rdb_ControllerRevision[4];
46     char    rdb_DriveInitName[40];
47 };
48 
49 struct PartitionBlock
50 {
51     unsigned long   pb_ID;
52     unsigned long   pb_SummedLongs;
53     long            pb_ChkSum;
54     unsigned long   pb_HostID;
55     unsigned long   pb_Next;
56     unsigned long   pb_Flags;
57     unsigned long   pb_Reserved1[2];
58     unsigned long   pb_DevFlags;
59     char            pb_DriveName[32];
60     unsigned long   pb_Reserved2[15];
61     unsigned long   pb_Environment[20];
62     unsigned long   pb_EReserved[12];
63 };
64 
65 #define DE_TABLESIZE    0
66 #define DE_SIZEBLOCK    1
67 #define DE_BLOCKSIZE    2
68 #define DE_NUMHEADS     3
69 #define DE_SECSPERBLOCK 4
70 #define DE_BLKSPERTRACK 5
71 #define DE_RESERVEDBLKS 6
72 #define DE_PREFAC       7
73 #define DE_INTERLEAVE   8
74 #define DE_LOWCYL       9
75 #define DE_HIGHCYL      10
76 #define DE_UPPERCYL     DE_HIGHCYL
77 #define DE_NUMBUFFERS   11
78 #define DE_BUFMEMTYPE   12
79 #define DE_MEMBUFTYPE   DE_BUFMEMTYPE
80 #define DE_MAXTRANSFER  13
81 #define DE_MASK         14
82 #define DE_BOOTPRI      15
83 #define DE_DOSTYPE      16
84 #define DE_BAUD         17
85 #define DE_CONTROL      18
86 #define DE_BOOTBLOCKS   19
87 
88 
89 /******************************** AFFS definitions */
90 #define T_SHORT		2
91 #define T_LIST			16
92 
93 #define ST_FILE		-3
94 #define ST_ROOT		1
95 #define ST_USERDIR	2
96 
97 struct BootBlock{
98 	int id;
99 	int chksum;
100 	int rootblock;
101 	int data[127];
102 };
103 
104 struct RootBlock{
105 	int p_type;					//0
106 	int n1[2];					//1-2
107 	int hashtable_size;		//3
108 	int n2;						//4
109 	int checksum;				//5
110 	int hashtable[72];		//6-77
111 	int bitmap_valid_flag;	//78
112 	int bitmap_ptrs[25];		//79-103
113 	int bitmap_extension;	//104
114 	int root_days;				//105
115 	int root_mins;				//106
116 	int root_ticks;			//107;
117 	char diskname[32];		//108-115
118 	int n3[2];					//116-117
119 	int volume_days;			//118
120 	int volume_mins;			//119
121 	int volume_ticks;			//120
122 	int creation_days;		//121
123 	int creation_mins;		//122
124 	int creation_ticks;		//123
125 	int n4[3];					//124-126
126 	int s_type;					//127
127 };
128 
129 struct DirHeader {
130 	int p_type;					//0
131 	int own_key;				//1
132 	int n1[3];					//2-4
133 	int checksum;				//5
134 	int hashtable[72];		//6-77
135 	int n2;						//78
136 	int owner;					//79
137 	int protection;			//80
138 	int n3;						//81
139 	char comment[92];			//82-104
140 	int days;					//105
141 	int mins;					//106
142 	int ticks;					//107
143 	char name[32];				//108-115
144 	int n4[2];					//116-117
145 	int linkchain;				//118
146 	int n5[5];					//119-123
147 	int hashchain;				//124
148 	int parent;					//125
149 	int n6;						//126
150 	int s_type;					//127
151 };
152 
153 struct FileHeader {
154 	int p_type;					//0
155 	int own_key;				//1
156 	int n1[3];					//2-4
157 	int checksum;				//5
158 	int filekey_table[72];	//6-77
159 	int n2;						//78
160 	int owner;					//79
161 	int protection;			//80
162 	int bytesize;				//81
163 	char comment[92];			//82-104
164 	int days;					//105
165 	int mins;					//106
166 	int ticks;					//107
167 	char name[32];				//108-115
168 	int n3[2];					//116-117
169 	int linkchain;				//118
170 	int n4[5];					//119-123
171 	int hashchain;				//124
172 	int parent;					//125
173 	int extension;				//126
174 	int s_type;					//127
175 };
176 
177 struct FileKeyExtension{
178 	int p_type;					//0
179 	int own_key;				//1
180 	int table_size;			//2
181 	int n1[2];					//3-4
182 	int checksum;				//5
183 	int filekey_table[72];	//6-77
184 	int info[46];				//78-123
185 	int n2;						//124
186 	int parent;					//125
187 	int extension;				//126
188 	int s_type;					//127
189 };
190 
191 struct Position {
192 	unsigned int block;
193 	short filekey;
194 	unsigned short byte;
195 	unsigned int offset;
196 };
197 
198 struct ReadData {
199 	unsigned int header_block;
200 	struct Position current;
201 	unsigned int filesize;
202 };
203 
204 //#warning "Big vs. little endian for configure needed"
205 #define AROS_BE2LONG(l)	\
206 	(                                  \
207 	    ((((unsigned long)(l)) >> 24) & 0x000000FFUL) | \
208 	    ((((unsigned long)(l)) >>  8) & 0x0000FF00UL) | \
209 	    ((((unsigned long)(l)) <<  8) & 0x00FF0000UL) | \
210 	    ((((unsigned long)(l)) << 24) & 0xFF000000UL)   \
211 	)
212 
213 struct CacheBlock {
214 	int blocknum;
215 	unsigned short flags;
216 	unsigned short access_count;
217 	unsigned int blockbuffer[128];
218 };
219 #define LockBuffer(x) (((struct CacheBlock *)(x))->flags |= 0x0001)
220 #define UnLockBuffer(x) (((struct CacheBlock *)(x))->flags &= ~0x0001)
221 
222 #define MAX_CACHE_BLOCKS 10
223 
224 struct FSysBuffer {
225 	struct ReadData file;
226 	struct CacheBlock blocks[MAX_CACHE_BLOCKS];
227 };
228 
229 #define bootBlock(x) ((struct BootBlock *)(x)->blockbuffer)
230 #define rootBlock(x) ((struct RootBlock *)(x)->blockbuffer)
231 #define dirHeader(x) ((struct DirHeader *)(x)->blockbuffer)
232 #define fileHeader(x) ((struct FileHeader *)(x)->blockbuffer)
233 #define extensionBlock(x) ((struct FileKeyExtension *)(x)->blockbuffer)
234 
235 #define rdsk(x) ((struct RigidDiskBlock *)(x)->blockbuffer)
236 #define part(x) ((struct PartitionBlock *)(x)->blockbuffer)
237 
238 static struct FSysBuffer *fsysb;
239 static int blockoffset; /* offset if there is an embedded RDB partition */
240 static int rootb;       /* block number of root block */
241 static int rdbb;        /* block number of rdb block */
242 
initCache(void)243 static void initCache(void)
244 {
245 int i;
246 
247 	for (i=0;i<MAX_CACHE_BLOCKS;i++)
248 	{
249 		fsysb->blocks[i].blocknum = -1;
250 		fsysb->blocks[i].flags = 0;
251 		fsysb->blocks[i].access_count = 0;
252 	}
253 }
254 
getBlock(unsigned int block)255 static struct CacheBlock *getBlock(unsigned int block)
256 {
257 struct CacheBlock *freeblock;
258 int i;
259 
260 	/* get first unlocked block */
261 	i = 0;
262 	do
263 	{
264 		freeblock = &fsysb->blocks[i++];
265 	} while (freeblock->flags & 0x0001);
266 	/* search through list if block is already loaded in */
267 	for (i=0;i<MAX_CACHE_BLOCKS;i++)
268 	{
269 		if (fsysb->blocks[i].blocknum == block)
270 		{
271 			fsysb->blocks[i].access_count++;
272 			return &fsysb->blocks[i];
273 		}
274 		if (!(fsysb->blocks[i].flags & 0x0001))
275 			if (freeblock->access_count>fsysb->blocks[i].access_count)
276 				freeblock = &fsysb->blocks[i];
277 	}
278 	freeblock->blocknum = block;
279 	devread(block+blockoffset, 0, 512, (char *)freeblock->blockbuffer);
280 	return freeblock;
281 }
282 
calcChkSum(unsigned short SizeBlock,unsigned int * buffer)283 static unsigned int calcChkSum(unsigned short SizeBlock, unsigned int *buffer)
284 {
285 unsigned int sum=0,count=0;
286 
287 	for (count=0;count<SizeBlock;count++)
288 		sum += AROS_BE2LONG(buffer[count]);
289 	return sum;
290 }
291 
affs_mount(void)292 int affs_mount(void) {
293 struct CacheBlock *cblock;
294 int i;
295 
296 	if (
297 			(current_drive & 0x80) &&
298 			(current_partition != 0xFFFFFF) &&
299 			(current_slice != 0x30)
300 		)
301 		return 0;
302 	fsysb = (struct FSysBuffer *)FSYS_BUF;
303 	blockoffset = 0;
304 	initCache();
305 	/* check for rdb partitiontable */
306 	for (i=0;i<RDB_LOCATION_LIMIT;i++)
307 	{
308 		cblock = getBlock(i);
309 		if (
310 				(
311 					((AROS_BE2LONG(bootBlock(cblock)->id) & 0xFFFFFF00)==0x444F5300) &&
312 					((AROS_BE2LONG(bootBlock(cblock)->id) & 0xFF)>0)
313 				) ||
314 				(AROS_BE2LONG(cblock->blockbuffer[0]) == IDNAME_RIGIDDISK)
315 			)
316 			break;
317 	}
318 	if (i == RDB_LOCATION_LIMIT)
319 		return 0;
320 	if (AROS_BE2LONG(cblock->blockbuffer[0]) == IDNAME_RIGIDDISK)
321 	{
322 		/* we have an RDB partition table within a MBR-Partition */
323 		rdbb = i;
324 	}
325 	else if (i<2)
326 	{
327 		/* partition type is 0x30 = AROS and AFFS formatted */
328 		rdbb = RDB_LOCATION_LIMIT;
329 		rootb = (part_length-1+2)/2;
330 		cblock = getBlock(rootb);
331 		if (
332 				(AROS_BE2LONG(rootBlock(cblock)->p_type) != T_SHORT) ||
333 				(AROS_BE2LONG(rootBlock(cblock)->s_type) != ST_ROOT) ||
334 				calcChkSum(128, cblock->blockbuffer)
335 			)
336 			return 0;
337 	}
338 	else
339 		return 0;
340 	return 1;
341 }
342 
seek(unsigned long offset)343 static int seek(unsigned long offset)
344 {
345 struct CacheBlock *cblock;
346 unsigned long block;
347 unsigned long togo;
348 
349 	block = fsysb->file.header_block;
350 
351 	togo = offset / 512;
352 	fsysb->file.current.filekey = 71-(togo % 72);
353 	togo /= 72;
354 	fsysb->file.current.byte = offset % 512;
355 	fsysb->file.current.offset = offset;
356 	while ((togo) && (block))
357 	{
358 		disk_read_func = disk_read_hook;
359 		cblock = getBlock(block);
360                 disk_read_func = NULL;
361 		block = AROS_BE2LONG(extensionBlock(cblock)->extension);
362 		togo--;
363 	}
364 	if (togo)
365 		return 1;
366 	fsysb->file.current.block = block;
367 	return 0;
368 }
369 
affs_read(char * buf,int len)370 int affs_read(char *buf, int len) {
371 struct CacheBlock *cblock;
372 unsigned short size;
373 unsigned int readbytes = 0;
374 
375 	if (fsysb->file.current.offset != filepos)
376 	{
377 		if (seek(filepos))
378 			return ERR_FILELENGTH;
379 	}
380 	if (fsysb->file.current.block == 0)
381 		return 0;
382 	if (len>(fsysb->file.filesize-fsysb->file.current.offset))
383 		len=fsysb->file.filesize-fsysb->file.current.offset;
384 	disk_read_func = disk_read_hook;
385 	cblock = getBlock(fsysb->file.current.block);
386         disk_read_func = NULL;
387 	while (len)
388 	{
389 		disk_read_func = disk_read_hook;
390 		if (fsysb->file.current.filekey<0)
391 		{
392 			fsysb->file.current.filekey = 71;
393 			fsysb->file.current.block = AROS_BE2LONG(extensionBlock(cblock)->extension);
394 			if (fsysb->file.current.block)
395 			{
396 				cblock = getBlock(fsysb->file.current.block);
397 			}
398                         //#warning "else shouldn't occour"
399 		}
400 		size = 512;
401 		size -= fsysb->file.current.byte;
402 		if (size>len)
403 		{
404 			size = len;
405 			devread
406 				(
407 					AROS_BE2LONG
408 					(
409 						extensionBlock(cblock)->filekey_table
410 							[fsysb->file.current.filekey]
411 					)+blockoffset,
412 					fsysb->file.current.byte, size, (char *)((long)buf+readbytes)
413 				);
414 			fsysb->file.current.byte += size;
415 		}
416 		else
417 		{
418 			devread
419 				(
420 					AROS_BE2LONG
421 					(
422 						extensionBlock(cblock)->filekey_table
423 							[fsysb->file.current.filekey]
424 					)+blockoffset,
425 					fsysb->file.current.byte, size, (char *)((long)buf+readbytes)
426 				);
427 			fsysb->file.current.byte = 0;
428 			fsysb->file.current.filekey--;
429 		}
430                 disk_read_func = NULL;
431 		len -= size;
432 		readbytes += size;
433 	}
434 	fsysb->file.current.offset += readbytes;
435 	filepos = fsysb->file.current.offset;
436 	return readbytes;
437 }
438 
capitalch(unsigned char ch,unsigned char flags)439 static unsigned char capitalch(unsigned char ch, unsigned char flags)
440 {
441 
442 	if ((flags==0) || (flags==1))
443 		return (unsigned char)((ch>='a') && (ch<='z') ? ch-('a'-'A') : ch);
444 	else		// DOS\(>=2)
445 		return (unsigned char)(((ch>=224) && (ch<=254) && (ch!=247)) ||
446 				 ((ch>='a') && (ch<='z')) ? ch-('a'-'A') : ch);
447 }
448 
449 // str2 is a BCPL string
noCaseStrCmp(char * str1,char * str2,unsigned char flags)450 static int noCaseStrCmp(char *str1, char *str2, unsigned char flags)
451 {
452 unsigned char length;
453 
454 	length=str2++[0];
455 	do {
456 		if ((*str1==0) && (length==0))
457 			return 0;
458 		length--;
459 //		if ((*str1==0) && (*str2==0)) return 1;
460 	} while (capitalch(*str1++,flags)==capitalch(*str2++,flags));
461 	str1--;
462 	return (*str1) ? 1 : -1;
463 }
464 
getHashKey(char * name,unsigned int tablesize,unsigned char flags)465 static unsigned int getHashKey(char *name,unsigned int tablesize, unsigned char flags)
466 {
467 unsigned int length;
468 
469 	length=0;
470 	while (name[length] != 0)
471 	    length++;
472 	while (*name!=0)
473 		length=(length * 13 +capitalch(*name++,flags)) & 0x7FF;
474 	return length%tablesize;
475 }
476 
getHeaderBlock(char * name,struct CacheBlock ** dirh)477 static grub_error_t getHeaderBlock(char *name, struct CacheBlock **dirh)
478 {
479 int key;
480 
481 	key = getHashKey(name, 72, 1);
482 	if (!dirHeader(*dirh)->hashtable[key])
483 		return ERR_FILE_NOT_FOUND;
484 	*dirh = getBlock(AROS_BE2LONG(dirHeader(*dirh)->hashtable[key]));
485 	if (calcChkSum(128, (*dirh)->blockbuffer))
486 	{
487 #ifdef DEBUG_AFFS
488 printf("ghb: %d\n", (*dirh)->blocknum);
489 #endif
490 		return ERR_FSYS_CORRUPT;
491 	}
492 	if (AROS_BE2LONG(dirHeader(*dirh)->p_type) != T_SHORT)
493 		return ERR_BAD_FILETYPE;
494 	while (noCaseStrCmp(name,dirHeader(*dirh)->name,1) != 0)
495 	{
496 		if (!dirHeader(*dirh)->hashchain)
497 			return ERR_FILE_NOT_FOUND;
498 		*dirh = getBlock(AROS_BE2LONG(dirHeader(*dirh)->hashchain));
499 		if (calcChkSum(128, (*dirh)->blockbuffer))
500 		{
501 #ifdef DEBUG_AFFS
502 printf("ghb2: %d\n", (*dirh)->blocknum);
503 #endif
504 			return ERR_FSYS_CORRUPT;
505 		}
506 		if (AROS_BE2LONG(dirHeader(*dirh)->p_type) != T_SHORT)
507 			return ERR_BAD_FILETYPE;
508 	}
509 	return 0;
510 }
511 
copyPart(char * src,char * dst)512 static char *copyPart(char *src, char *dst)
513 {
514 	while ((*src != '/') && (*src))
515 		*dst++ = *src++;
516 	if (*src == '/')
517 		src++;
518 	*dst-- = 0;
519 	/* cut off spaces at the end */
520 	while (*dst == ' ')
521 		*dst-- = 0;
522 	return src;
523 }
524 
findBlock(char * name,struct CacheBlock ** dirh)525 static grub_error_t findBlock(char *name, struct CacheBlock **dirh)
526 {
527 char dname[32];
528 int block;
529 
530 	name++;	/* skip "/" */
531 	/* partition table part */
532 	if (rdbb < RDB_LOCATION_LIMIT)
533 	{
534 	int bpc;
535 
536 		blockoffset = 0;
537 		*dirh = getBlock(rdbb);
538 		if (*name==0)
539 			return 0;
540 		name = copyPart(name, dname);
541 		bpc = AROS_BE2LONG(rdsk(*dirh)->rdb_Sectors)*AROS_BE2LONG(rdsk(*dirh)->rdb_Heads);
542 		block = AROS_BE2LONG(rdsk(*dirh)->rdb_PartitionList);
543 		while (block != -1)
544 		{
545 			*dirh = getBlock(block);
546 			if (noCaseStrCmp(dname, part(*dirh)->pb_DriveName, 1) == 0)
547 				break;
548 			block = AROS_BE2LONG(part(*dirh)->pb_Next);
549 		}
550 		if (block == -1)
551 			return ERR_FILE_NOT_FOUND;
552 		if	(
553 				((AROS_BE2LONG(part(*dirh)->pb_Environment[DE_DOSTYPE]) & 0xFFFFFF00)!=0x444F5300) ||
554 				((AROS_BE2LONG(part(*dirh)->pb_Environment[DE_DOSTYPE]) & 0xFF)==0)
555 			)
556 			return ERR_BAD_FILETYPE;
557 		blockoffset = AROS_BE2LONG(part(*dirh)->pb_Environment[DE_LOWCYL]);
558 		rootb = AROS_BE2LONG(part(*dirh)->pb_Environment[DE_HIGHCYL]);
559 		rootb = rootb-blockoffset+1; /* highcyl-lowcyl+1 */
560 		rootb *= bpc;
561 		rootb = rootb-1+AROS_BE2LONG(part(*dirh)->pb_Environment[DE_RESERVEDBLKS]);
562 		rootb /= 2;
563 		blockoffset *= bpc;
564 	}
565 
566 	/* filesystem part */
567 	*dirh = getBlock(rootb);
568 	while (*name)
569 	{
570 		if (
571 				(AROS_BE2LONG(dirHeader(*dirh)->s_type) != ST_ROOT) &&
572 				(AROS_BE2LONG(dirHeader(*dirh)->s_type) != ST_USERDIR)
573 			)
574 			return ERR_BAD_FILETYPE;
575 		name = copyPart(name, dname);
576 		errnum = getHeaderBlock(dname, dirh);
577 		if (errnum)
578 			return errnum;
579 	}
580 	return 0;
581 }
582 
583 #ifndef STAGE1_5
checkPossibility(char * filename,char * bstr)584 static void checkPossibility(char *filename, char *bstr)
585 {
586 	char cstr[32];
587 
588 	if (noCaseStrCmp(filename, bstr, 1)<=0)
589 	{
590 		if (print_possibilities>0)
591 			print_possibilities = -print_possibilities;
592 		memcpy(cstr, bstr+1, bstr[0]);
593 		cstr[bstr[0]]=0;
594 		print_a_completion(cstr);
595 	}
596 }
597 #else
598 #define checkPossibility(a, b) do { } while(0)
599 #endif
600 
affs_dir(char * dirname)601 int affs_dir(char *dirname)
602 {
603     struct CacheBlock *buffer1;
604     struct CacheBlock *buffer2;
605     char *current = dirname;
606     char filename[128];
607     char *fname = filename;
608     int i,block;
609 
610     if (print_possibilities)
611     {
612 	while (*current)
613 	    current++;
614 	while (*current != '/')
615 	    current--;
616 	current++;
617 	while (*current)
618 	{
619 	    *fname++ = *current;
620 	    *current++ = 0;
621 	}
622 	*fname=0;
623 	errnum = findBlock(dirname, &buffer1);
624 	if (errnum)
625 	    return 0;
626 	if (AROS_BE2LONG(dirHeader(buffer1)->p_type) == IDNAME_RIGIDDISK)
627 	{
628 	    block = AROS_BE2LONG(rdsk(buffer1)->rdb_PartitionList);
629 	    while (block != -1)
630 	    {
631 		buffer1 = getBlock(block);
632 		checkPossibility(filename, part(buffer1)->pb_DriveName);
633 		block = AROS_BE2LONG(part(buffer1)->pb_Next);
634 	    }
635 #ifndef STAGE1_5
636 	    if (*filename == 0)
637 		if (print_possibilities>0)
638 		    print_possibilities = -print_possibilities;
639 #endif
640 	}
641 	else if (AROS_BE2LONG(dirHeader(buffer1)->p_type) == T_SHORT)
642 	{
643 	    LockBuffer(buffer1);
644 	    for (i=0;i<72;i++)
645 	    {
646 		block = dirHeader(buffer1)->hashtable[i];
647 		while (block)
648 		{
649 		    buffer2 = getBlock(AROS_BE2LONG(block));
650 		    if (calcChkSum(128, buffer2->blockbuffer))
651 		    {
652 			errnum = ERR_FSYS_CORRUPT;
653 			return 0;
654 		    }
655 		    if (AROS_BE2LONG(dirHeader(buffer2)->p_type) != T_SHORT)
656 		    {
657 			errnum = ERR_BAD_FILETYPE;
658 			return 0;
659 		    }
660 		    checkPossibility(filename, dirHeader(buffer2)->name);
661 		    block = dirHeader(buffer2)->hashchain;
662 		}
663 	    }
664 	    UnLockBuffer(buffer1);
665 #ifndef STAGE1_5
666 	    if (*filename == 0)
667 		if (print_possibilities>0)
668 		    print_possibilities = -print_possibilities;
669 #endif
670 	}
671 	else
672 	{
673 	    errnum = ERR_BAD_FILETYPE;
674 	    return 0;
675 	}
676 	while (*current != '/')
677 	    current--;
678 	current++;
679 	fname = filename;
680 	while (*fname)
681 	    *current++ = *fname++;
682         //#warning "TODO: add some more chars until possibilities differ"
683 	if (print_possibilities>0)
684 	    errnum = ERR_FILE_NOT_FOUND;
685 	return (print_possibilities<0);
686     }
687     else
688     {
689 	while (*current && !isspace(*current))
690 	    *fname++ = *current++;
691 	*fname = 0;
692 
693 	errnum = findBlock(filename, &buffer2);
694 	if (errnum)
695 	    return 0;
696 	if (AROS_BE2LONG(fileHeader(buffer2)->s_type)!=ST_FILE)
697 	{
698 	    errnum = ERR_BAD_FILETYPE;
699 	    return 0;
700 	}
701 	fsysb->file.header_block = AROS_BE2LONG(fileHeader(buffer2)->own_key);
702 	fsysb->file.current.block = AROS_BE2LONG(fileHeader(buffer2)->own_key);
703 	fsysb->file.current.filekey = 71;
704 	fsysb->file.current.byte = 0;
705 	fsysb->file.current.offset = 0;
706 	fsysb->file.filesize = AROS_BE2LONG(fileHeader(buffer2)->bytesize);
707 	filepos = 0;
708 	filemax = fsysb->file.filesize;
709 	return 1;
710     }
711 }
712 #endif
713