3 * Support for the Rock Ridge filing system.
5 * ----------------------------------------------------------------------
6 * This code is (C) Copyright 1993,1994 by Frank Munkert.
8 * This software may be freely distributed and redistributed for
9 * non-commercial purposes, provided this notice is included.
10 * ----------------------------------------------------------------------
13 * 08-Dec-10 neil Do not mark files/dirs as unwritable/undeletable.
14 * 06-Mar-09 error - Removed madness, fixed insanity. Cleanup started
15 * 18-Aug-07 sonic Fixed reading CL and PL fields on little-endian machines
16 * 04-Jun-07 sonic Fixed endianess check in Is_A_Symbolic_Link()
17 * 05-May-07 sonic Added support for RockRidge protection bits and file comments
18 * 07-Jul-02 sheutlin various changes when porting to AROS
19 * - global variables are now in a struct Globals *global
20 * - replaced (unsigned) long by (U)LONG
21 * 05-Feb-94 fmu Added support for relocated directories.
22 * 16-Oct-93 fmu Adapted to new VOLUME structure.
25 #include <proto/exec.h>
26 #include <exec/memory.h>
34 #include "aros_stuff.h"
35 #include "clib_stuff.h"
37 #define VOL(vol,tag) (((t_iso_vol_info *)(vol->vol_info))->tag)
38 #define OBJ(obj,tag) (((t_iso_obj_info *)(obj->obj_info))->tag)
40 /* Check whether the given volume uses the Rock Ridge Interchange Protocol.
41 * The protocol is identified by the sequence
42 * 'S' 'P' 7 1 0xbe 0xef
43 * in the system use field of the (00) directory in the root directory of
46 * Returns 1 iff the RR protocol is used; 0 otherwise.
47 * If the RR protocol is used, *p_skip will be set to the skip length
48 * specified in the SP system use field.
51 t_bool
Uses_Rock_Ridge_Protocol(VOLUME
*p_volume
, int *p_skip
) {
52 ULONG loc
= VOL(p_volume
,pvd
).root
.extent_loc
;
53 directory_record
*dir
;
57 if (!(dir
= Get_Directory_Record(p_volume
, loc
, 0)))
60 system_use_pos
= 33 + dir
->file_id_length
;
61 if (system_use_pos
& 1)
64 if (system_use_pos
>= dir
->length
)
67 sys
= (unsigned char *) dir
+ system_use_pos
;
83 /* Searches for the system use field with name p_name in the directory record
84 * p_dir and fills the buffer p_buf (with length p_buf_len) with the information
85 * contained in the system use field.
87 * p_index is the ordinal number of the system use field (if more than one
88 * system use field with the same name is recorded.) 0=first occurrence,
89 * 1=second occurrence, and so on.
91 * 1 is returned if the system use field has been found; otherwise 0
95 int Get_System_Use_Field
97 VOLUME
*p_volume
, directory_record
*p_dir
,
106 ULONG length
= p_dir
->length
;
107 unsigned char *buf
= (unsigned char *) p_dir
;
109 system_use_pos
= 33 + p_dir
->file_id_length
;
110 if (system_use_pos
& 1)
112 system_use_pos
+= VOL(p_volume
,skip
);
114 /* the system use field must be at least 4 bytes long */
115 while (system_use_pos
+ 3 < length
)
117 slen
= buf
[system_use_pos
+2];
119 buf
[system_use_pos
] == p_name
[0] &&
120 buf
[system_use_pos
+1] == p_name
[1]
127 len
= (slen
< p_buf_len
) ? slen
: p_buf_len
;
128 CopyMem(buf
+ system_use_pos
, p_buf
, len
);
132 /* look for continuation area: */
134 buf
[system_use_pos
] == 'C' &&
135 buf
[system_use_pos
+1] == 'E'
138 ULONG newloc
, offset
;
139 CopyMem(buf
+ system_use_pos
+ 8, &newloc
, 4);
140 CopyMem(buf
+ system_use_pos
+ 16, &offset
, 4);
141 CopyMem(buf
+ system_use_pos
+ 24, &length
, 4);
142 if (!Read_Chunk(p_volume
->cd
, newloc
))
144 buf
= p_volume
->cd
->buffer
;
145 system_use_pos
= offset
;
149 /* look for system use field terminator: */
151 buf
[system_use_pos
] == 'S' &&
152 buf
[system_use_pos
+1] == 'T'
156 system_use_pos
+= slen
;
161 /* Determines the Rock Ridge file name of the CDROM object p_obj.
162 * The file name will be stored in the buffer p_buf (with length p_buf_len).
163 * The file name will NOT be null-terminated. The number of characters in
164 * the file name is returned. If there is no Rock Ridge file name for
165 * p_obj, then -1 is returned.
169 (VOLUME
*p_volume
, directory_record
*p_dir
, char *p_buf
, int p_buf_len
)
171 struct nm_system_use_field
{
173 unsigned char length
;
174 unsigned char version
;
185 !Get_System_Use_Field
186 (p_volume
,p_dir
,"NM",(char *)&nm
,sizeof(nm
),index
)
191 len
= (p_buf_len
< slen
) ? p_buf_len
: slen
;
193 CopyMem(nm
.name
, p_buf
, len
);
205 /* Determines the Rock Ridge Amiga protection bits and file comment of the CDROM object p_obj.
206 * Protection bits will be stored in the p_prot.
207 * The file comment will be stored in the buffer p_buf (with length p_buf_len).
208 * The file comment will NOT be null-terminated. The number of characters in
209 * the file name is returned. If there is no Rock Ridge file comment for
210 * p_obj, then -1 is returned.
213 int Get_RR_File_Comment(VOLUME
*p_volume
, directory_record
*p_dir
, uint32_t *p_prot
, char *p_buf
, int p_buf_len
)
216 #define AS_PROTECTION 0x01
217 #define AS_COMMENT 0x02
218 #define AS_COMMENT_CONTINUE 0x04
220 struct as_system_use_field
223 unsigned char length
;
224 unsigned char version
;
236 if (!Get_System_Use_Field(p_volume
,p_dir
,"AS",(char *)&as
,sizeof(as
),index
))
240 if (as
.flags
& AS_PROTECTION
) {
241 CopyMem(ptr
, &pbuf
, 4);
243 *p_prot
= AROS_BE2LONG(pbuf
) & ~(FIBF_WRITE
| FIBF_DELETE
);
245 if (!(as
.flags
& AS_COMMENT
))
248 len
= (p_buf_len
< slen
) ? p_buf_len
: slen
;
250 CopyMem(ptr
, p_buf
, len
);
253 if (!(as
.flags
& AS_COMMENT_CONTINUE
))
262 /* Returns 1 if the PX system use field indicates a symbolic link.
263 * amiga_mode is a pointer to storage area for AmigaOS protection bits.
266 int Is_A_Symbolic_Link(VOLUME
*p_volume
, directory_record
*p_dir
, uint32_t *amiga_mode
)
268 struct px_system_use_field
{
270 unsigned char length
;
271 unsigned char version
;
288 if (!Get_System_Use_Field(p_volume
,p_dir
,"PX",(char *)&px
,sizeof(px
),0))
291 if (!(px
.mode
& S_IXUSR
))
292 *amiga_mode
|= FIBF_EXECUTE
;
293 if (!(px
.mode
& S_IRUSR
))
294 *amiga_mode
|= FIBF_READ
;
295 if (px
.mode
& S_IXGRP
)
296 *amiga_mode
|= FIBF_GRP_EXECUTE
;
297 if (px
.mode
& S_IRGRP
)
298 *amiga_mode
|= FIBF_GRP_READ
;
299 if (px
.mode
& S_IXOTH
)
300 *amiga_mode
|= FIBF_OTR_EXECUTE
;
301 if (px
.mode
& S_IROTH
)
302 *amiga_mode
|= FIBF_OTR_READ
;
304 0120000 is the POSIX code for symbolic links:
306 return (px
.mode
& 0770000) == 0120000;
309 /* Read content of SL system use field.
310 * A full path name (starting with ":" or "sys:") will always be returned.
313 t_bool
Get_Link_Name(CDROM_OBJ
*p_obj
, char *p_buf
, int p_buf_len
) {
314 unsigned char buf
[256];
325 !Get_System_Use_Field
326 (p_obj
->volume
,OBJ(p_obj
,dir
),"SL",(char *)buf
,sizeof(buf
),index
)
329 return (index
== 0) ? 0 : 1;
336 if (StrLen (out
) > 256)
339 if (index
== 0 && offs
== 5)
341 /* handle the first component record: */
343 if (buf
[5] & 4) /* parent directory */
345 CDROM_OBJ
*parent1
= Find_Parent(p_obj
);
350 parent2
= Find_Parent(parent1
);
353 if (!Full_Path_Name(parent2
, fullpath
, sizeof (fullpath
)))
355 Close_Object(parent1
);
356 Close_Object(parent2
);
357 StrCat (out
, fullpath
);
361 else if (buf
[5] & 8) /* root */
362 StrCat (out
, "sys:");
363 else if (buf
[5] & 16) /* volume root */
367 /* current directory */
368 CDROM_OBJ
*parent
= Find_Parent(p_obj
);
372 if (!Full_Path_Name(parent
, fullpath
, sizeof (fullpath
)))
374 Close_Object(parent
);
375 StrCat (out
, fullpath
);
381 if (out
[0] && (c
= out
[StrLen(out
)-1]) != ':' && c
!= '/')
384 if (buf
[offs
] & 32) /* host name */
385 StrCat (out
, "AMIGA");
388 CopyMem(buf
+ offs
, out
+ len
, buf
[offs
+1]);
389 out
[len
+ buf
[offs
+1]] = 0;
391 offs
+= 2 + buf
[offs
+1];
395 if (!(buf
[4] & 1)) /* continue flag */
399 CopyMem(out
, p_buf
, p_buf_len
-1);
400 p_buf
[p_buf_len
-1] = 0;
404 /* Check whether a system use field is present: */
406 int Has_System_Use_Field
407 (VOLUME
*p_volume
, directory_record
*p_dir
, char *p_name
)
409 return Get_System_Use_Field(p_volume
, p_dir
, p_name
, NULL
, 0, 0);
412 /* Return content of "CL" system use field, or -1, if no such system use field
416 LONG
RR_Child_Link(VOLUME
*p_volume
, directory_record
*p_dir
) {
425 if (!Get_System_Use_Field(p_volume
, p_dir
,"CL",(char *)&buf
,sizeof(buf
),0))
435 /* Return content of "PL" system use field, or -1, if no such system use field
439 LONG
RR_Parent_Link(VOLUME
*p_volume
, directory_record
*p_dir
) {
448 if (!Get_System_Use_Field(p_volume
,p_dir
,"PL",(char *)&buf
,sizeof(buf
),0))