2 * Copyright (C) 2013, The AROS Development Team
4 * Author: Jason S. McMullan <jason.mcmullan@gmail.com>
6 * Licensed under the AROS PUBLIC LICENSE (APL) Version 1.1
12 #include <aros/debug.h>
14 #include <proto/exec.h>
15 #include <proto/dos.h>
16 #include <proto/utility.h>
23 struct CDFSLock il_Public
;
25 UQUAD il_Offset
; /* For read/write offset */
26 ULONG il_ParentExtent
; /* Extent of the parent directory */
30 struct isoVolume iv_Volume
;
31 struct ISOLock iv_RootLock
;
32 TEXT iv_Name
[1 + 32 + 1];
35 static ULONG
ascdec(STRPTR val
, int len
)
39 while ((*val
>= '0' && *val
<= '9') && len
> 0) {
49 #define AMIGA_EPOC 722484 /* Day number of Amiga Epoc, using Zeller */
51 static void ascdate2stamp(ascDate
*asc
, struct DateStamp
*date
)
53 ULONG year
= ascdec(asc
->Year
, 4);
54 ULONG month
= ascdec(asc
->Month
, 2);
55 ULONG day
= ascdec(asc
->Day
, 2);
61 date
->ds_Days
= (365*year
+ year
/4 - year
/100 + year
/400 + day
+ (153*month
+8)/5) - AMIGA_EPOC
;
62 date
->ds_Minute
= ascdec(asc
->Hour
, 2) * 60 +
63 ascdec(asc
->Minute
, 2);
64 date
->ds_Tick
= ascdec(asc
->Second
, 2) * 50 + ascdec(asc
->Hundredth
, 2) / 2;
66 /* FIXME: Adjust for timezone */
69 static void bindate2stamp(binDate
*bin
, struct DateStamp
*date
)
71 ULONG year
= bin
->Years
+ 1900;
72 ULONG month
= bin
->Month
;
79 date
->ds_Days
= (365*year
+ year
/4 - year
/100 + year
/400 + day
+ (153*month
+8)/5) - AMIGA_EPOC
;
80 date
->ds_Minute
= bin
->Hour
* 60 +
82 date
->ds_Tick
= bin
->Second
* 50;
84 /* FIXME: Adjust for timezone */
87 static inline ULONG
isoRead32LM(int32LM
*lm
)
89 /* What fun! Some ISO creators (ISOCD v1.04, I'm looking at you!)
90 * only filled in one side of this field.
92 #if _BYTE_ORDER == _BIG_ENDIAN
93 return lm
->MSB
? lm
->MSB
: (ULONG
)AROS_LE2LONG(lm
->LSB
);
94 #elif _BYTE_ORDER == _LITTLE_ENDIAN
95 return lm
->LSB
? lm
->LSB
: (ULONG
)AROS_BE2LONG(lm
->MSB
);
96 #else /* Wacky byte order? Impossible in this day and age. */
97 #error PDP11s are no longer supported.
101 static BOOL
isoParseDir(struct CDFSVolume
*vol
, struct ISOLock
*il
, struct isoDirectory
*dir
, ULONG iparent
)
103 struct CDFS
*cdfs
= vol
->cv_CDFSBase
;
104 struct FileInfoBlock
*fib
= &il
->il_Public
.cl_FileInfoBlock
;
105 struct FileLock
*fl
= &il
->il_Public
.cl_FileLock
;
106 struct ISOVolume
*iv
= vol
->cv_Private
;
108 BOOL has_Amiga_Protections
= FALSE
;
110 D(bug("%s: \"%s\" Extent @0x%08x, Parent 0x%08x, Flags 0x%02x\n", __func__
,
112 isoRead32LM(&dir
->ExtentLocation
), iparent
, dir
->Flags
));
114 if (dir
->Flags
& (ISO_Directory_ASSOC
| ISO_Directory_HIDDEN
))
117 il
->il_Extent
= isoRead32LM(&dir
->ExtentLocation
);
119 if (iv
&& il
->il_Extent
== iv
->iv_RootLock
.il_Extent
) {
120 CopyMem(&iv
->iv_RootLock
, il
, sizeof(*il
));
124 /* The starting location of the file is its unique 'key' */
125 fl
->fl_Key
= il
->il_Extent
;
127 fib
->fib_DirEntryType
= (dir
->Flags
& ISO_Directory_ISDIR
) ? ST_USERDIR
: ST_FILE
;
129 len
= dir
->FileIdentifierLength
;
130 if (len
> MAXFILENAMELENGTH
-2)
131 len
= MAXFILENAMELENGTH
-2;
132 for (i
= 0; i
< len
; i
++) {
133 /* Goddam VMS guys screwing up a perfectly good specification... */
134 if (dir
->FileIdentifier
[i
] == ';') {
138 fib
->fib_FileName
[i
+ 1] = dir
->FileIdentifier
[i
];
140 fib
->fib_FileName
[0] = len
;
141 fib
->fib_FileName
[len
+1] = 0;
142 fib
->fib_Protection
= FIBF_DELETE
|
152 fib
->fib_EntryType
= fib
->fib_DirEntryType
;
153 fib
->fib_Size
= isoRead32LM(&dir
->DataLength
);
154 fib
->fib_NumBlocks
= (fib
->fib_Size
+ 2047) / 2048;
155 bindate2stamp(&dir
->RecordingDate
, &fib
->fib_Date
);
156 fib
->fib_Comment
[0] = 0;
157 fib
->fib_OwnerUID
= 0;
158 fib
->fib_OwnerGID
= 0;
160 il
->il_ParentExtent
= iparent
;
162 /* Parse RockRidge extensions */
163 i
= ((UBYTE
*)&dir
->FileIdentifier
[dir
->FileIdentifierLength
] -
167 while (i
< dir
->DirectoryLength
) {
168 struct rrSystemUse
*rr
= (APTR
)(((UBYTE
*)dir
) + i
);
169 D(bug("%s: RR @%d [%c%c] (%d)\n", __func__
, i
, (AROS_BE2LONG(rr
->Signature
) >> 8) & 0xff, AROS_BE2LONG(rr
->Signature
) & 0xff, rr
->Length
));
170 if (rr
->Length
== 0) {
171 D(bug("%s: Corrupted RR section detected\n", __func__
));
174 switch (AROS_BE2LONG(rr
->Signature
)) {
175 case RR_SystemUse_AS
:
176 if (rr
->Version
== RR_SystemUse_AS_VERSION
) {
177 UBYTE
*data
= &rr
->AS
.Data
[0];
179 /* Amiga System Use area */
180 if (rr
->AS
.Flags
& RR_AS_PROTECTION
) {
181 struct SystemUseASProtection
*ap
= (APTR
)data
;
182 fib
->fib_Protection
= (ap
->User
<< 24) |
184 (ap
->MultiUser
<< 8) |
185 (ap
->Protection
<< 0);
186 data
= (UBYTE
*)&ap
[1];
187 has_Amiga_Protections
= TRUE
;
189 if (rr
->AS
.Flags
& RR_AS_COMMENT
) {
190 struct SystemUseASComment
*ac
= (APTR
)data
;
191 int len
= ac
->Length
;
192 if (len
> (MAXCOMMENTLENGTH
- fib
->fib_Comment
[0])-1) {
193 len
= (MAXCOMMENTLENGTH
- fib
->fib_Comment
[0])-1;
194 CopyMem(&ac
->Comment
[0], &fib
->fib_Comment
[fib
->fib_Comment
[0]+1], len
);
195 fib
->fib_Comment
[0] += len
;
200 case RR_SystemUse_PX
:
201 /* Don't overwrite the Amiga RR protections */
202 if (has_Amiga_Protections
)
204 if (rr
->Version
== RR_SystemUse_PX_VERSION
) {
206 ULONG mode
= isoRead32LM(&rr
->PX
.st_mode
);
207 prot
|= (mode
& S_IXOTH
) ? FIBF_OTR_EXECUTE
: 0;
208 prot
|= (mode
& S_IWOTH
) ? (FIBF_OTR_WRITE
| FIBF_OTR_DELETE
): 0;
209 prot
|= (mode
& S_IROTH
) ? FIBF_OTR_READ
: 0;
210 prot
|= (mode
& S_IXGRP
) ? FIBF_GRP_EXECUTE
: 0;
211 prot
|= (mode
& S_IWGRP
) ? (FIBF_GRP_WRITE
| FIBF_GRP_DELETE
) : 0;
212 prot
|= (mode
& S_IRGRP
) ? FIBF_GRP_READ
: 0;
213 prot
|= (mode
& S_IXUSR
) ? 0 : FIBF_EXECUTE
;
214 prot
|= (mode
& S_IWUSR
) ? 0 : (FIBF_WRITE
| FIBF_DELETE
);
215 prot
|= (mode
& S_IRUSR
) ? 0 : FIBF_READ
;
217 fib
->fib_Protection
= prot
;
218 fib
->fib_OwnerUID
= isoRead32LM(&rr
->PX
.st_uid
);
219 fib
->fib_OwnerGID
= isoRead32LM(&rr
->PX
.st_gid
);
222 case RR_SystemUse_NM
:
223 if (rr
->Version
== RR_SystemUse_NM_VERSION
) {
224 int len
= rr
->Length
- ((UBYTE
*)&rr
->NM
.Content
[0] - (UBYTE
*)rr
);
225 if (len
> (MAXCOMMENTLENGTH
- fib
->fib_FileName
[0])-1) {
226 len
= (MAXCOMMENTLENGTH
- fib
->fib_FileName
[0])-1;
227 CopyMem(&rr
->NM
.Content
[0], &fib
->fib_FileName
[fib
->fib_FileName
[0]+1], len
);
228 fib
->fib_FileName
[0] += len
;
232 case RR_SystemUse_CL
:
233 if (rr
->Version
== RR_SystemUse_CL_VERSION
) {
234 il
->il_Extent
= isoRead32LM(&rr
->CL
.ChildDirectory
);
237 case RR_SystemUse_PL
:
238 if (rr
->Version
== RR_SystemUse_PL_VERSION
) {
239 il
->il_ParentExtent
= isoRead32LM(&rr
->PL
.ParentDirectory
);
242 case RR_SystemUse_RE
:
243 if (rr
->Version
== RR_SystemUse_RE_VERSION
) {
244 /* We must ignore this entry */
248 case RR_SystemUse_TF
:
249 /* TF fields have no use under AROS */
251 case RR_SystemUse_SF
:
252 D(bug("%s: Sparse files are not (yet) supported\n"));
261 D(fib
->fib_FileName
[fib
->fib_FileName
[0]+1]=0);
263 D(bug("%s: %c Lock %p, 0x%08x: \"%s\", dir size %d\n", __func__
,
264 (fib
->fib_DirEntryType
== 0) ? 'F' : 'D',
267 &il
->il_Public
.cl_FileInfoBlock
.fib_FileName
[1],
268 dir
->DirectoryLength
));
269 D(bug("%s: @0x%08x, %d bytes\n", __func__
, il
->il_Extent
, il
->il_Public
.cl_FileInfoBlock
.fib_Size
));
274 static LONG
isoReadDir(struct CDFSVolume
*vol
, struct ISOLock
*ilock
, ULONG block
, ULONG offset
, ULONG iparent
, ULONG
*size
)
276 struct BCache
*bcache
= vol
->cv_Device
->cd_BCache
;
280 err
= BCache_Read(bcache
, block
, &buff
);
281 if (err
== RETURN_OK
) {
282 struct isoDirectory
*dir
= (APTR
)&buff
[offset
];
283 if (!isoParseDir(vol
, ilock
, dir
, iparent
))
284 err
= ERROR_OBJECT_WRONG_TYPE
;
286 if (dir
->DirectoryLength
== 0) {
287 err
= ERROR_NO_MORE_ENTRIES
;
290 *size
= dir
->DirectoryLength
;
291 if (ilock
->il_ParentExtent
== 0 &&
293 dir
->DirectoryLength
) {
294 offset
= dir
->DirectoryLength
;
295 dir
= (struct isoDirectory
*)&buff
[offset
];
296 ilock
->il_ParentExtent
= isoRead32LM(&dir
->ExtentLocation
);
298 *size
+= dir
->DirectoryLength
;
307 static LONG
isoFindCmp(struct CDFSVolume
*vol
, struct ISOLock
*ifile
, ULONG extent
, BOOL (*cmp
)(struct ISOLock
*il
, APTR data
), APTR data
)
314 /* Read the self/parent at the begining of the directory */
315 err
= isoReadDir(vol
, &tmp
, extent
, 0, 0, &size
);
316 if (err
!= RETURN_OK
)
322 while ((block
* 2048 + offset
) < tmp
.il_Public
.cl_FileInfoBlock
.fib_Size
) {
323 err
= isoReadDir(vol
, ifile
, extent
+ block
, offset
, extent
, &size
);
325 if (err
!= ERROR_OBJECT_WRONG_TYPE
) {
326 if (err
!= RETURN_OK
)
329 if (cmp(ifile
, data
))
334 if ((2048 - offset
) < sizeof(struct isoDirectory
) || size
== 0) {
343 static LONG
isoFindName(struct CDFSVolume
*vol
, struct ISOLock
*ifile
, CONST_STRPTR file
, struct ISOLock
*iparent
)
345 struct CDFS
*cdfs
= vol
->cv_CDFSBase
;
351 BOOL
cmp(struct ISOLock
*fl
, APTR data
) {
352 struct namecmp
*d
= data
;
353 D(bug("%s: file \"%s\"(%d) vs \"%s\"(%d)\n", __func__
,
354 d
->file
, d
->len
, &fl
->il_Public
.cl_FileInfoBlock
.fib_FileName
[1],
355 fl
->il_Public
.cl_FileInfoBlock
.fib_FileName
[0]));
357 return (d
->len
== fl
->il_Public
.cl_FileInfoBlock
.fib_FileName
[0] &&
358 Strnicmp(d
->file
, &ifile
->il_Public
.cl_FileInfoBlock
.fib_FileName
[1], d
->len
) == 0);
362 data
.len
= strlen(file
);
364 return isoFindCmp(vol
, ifile
, iparent
->il_Extent
, cmp
, &data
);
367 static LONG
isoFindExtent(struct CDFSVolume
*vol
, struct ISOLock
*ifile
, ULONG extent
, ULONG parent
)
369 BOOL
cmp(struct ISOLock
*fl
, APTR data
) {
370 ULONG extent
= (ULONG
)(IPTR
)data
;
371 return extent
== fl
->il_Extent
;
374 return isoFindCmp(vol
, ifile
, parent
, cmp
, (APTR
)(IPTR
)extent
);
377 LONG
ISO9660_Mount(struct CDFSVolume
*vol
)
379 struct CDFS
*cdfs
= vol
->cv_CDFSBase
;
380 struct BCache
*bcache
= vol
->cv_Device
->cd_BCache
;
381 struct ISOVolume
*iv
;
384 BOOL gotdate
= FALSE
, gotname
= FALSE
;
386 /* Don't mount filesystems with an invalid block size */
387 if (bcache
->bc_BlockSize
!= 2048)
388 return ERROR_NOT_A_DOS_DISK
;
390 iv
= AllocVec(sizeof(*iv
), MEMF_PUBLIC
| MEMF_CLEAR
);
392 return ERROR_NO_FREE_STORE
;
394 /* Check for an ISO9660 volume */
395 for (block
= 16;; block
++) {
396 struct isoVolume
*iso
;
397 err
= BCache_Read(bcache
, block
, (UBYTE
**)&iso
);
398 if (err
!= RETURN_OK
)
401 if (memcmp(iso
->Identifier
,"CD001",5) != 0) {
402 err
= ERROR_NOT_A_DOS_DISK
;
406 if (iso
->Type
== ISO_Volume_Primary
) {
408 struct ISOLock
*il
= &iv
->iv_RootLock
;
409 struct isoDirectory
*dir
= (APTR
)&iso
->Primary
.RootDirectoryEntry
[0];
411 CopyMem(iso
, &iv
->iv_Volume
, sizeof(*iso
));
412 for (i
= 0; i
< 32; i
++) {
413 iv
->iv_Name
[i
+1] = iso
->Primary
.VolumeIdentifier
[i
];
414 if (iv
->iv_Name
[i
+1] == 0)
421 /* Convert from ISO date to DOS Datestamp */
422 ascdate2stamp(&iso
->Primary
.VolumeCreation
, &vol
->cv_DosVolume
.dl_VolumeDate
);
425 isoParseDir(vol
, il
, dir
, 0);
426 isoReadDir(vol
, il
, il
->il_Extent
, 0, 0, NULL
);
427 il
->il_Public
.cl_FileLock
.fl_Volume
= MKB_VOLUME(vol
);
432 if (iso
->Type
== ISO_Volume_Terminator
) {
433 vol
->cv_Private
= iv
;
434 struct ISOLock
*il
= &iv
->iv_RootLock
;
435 struct FileInfoBlock
*fib
= &il
->il_Public
.cl_FileInfoBlock
;
439 iv
->iv_Name
[1] = 'I';
440 iv
->iv_Name
[2] = 'S';
441 iv
->iv_Name
[3] = 'O';
442 iv
->iv_Name
[4] = '0';
445 #ifdef AROS_FAST_BSTR
446 vol
->cv_DosVolume
.dl_Name
= &iv
->iv_Name
[1];
448 vol
->cv_DosVolume
.dl_Name
= MKBADDR(iv
->iv_Name
);
451 struct Library
*DOSBase
;
452 if ((DOSBase
= OpenLibrary("dos.library", 0))) {
453 DateStamp(&vol
->cv_DosVolume
.dl_VolumeDate
);
454 CloseLibrary(DOSBase
);
458 /* We use the Volume as our root lock alias */
459 vol
->cv_DosVolume
.dl_Type
= AROS_MAKE_ID('I','S','O',0);
460 vol
->cv_DosVolume
.dl_Lock
= MKB_LOCK(&iv
->iv_RootLock
.il_Public
);
461 vol
->cv_Private
= iv
;
463 fib
->fib_DirEntryType
= ST_ROOT
;
464 CopyMem(AROS_BSTR_ADDR(vol
->cv_DosVolume
.dl_Name
),
465 &fib
->fib_FileName
[1],
466 AROS_BSTR_strlen(vol
->cv_DosVolume
.dl_Name
));
467 fib
->fib_FileName
[0] = AROS_BSTR_strlen(vol
->cv_DosVolume
.dl_Name
);
474 vol
->cv_Private
= NULL
;
479 LONG
ISO9660_Unmount(struct CDFSVolume
*vol
)
481 struct CDFS
*cdfs
= vol
->cv_CDFSBase
;
483 FreeVec(vol
->cv_Private
);
484 return ERROR_NO_FREE_STORE
;
487 LONG
ISO9660_Locate(struct CDFSVolume
*vol
, struct CDFSLock
*idir
, CONST_STRPTR file
, ULONG mode
, struct CDFSLock
**ifile
)
489 struct CDFS
*cdfs
= vol
->cv_CDFSBase
;
490 struct ISOLock
*fl
, *il
, tl
;
491 CONST_STRPTR path
, rest
;
494 if (mode
!= MODE_OLDFILE
)
495 return ERROR_DISK_WRITE_PROTECTED
;
497 il
= (struct ISOLock
*)idir
;
499 D(bug("%s: 0x%08x: \"%s\"\n", __func__
, il
->il_ParentExtent
, file
));
501 fl
= AllocVec(sizeof(*fl
), MEMF_PUBLIC
| MEMF_CLEAR
);
503 // Get the actual filename
504 path
= strchr(file
, ':');
506 // Switch to the root directory
507 il
= (struct ISOLock
*)B_LOCK(vol
->cv_DosVolume
.dl_Lock
);
513 while (path
[0] == 0 || path
[0] == '/') {
516 CopyMem(il
, fl
, sizeof(*fl
));
517 *ifile
= &fl
->il_Public
;
522 if (path
[0] == '/') {
526 /* Already at root? */
527 if (il
->il_Public
.cl_FileInfoBlock
.fib_DirEntryType
== ST_ROOT
)
530 /* Otherwise, move to parent */
531 err
= isoReadDir(vol
, &tl
, il
->il_ParentExtent
, 0, 0, NULL
);
532 if (err
== RETURN_OK
) {
533 /* .. and find its name in its parent */
534 isoFindExtent(vol
, &tl
, tl
.il_Extent
, tl
.il_ParentExtent
);
543 while (*path
&& (rest
= strchr(path
, '/'))) {
545 TEXT fname
[MAXFILENAMELENGTH
];
547 if ((il
->il_Public
.cl_FileInfoBlock
.fib_DirEntryType
!= ST_USERDIR
) &&
548 (il
->il_Public
.cl_FileInfoBlock
.fib_DirEntryType
!= ST_ROOT
)) {
549 return ERROR_DIR_NOT_FOUND
;
553 if (len
>= MAXFILENAMELENGTH
) {
555 return ERROR_OBJECT_NOT_FOUND
;
558 CopyMem(path
, fname
, len
);
560 D(bug("%s: path=\"%s\" rest=\"%s\" fname=\"%s\"\n",
561 __func__
, path
, rest
, fname
));
563 err
= isoFindName(vol
, fl
, fname
, il
);
564 D(bug("%s:%d isoFindName => %d\n", __func__
, __LINE__
, err
));
565 if (err
!= RETURN_OK
) {
570 CopyMem(fl
, &tl
, sizeof(*fl
));
578 *ifile
= &fl
->il_Public
;
582 err
= isoFindName(vol
, fl
, path
, il
);
583 D(bug("%s:%d isoFindName => %d\n", __func__
, __LINE__
, err
));
584 if (err
== RETURN_OK
) {
585 *ifile
= &fl
->il_Public
;
591 err
= ERROR_NO_FREE_STORE
;
597 VOID
ISO9660_Close(struct CDFSVolume
*vol
, struct CDFSLock
*fl
)
599 struct CDFS
*cdfs
= vol
->cv_CDFSBase
;
603 LONG
ISO9660_ExamineNext(struct CDFSVolume
*vol
, struct CDFSLock
*dl
, struct FileInfoBlock
*fib
)
605 struct CDFS
*cdfs
= vol
->cv_CDFSBase
;
606 ULONG offset
, block
, diskkey
;
607 struct ISOLock tl
, *il
= (struct ISOLock
*)dl
;
611 D(bug("%s: Root %p, This %p, DiskKey %d of %d\n", __func__
,
612 &((struct ISOVolume
*)vol
->cv_Private
)->iv_RootLock
, dl
,
613 fib
->fib_DiskKey
, dl
->cl_FileInfoBlock
.fib_Size
));
615 /* Skip the first two entries, which simply point to the parent
616 * The funky math is for the single-character 'filename' given
617 * to those directories, and the round-up-to int16 padding
619 if (fib
->fib_DiskKey
== 0)
620 fib
->fib_DiskKey
= (((sizeof(struct isoDirectory
)+1)+1)&~1)*2;
622 if (fib
->fib_DiskKey
>= dl
->cl_FileInfoBlock
.fib_Size
)
623 return ERROR_NO_MORE_ENTRIES
;
625 diskkey
= fib
->fib_DiskKey
;
626 block
= diskkey
/ 2048;
627 offset
= diskkey
% 2048;
629 while (diskkey
< dl
->cl_FileInfoBlock
.fib_Size
) {
630 err
= isoReadDir(vol
, &tl
, il
->il_Extent
+ block
, offset
, il
->il_Extent
, &size
);
632 if (err
!= RETURN_OK
&& err
!= ERROR_OBJECT_WRONG_TYPE
)
635 D(bug("%s: err=%d, size=%d\n", __func__
, err
, size
));
637 if ((2048 - offset
) < sizeof(struct isoDirectory
) || size
== 0) {
642 diskkey
= block
* 2048 + offset
;
644 if (err
== RETURN_OK
) {
645 struct FileInfoBlock
*tfib
= &tl
.il_Public
.cl_FileInfoBlock
;
646 CopyMem(tfib
, fib
, sizeof(*fib
));
650 err
= ERROR_NO_MORE_ENTRIES
;
653 fib
->fib_DiskKey
= diskkey
;
655 D(bug("%s: Error %d\n", __func__
, err
));
660 LONG
ISO9660_Read(struct CDFSVolume
*vol
, struct CDFSLock
*fl
, APTR buff
, SIPTR len
, SIPTR
*actualp
)
662 struct CDFS
*cdfs
= vol
->cv_CDFSBase
;
663 struct BCache
*bcache
= vol
->cv_Device
->cd_BCache
;
664 struct ISOLock
*il
= (struct ISOLock
*)fl
;
665 UQUAD size
= fl
->cl_FileInfoBlock
.fib_Size
;
668 LONG err
= RETURN_OK
;
672 block
= il
->il_Offset
/ 2048;
673 offset
= il
->il_Offset
% 2048;
674 if ((len
+ il
->il_Offset
) > size
)
675 len
= size
- il
->il_Offset
;
678 ULONG tocopy
= 2048 - offset
;
682 err
= BCache_Read(bcache
, il
->il_Extent
+ block
, &cache
);
683 if (err
!= RETURN_OK
)
685 CopyMem(cache
+ offset
, buff
, tocopy
);
690 il
->il_Offset
+= tocopy
;
700 LONG
ISO9660_Seek(struct CDFSVolume
*vol
, struct CDFSLock
*fl
, SIPTR pos
, LONG mode
, SIPTR
*oldpos
)
702 struct ISOLock
*il
= (struct ISOLock
*)fl
;
703 UQUAD size
= fl
->cl_FileInfoBlock
.fib_Size
;
705 *oldpos
= il
->il_Offset
;
707 case OFFSET_BEGINNING
:
708 if (pos
< 0 || pos
> size
)
709 return ERROR_SEEK_ERROR
;
713 if (-pos
> il
->il_Offset
||
714 (il
->il_Offset
+ pos
) > size
)
715 return ERROR_SEEK_ERROR
;
716 il
->il_Offset
+= pos
;
719 if (pos
< 0 || -pos
> size
)
720 return ERROR_SEEK_ERROR
;
721 il
->il_Offset
= size
+ pos
;
724 return ERROR_SEEK_ERROR
;
730 const struct CDFSOps ISO9660_Ops
= {
731 .op_Type
= AROS_MAKE_ID('I','S','O',0),
732 .op_Mount
= ISO9660_Mount
,
733 .op_Unmount
= ISO9660_Unmount
,
734 .op_Locate
= ISO9660_Locate
,
735 .op_Close
= ISO9660_Close
,
736 .op_ExamineNext
= ISO9660_ExamineNext
,
737 .op_Seek
= ISO9660_Seek
,
738 .op_Read
= ISO9660_Read
,