Switched from AAIP-1.0 with field "AA" to AAIP-2.0 with field "AL"

because ancient Apple ISO 9660 already used "AA".
Old AAIP-1.0 enhanced images can still be read and luckily their AAIP fields
can be distinguished from eventual Apple AA fields.
release-1.5.4.branch
Thomas Schmitt 14 years ago
parent d28351c5a4
commit 21de3e2087
  1. 116
      doc/susp_aaip_2_0.txt
  2. 49
      libisofs/aaip_0_2.c
  3. 17
      libisofs/aaip_0_2.h
  4. 2
      libisofs/builder.c
  5. 33
      libisofs/fs_image.c
  6. 35
      libisofs/libisofs.h
  7. 2
      libisofs/node.c
  8. 2
      libisofs/node.h
  9. 82
      libisofs/rockridge.c
  10. 35
      libisofs/rockridge.h
  11. 90
      libisofs/rockridge_read.c

@ -2,9 +2,9 @@
Arbitrary Attribute Interchange Protocol
Version 1.0
Version 2.0
Feb 19 2009
Mar 18 2009
Interchange of Persistent File Attributes
@ -20,8 +20,8 @@ Goal is to have for each file an arbitrary number of attributes which consist
of two components (Name and Value) of arbitrary length and to have a compact
representation of ACLs.
This document describes a SUSP entry with Signature Word "AA" which collides
neither with SUSP 1.12 nor with RRIP 1.12. The AA entry has been designed
This document describes a SUSP entry with Signature Word "AL" which collides
neither with SUSP 1.12 nor with RRIP 1.12. The AL entry has been designed
to be as similar to the RRIP entry SL as possible.
The presence of AAIP shall be announced by a particular ER entry.
@ -29,22 +29,22 @@ Since the size of a SUSP entry is limited to 255, multiple entries may be
needed to describe one component. The CE mechanism of SUSP shall be used to
address enough storage if needed.
AA entries and the ER entry of AAIP shall only be present if the ER entry
AL entries and the ER entry of AAIP shall only be present if the ER entry
of RRIP is present.
-------------------------------------------------------------------------------
System Entries Provided by this Specification
* AA
* AL
Description of the "AA" System Use Entry
Description of the "AL" System Use Entry
The entry has exactly the same layout as RRIP entry SL. One has to expect
more data bytes than with SL, though, and any of the 256 possible byte values.
The reader shall be prepared to detect and handle oversized data.
One or more AA entries form the Attribute List of a file object with
One or more AL entries form the Attribute List of a file object with
an even number of components. Each two consequtive components form a pair of
Name and Value.
@ -53,12 +53,12 @@ Names must not contain byte value 0x00. Names which begin by bytes 0x01 to 0x1f
represent names in particular namespaces. See below: Namespaces.
The meaning of any other names or name parts is not specified by this document.
All AA entries except the last one shall have the CONTINUE flag set. An AA
All AL entries except the last one shall have the CONTINUE flag set. An AL
entry with CONTINUE set to 0 indicates the end of the Attribute List.
The format of the AA System Use Field is as follows:
The format of the AL System Use Field is as follows:
[1] "BP 1 to BP 2 - Signature Word" shall be (41)(41) ("AA").
[1] "BP 1 to BP 2 - Signature Word" shall be (41)(4C) ("AL").
[2] "BP 3 - Length" shall specify as an 8-bit number the length in bytes of
the AA entry recorded according to ISO 9660:7.1.1.
@ -67,18 +67,18 @@ The format of the AA System Use Field is as follows:
[4] "BP 5 - Flags" shall contain bit field flags numbered 0 to 7 starting
with the least significant bit as follows:
0 CONTINUE This AA entry continues in the next AA entry.
0 CONTINUE This AL entry continues in the next AL entry.
All other bits shall be set to 0.
[5] "BP 6 to Length - Component Area" shall contain Component Records
as described below.
| 'A' | 'A' | LENGTH | 1 | FLAGS | COMPONENT AREA |
| 'A' | 'L' | LENGTH | 1 | FLAGS | COMPONENT AREA |
Within AA entries each component (Name or Value) shall be recorded as one
Within AL entries each component (Name or Value) shall be recorded as one
or more component records. If a component does not fit into the remaining
space of an AA entry then it shall be continued in following AA entries.
space of an AL entry then it shall be continued in following AL entries.
All Component Records of a component except the last one shall have the
CONTINUE flag set. A Component Record with CONTINUE set to 0 indicates the end
@ -94,8 +94,8 @@ inform the author of this document if you find such a discrepancy.
Component Records shall be recorded contiguously within each Component Area,
starting in the first byte of the Component Area. The last Component Record
in the Component Area of an AA System Use Entry may be continued in the
Component Area of the next recorded AA System Use Entry in the same
in the Component Area of an AL System Use Entry may be continued in the
Component Area of the next recorded AL System Use Entry in the same
System Use Area.
Each Component Record shall have the following format:
@ -103,7 +103,7 @@ Each Component Record shall have the following format:
[A] "BP 1 - Component Flags" shall contain bit field flags numbered 0 to 7,
starting with the least significant bit, as follows:
0 CONTINUE This Component Record continues in the next
AA Component Record.
AL Component Record.
all others are RESERVED and shall be 0.
[B] "BP 2 - Component Length (LEN_CP)" shall specify as an 8-bit number the
@ -120,16 +120,16 @@ Each Component Record shall have the following format:
Example: Two pairs of "name"="long...content" and "one"="more" encoded as
two AA entries
two AL entries
Field 1 contains the Component Record of Name and one Component Record of
Value :
{ 'A', 'A', 255, 1, 1,
{ 'A', 'L', 255, 1, 1,
0, 4, 'n', 'a', 'm', 'e',
1, 255, 'l', 'o', 'n', 'g', ... 238 more bytes, 13 go to next AA ... }
1, 255, 'l', 'o', 'n', 'g', ... 238 more bytes, 13 go to next AL ... }
Field 2 contains the rest of "long...content" and the complete second pair.
It marks the end of the Attribute List :
{ 'A', 'A', 38, 1, 0,
{ 'A', 'L', 38, 1, 0,
... 13 remaining bytes of the Component Record in first entry ...
0, 7, 'c', 'o', 'n', 't', 'e', 'n', 't',
0, 3, 'o', 'n', 'e',
@ -166,7 +166,9 @@ The reserved start bytes of names have the following meaning
0x02 namespace "system."
0x03 namespace "user."
0x04 namespace "isofs."
0x05 to 0x1F shall not be used yet.
0x05 namespace "trusted."
0x06 namespace "security."
0x07 to 0x1F shall not be used yet.
Examples:
Name "user.abc" with and without short notation. Both is allowed.
@ -249,7 +251,7 @@ An eventually needed qualifier is stored in one or more Qualifier Records.
Example: From man 5 acl: u::rw-,u:lisa:rw-,g::r--,g:toolies:rw-,m::r--,o::r--
"lisa" has user number 123, "toolies" has group number 65534
{ 'A', 'A', 20, 1, 0,
{ 'A', 'L', 20, 1, 0,
0, 0,
0, 11, 0x16,
0xAE, 1, 123,
@ -260,7 +262,7 @@ Example: From man 5 acl: u::rw-,u:lisa:rw-,g::r--,g:toolies:rw-,m::r--,o::r--
Example: "Access" ACL and "default" ACL (0x81 is the switch mark)
u::rwx,g::r-x,o::r-x, du::rwx,dg::r-x,dm::rwx,do::r-x,du:lisa:rwx
{ 'A', 'A', 20, 1, 0,
{ 'A', 'L', 20, 1, 0,
0, 0,
0, 11, 0x17, 0x35, 0x65,
0x81,
@ -280,7 +282,7 @@ may not appear in the root of directory sub trees.
An interested reader shall examine the Arbitrary Attributes of this Directory
Entry in order to collect a translation table.
The advised translation is: PX or AA Id number -> name -> local id number.
The advised translation is: PX or AL Id number -> name -> local id number.
The Qualifier Bytes of a TRANSLATE entry shall have the following format:
@ -312,7 +314,7 @@ Example: A very long qualifier naming "His_Excellency_..._the_Boss" as user #1.
Specification of the ER System Use Entry Values for AAIP:
This ER system entry shall only be present if the ER entry of RRIP is present.
To be compliant with SUSP-1.12, this ER entry must be present if AA entries
To be compliant with SUSP-1.12, this ER entry must be present if AL entries
are present, and ES entries have to mark RRIP and AAIP entries.
If for some reason compliance with SUSP-1.10 is intended, then this ER entry
and the ES entries must not be present, although SUSP-1.10 would allow ER.
@ -320,10 +322,10 @@ and the ES entries must not be present, although SUSP-1.10 would allow ER.
The Extension Version number for this version of AAIP shall be 1.
The Extension Identifier field shall be "AAIP_0100" with Identifier Length 9.
The Extension Identifier field shall be "AAIP_0200" with Identifier Length 9.
The mandatory content form of the Extension Descriptor is
"AA PROVIDES VIA AAIP 1.0 SUPPORT FOR ARBITRARY FILE ATTRIBUTES IN ISO 9660 IMAGES"
"AL PROVIDES VIA AAIP 2.0 SUPPORT FOR ARBITRARY FILE ATTRIBUTES IN ISO 9660 IMAGES"
The Description Length is 81.
The recommended content of the Extension Source is
@ -367,11 +369,11 @@ Model Relations:
[1:0..n] [1:0..n]
Arbitrary Attribute ( [1:0..1] ACL ) Entry
[1:2..2n] [1:0..1]
Component ( [1..m:1..n] AA Field ) Qualifier
Component ( [1..m:1..n] AL Field ) Qualifier
[1:1..n] << one of >>
Component Record / \
[1..m:1..n] Translation Entry , Numeric Id
AA Field | |
AL Field | |
[1:1..n] [1:1]
\ /
Qualifier Record
@ -379,12 +381,30 @@ Model Relations:
-------------------------------------------------------------------------------
Revoked drafts:
There was a draft AAIP 0.0 with ER signature "AAIP_2008A". It did not resemble
the existing entry SL and therefore shall not be used by writers of ISO images.
The following outdated versions may be interpreted at read time but they
shall not be written any more.
AAIP-1.0
Previous versions up to AAIP 1.0 used field signature "AA" rather than "AL".
This nearly collides with "Apple ISO 9660 Extensions". The Apple "AA" field of
version 1 has a length of 7, whereas the shortest first AAIP field "AA" had
length 9.
Beginning with AAIP 2.0, the field name has been changed to "AL".
If a reader interprets old AAIP "AA" fields, then it must take precautions to
distinguish them from Apple "AA" fields. But it is well compliant with AAIP 2.0
to just ignore any kind of "AA" fields.
AAIP 1.0 had ER signature "AAIP_0100".
AAIP-0.2
AAIP 0.2 with ER signature "AAIP_0002" allowed to announce and use a different
signature than "AA". This has been revoked because ES entries serve the purpose
signature than "AA". This was revoked because ES entries serve the purpose
to distinguish AAIP entries from eventual "AA" entries of any other extension.
Regrettably no reader (kernel) was found which neatly interprets ES. Many do
not even recognize the RRIP-1.12 ER signatures "IEEE_P1282", "IEEE_1282".
AAIP 0.2 defined two ACL types which did not make it into AAIP 1.0
2 ACL_USER of arbitrary user, with name as qualifier
@ -392,14 +412,34 @@ AAIP 0.2 defined two ACL types which did not make it into AAIP 1.0
Their job was transferred to ACL_USER_N and ACL_GROUP_N which have numeric
qualifiers.
AAIP-0.0
There was a draft AAIP 0.0 with ER signature "AAIP_2008A". It did not resemble
the existing entry SL and was never implemented.
-------------------------------------------------------------------------------
References:
ECMA-119 http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-119.pdf
ECMA-119 aka ISO 9660
http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-119.pdf
SUSP 1.12 (entries CE , PD , SP , ST , ER , ES)
ftp://ftp.ymi.com/pub/rockridge/susp112.ps
RRIP 1.12 (entries PX , PN , SL , NM , CL , PL , RE , TF , SF , obsolete: RR)
ftp://ftp.ymi.com/pub/rockridge/rrip112.ps
SUSP 1.12 ftp://ftp.ymi.com/pub/rockridge/susp112.ps
Apple ISO 9660 Extensions (entries AA and BA)
http://developer.apple.com/technotes/fl/fl_36.html
RRIP 1.12 ftp://ftp.ymi.com/pub/rockridge/rrip112.ps
(especially entry SL)
Amiga AS entry
http://www.estamos.de/makecd/Rock_Ridge_Amiga_Specific
zisofs entry ZF (prepared by zisofs-tools, written by mkisofs)
http://freshmeat.net/projects/zisofs-tools/
Program mkisofs emits entry XA
ftp://ftp.berlios.de/pub/cdrecord/alpha
-------------------------------------------------------------------------------

@ -1,7 +1,7 @@
/*
Arbitrary Attribute Interchange Protocol , AAIP versions 0.2 and 1.0.
Arbitrary Attribute Interchange Protocol , AAIP versions 0.2 , 1.0 , 2.0.
Implementation of encoding and decoding xattr and ACL.
See test/aaip_0_2.h
@ -21,6 +21,8 @@
#include <grp.h>
#include <sys/stat.h>
#include "libisofs.h"
/* <<<
*/
#define Aaip_encode_debuG 1
@ -80,7 +82,7 @@ static int aaip_encode_pair(char *name, size_t attr_length, char *attr,
This is malloc() memory which needs to be freed when
no longer needed
@param flag Bitfield for control purposes
bit0= set CONTINUE bit of last AA field to 1
bit0= set CONTINUE bit of last AAIP field to 1
@return >0 is the number of SUSP fields generated,
0 means error
*/
@ -126,7 +128,13 @@ size_t aaip_encode(size_t num_attrs, char **names,
/* write the field headers */
for(i= 0; i < number_of_fields; i++) {
(*result)[i * 255 + 0]= 'A';
#ifdef Libisofs_aaip_2_0
(*result)[i * 255 + 1]= 'L';
#else /* Libisofs_aaip_2_0 */
(*result)[i * 255 + 1]= 'A';
#endif /* ! Libisofs_aaip_2_0 */
if(i < number_of_fields - 1 || (mem_size % 255) == 0)
(*result)[i * 255 + 2]= 255;
else
@ -200,7 +208,7 @@ static int aaip_encode_comp(unsigned char *result, size_t *result_fill,
/* Write the component records for name and attr. Skip the positions of
AA field headers.
AAIP field headers.
@param flag bit0= only count but do not produce result
*/
static int aaip_encode_pair(char *name, size_t attr_length, char *attr,
@ -818,11 +826,11 @@ int aaip_add_acl_st_mode(char *acl_text, mode_t st_mode, int flag)
struct aaip_state {
/* AA field status */
int aa_head_missing; /* number of bytes needed to complete AA field header */
int aa_missing; /* number of bytes needed to complete current AA field */
int aa_ends; /* 0= still AA fields expected, 1= last AA being processed,
2= all AA fields processed, 3= all is delivered */
/* AAIP field status */
int aa_head_missing; /* number of bytes needed to complete field header */
int aa_missing; /* number of bytes needed to complete current field */
int aa_ends; /* 0= still fields expected, 1= last field being processed,
2= all fields processed, 3= all is delivered */
/* Buffer for component records */
int recs_invalid; /* number of components to skip */
@ -1178,11 +1186,19 @@ static int aaip_consume_aa_head(struct aaip_state *aaip,
aaip->aa_head_missing-= todo;
if(aaip->aa_head_missing == 0) {
aaip_read_from_recs(aaip, aaip->recs_fill - 5, aa_head, 5, 0);
#ifdef Libisofs_aaip_2_0
if(aa_head[0] != 'A' || (aa_head[1] != 'L' && aa_head[1] != 'A') ||
aa_head[3] != 1)
return(-1);
#else /* Libisofs_aaip_2_0 */
if(aa_head[0] != 'A' || aa_head[1] != 'A' || aa_head[3] != 1)
return(-1);
#endif /* ! Libisofs_aaip_2_0 */
aaip->aa_missing= aa_head[2];
aaip->aa_ends= !(aa_head[4] & 1);
aaip->recs_fill-= 5; /* AA heads do not get delivered */
aaip->recs_fill-= 5; /* AAIP field heads do not get delivered */
if(aaip->aa_missing >= 5)
aaip->aa_missing-= 5;
else
@ -1262,7 +1278,7 @@ static int aaip_consume_aa_data(struct aaip_state *aaip,
0 inquires the buffer status avoiding replies <= 0
@param ready_bytes Number of decoded bytes ready for delivery
@param flag Bitfield for control purposes
@return -1= non-AA field detected
@return -1= non-AAIP field detected
*ready_bytes gives number of consumed bytes in data
0= cannot accept data because buffer full
1= no component record complete, submit more data
@ -1506,7 +1522,7 @@ retry:;
@return <0 error
-3 buffer full (program error)
-2 insufficient result_size (only with flag bit0)
-1 non-AA field detected
-1 non-AAIP field detected
0 data not accepted, first fetch pending pairs with num_data == 0
1 name and value are not valid yet, submit more data
2 name and value are valid, submit more data
@ -1521,7 +1537,7 @@ int aaip_decode_pair(struct aaip_state *aaip,
int flag)
{
int ret;
size_t ready_bytes;
size_t ready_bytes= 0;
#ifdef Aaip_with_short_namespaceS
char prefix[Aaip_max_name_expansioN + 1];
@ -1552,7 +1568,7 @@ int aaip_decode_pair(struct aaip_state *aaip,
else if(aaip->num_recs)
ret= 2;
}
if(ret < 0) { /* non-AA field detected */
if(ret < 0) { /* non-AAIP field detected */
*consumed= ready_bytes;
{ret= -1; goto ex;}
} else if(ret == 0) { /* buffer overflow */;
@ -1673,8 +1689,9 @@ static int aaip_enlarge_buf(struct aaip_state *aaip, size_t memory_limit,
bit15= end decoding :
Free handle and its intermediate list memory.
@return <=0 error
-4 interpretation stalled, no valid result
-3 program error, unexpected reply from lower layers
-2 non-AA-field detected, arrays are complete,
-2 non-AAIP-field detected, arrays are complete,
call aaip_get_decoded_attrs()
-1 out of memory
1 not complete yet, submit more data
@ -1776,8 +1793,10 @@ int aaip_decode_attrs(struct aaip_state **handle,
if(ret != 1)
return(ret);
} else if(ret == -1) { /* non-AA field detected */
} else if(ret == -1) { /* non-AAIP field detected */
was_non_aa= 1;
if(pair_consumed <= 0)
return(-4); /* interpretation did not advance */
} else if(ret < 0) { /* other error */
return(-3);

@ -29,7 +29,7 @@
This is malloc() memory which needs to be freed when
no longer needed
@param flag Bitfield for control purposes
bit0= set CONTINUE bit of last AA field to 1
bit0= set CONTINUE bit of last AAIP field to 1
@return >0 is the number of SUSP fields generated,
0 means error
*/
@ -207,15 +207,16 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
attribute lists but may also be used as alternative to Pair Level.
*/
/* Operations on complete AA field strings which need no decoder context.
These function expect to get submitted a complete chain of AA fields.
/* Operations on complete AAIP field strings which need no decoder context.
These function expect to get submitted a complete chain of AAIP fields.
*/
/* Determine the size of the AA string by interpreting the SUSP structure.
/* Determine the size of the AAIP string by interpreting the SUSP structure.
@param data An arbitrary number of bytes beginning with the
complete chain of AA fields. Trailing trash is ignored.
complete chain of AAIP fields. Trailing trash is
ignored.
@param flag Unused yet. Submit 0.
@return The number of bytes of the AA field chain.
@return The number of bytes of the AAIP field chain.
*/
size_t aaip_count_bytes(unsigned char *data, int flag);
@ -231,7 +232,7 @@ size_t aaip_sizeof_aaip_state(void);
/* Initialize a AAIP decoder context.
This has to be done before the first AA field of a node is processed.
This has to be done before the first AAIP field of a node is processed.
The caller has to provide the storage of the struct aaip_state.
@param aaip The AAIP decoder context to be initialized
@param flag Bitfield for control purposes
@ -259,7 +260,7 @@ int aaip_init_aaip_state(struct aaip_state *aaip, int flag);
0 inquires the buffer status avoiding replies <= 0
@param ready_bytes Number of decoded bytes ready for delivery
@param flag Bitfield for control purposes
@return -1= non-AA field detected
@return -1= non-AAIP field detected
*ready_bytes gives number of consumed bytes in data
0= cannot accept data because buffer full
1= no component record complete, submit more data

@ -197,7 +197,7 @@ int default_create_node(IsoNodeBuilder *builder, IsoImage *image,
1 << 15); /* free ACL texts */
}
/* Obtain ownership of eventual AA string */
/* Obtain ownership of eventual AAIP string */
ret = iso_file_source_get_aa_string(src, &aa_string,
1 | (image->builder_ignore_acl << 1) |
(image->builder_ignore_ea << 2 ));

@ -306,7 +306,7 @@ struct image_fs_data
} data;
/**
* malloc() storage for the string of AA fields which represent
* malloc() storage for the string of AAIP fields which represent
* ACLs and XFS-style Extended Attributes. (Not to be confused with
* ECMA-119 Extended Attributes.)
*/
@ -1350,8 +1350,8 @@ int iso_file_source_new_ifs(IsoImageFilesystem *fs, IsoFileSource *parent,
}
continue;
/* Need to read AA in any case so it is available for S_IRWXG
mapping in case that fsdata->aaip_load != 1
/* Need to read AA resp. AL in any case so it is available for
S_IRWXG mapping in case that fsdata->aaip_load != 1
*/
} else if (SUSP_SIG(sue, 'A', 'A')) {
@ -1364,10 +1364,17 @@ int iso_file_source_new_ifs(IsoImageFilesystem *fs, IsoFileSource *parent,
continue;
}
/* >>> AAIP-2 :
SUSP_SIG(sue, 'A', 'L')
read_aaip_AL() like read_aaip_AA()
*/
} else if (SUSP_SIG(sue, 'A', 'L')) {
ret = read_aaip_AL(sue, &aa_string, &aa_size, &aa_len,
&prev_field, &aa_done, 0);
if (ret < 0) {
/* notify and continue */
ret = iso_msg_submit(fsdata->msgid, ISO_WRONG_RR_WARN, ret,
"Invalid AL entry");
continue;
}
/* This message is inflationary */
/*
@ -2024,13 +2031,15 @@ int read_root_susp_entries(_ImageFsData *data, uint32_t block)
} else if (sue->data.ER.len_id[0] == 9 &&
(strncmp((char*)sue->data.ER.ext_id, "AAIP_0002", 9) == 0 ||
strncmp((char*)sue->data.ER.ext_id, "AAIP_0100", 9) == 0)) {
strncmp((char*)sue->data.ER.ext_id, "AAIP_0100", 9) == 0 ||
strncmp((char*)sue->data.ER.ext_id, "AAIP_0200", 9) == 0)) {
/* Tolerate AAIP ER even if not supported */
iso_msg_debug(data->msgid,
"Suitable AAIP ER found.");
iso_msg_debug(data->msgid, "Suitable AAIP ER found.");
if (((char*)sue->data.ER.ext_id)[6] == '1')
if (strncmp((char*)sue->data.ER.ext_id, "AAIP_0200", 9) == 0)
data->aaip_version = 200;
else if (((char*)sue->data.ER.ext_id)[6] == '1')
data->aaip_version = 100;
else
data->aaip_version = 2;
@ -2424,7 +2433,7 @@ int src_aa_to_node(IsoFileSource *src, IsoNode *node, int flag)
data = (ImageFileSourceData*)src->data;
fsdata = data->fs->data;
/* Obtain ownership of eventual AA string */
/* Obtain ownership of eventual AAIP string */
ret = iso_file_source_get_aa_string(src, &aa_string, 1);
if (ret != 1 || aa_string == NULL)
return 1;

@ -685,7 +685,7 @@ struct IsoFileSource_Iface
/**
* Valid only if .version is > 0. See above.
* Get the AA string with encoded ACL and xattr.
* Get the AAIP string with encoded ACL and xattr.
* (Not to be confused with ECMA-119 Extended Attributes).
*
* bit1 and bit2 of flag should be implemented so that freshly fetched
@ -694,14 +694,14 @@ struct IsoFileSource_Iface
* delivered.
*
* @param flag Bitfield for control purposes
* bit0= Transfer ownership of AA string data.
* bit0= Transfer ownership of AAIP string data.
* src will free the eventual cached data and might
* not be able to produce it again.
* bit1= No need to get ACL (no guarantee of exclusion)
* bit2= No need to get xattr (no guarantee of exclusion)
* @param aa_string Returns a pointer to the AA string data. If no AA
* @param aa_string Returns a pointer to the AAIP string data. If no AAIP
* string is available, *aa_string becomes NULL.
* (See doc/susp_aaip_0_2.txt for the meaning of AA and
* (See doc/susp_aaip_*_*.txt for the meaning of AAIP and
* libisofs/aaip_0_2.h for encoding and decoding.)
* The caller is responsible for finally calling free()
* on non-NULL results.
@ -1286,7 +1286,7 @@ int iso_write_opts_set_rrip_version_1_10(IsoWriteOpts *opts, int oldvers);
/**
* Write AAIP as extension according to SUSP 1.10 rather than SUSP 1.12.
* I.e. without announcing it by an ER field and thus without the need
* to preceed the RRIP fields and the AA field by ES fields.
* to preceed the RRIP fields and the AAIP field by ES fields.
* This saves 5 to 10 bytes per file and might avoid problems with readers
* which dislike ER fields other than the ones for RRIP.
* On the other hand, SUSP 1.12 frowns on such unannounced extensions
@ -3824,17 +3824,17 @@ int iso_file_source_readlink(IsoFileSource *src, char *buf, size_t bufsiz);
/**
* Get the AA string with encoded ACL and xattr.
* Get the AAIP string with encoded ACL and xattr.
* (Not to be confused with ECMA-119 Extended Attributes).
* @param src The file source object to be inquired.
* @param aa_string Returns a pointer to the AA string data. If no AA
* @param aa_string Returns a pointer to the AAIP string data. If no AAIP
* string is available, *aa_string becomes NULL.
* (See doc/susp_aaip_0_2.txt for the meaning of AA and
* (See doc/susp_aaip_0_2.txt for the meaning of AAIP and
* libisofs/aaip_0_2.h for encoding and decoding.)
* The caller is responsible for finally calling free()
* on non-NULL results.
* @param flag Bitfield for control purposes
* bit0= Transfer ownership of AA string data.
* bit0= Transfer ownership of AAIP string data.
* src will free the eventual cached data and might
* not be able to produce it again.
* bit1= No need to get ACL (but no guarantee of exclusion)
@ -4330,15 +4330,16 @@ IsoStream *iso_stream_get_input_stream(IsoStream *stream, int flag);
/* --------------------------------- AAIP --------------------------------- */
/**
* Function to identify and manage AA strings as xinfo of IsoNode.
* Function to identify and manage AAIP strings as xinfo of IsoNode.
*
* An AA string contains the Attribute List with the xattr and ACL of a node
* An AAIP string contains the Attribute List with the xattr and ACL of a node
* in the image tree. It is formatted according to libisofs specification
* AAIP-1.0 and ready to be written into the System Use Area resp. Continuation
* Area of a directory entry in an ISO image.
*
* Applications are not supposed to manipulate AA strings directly. They should
* rather make use of the appropriate iso_node_get_* and iso_node_set_* calls.
* Applications are not supposed to manipulate AAIP strings directly.
* They should rather make use of the appropriate iso_node_get_* and
* iso_node_set_* calls.
*
* AAIP represents ACLs as xattr with empty name and AAIP-specific binary
* content. Local filesystems may represent ACLs as xattr with names like
@ -4977,6 +4978,9 @@ struct burn_source {
#define Libisofs_avoid_using_allocA yes
/* ---------------------------- Improvements --------------------------- */
/* Cleanup : make call setlocale() at init time resp. never
*/
#define Libisofs_setlocale_in_iniT yes
@ -4988,6 +4992,11 @@ struct burn_source {
#define Libisofs_file_src_cmp_sizE yes
/* Disambiguation : change to AAIP-2.0 with field signature "AL"
*/
#define Libisofs_aaip_2_0 yes
/* ---------------------------- Experiments ---------------------------- */

@ -1372,7 +1372,7 @@ int attrs_cleanout_name(char *del_name, size_t *num_attrs, char **names,
/**
* Backend of iso_node_get_attrs() with parameter node replaced by the
* AA string from where to get the attribute list.
* AAIP string from where to get the attribute list.
* All other parameter specs apply.
*/
int iso_aa_get_attrs(unsigned char *aa_string, size_t *num_attrs,

@ -350,7 +350,7 @@ int iso_aa_get_acl_text(unsigned char *aa_string, mode_t st_mode,
/**
* Backend of iso_node_get_attrs() with parameter node replaced by the
* AA string from where to get the attribute list.
* AAIP string from where to get the attribute list.
* All other parameter specs apply.
*/
int iso_aa_get_attrs(unsigned char *aa_string, size_t *num_attrs,

@ -15,6 +15,7 @@
#include "messages.h"
#include "image.h"
#include "aaip_0_2.h"
#include "libisofs.h"
#include <string.h>
@ -505,7 +506,7 @@ int rrip_add_SL(Ecma119Image *t, struct susp_info *susp, uint8_t **comp,
parameters susp and data may be NULL in this case
*/
static
int aaip_add_AA(Ecma119Image *t, struct susp_info *susp,
int aaip_add_AL(Ecma119Image *t, struct susp_info *susp,
uint8_t **data, size_t num_data,
size_t *sua_free, size_t *ce_len, int flag)
{
@ -647,45 +648,46 @@ int rrip_add_ER(Ecma119Image *t, struct susp_info *susp)
static
int aaip_add_ER(Ecma119Image *t, struct susp_info *susp, int flag)
{
unsigned char *AA;
unsigned char *ER;
AA = malloc(160);
if (AA == NULL) {
ER = malloc(160);
if (ER == NULL) {
return ISO_OUT_OF_MEM;
}
AA[0] = 'E';
AA[1] = 'R';
AA[2] = 160;
AA[3] = 1;
AA[4] = 9;
AA[5] = 81;
AA[6] = 62;
AA[7] = 1;
#define Libisofs_aaip_1_0 yes
#ifdef Libisofs_aaip_1_0
memcpy(AA + 8, "AAIP_0100", 9);
memcpy(AA + 17,
"AA PROVIDES VIA AAIP 1.0 SUPPORT FOR ARBITRARY FILE ATTRIBUTES"
ER[0] = 'E';
ER[1] = 'R';
ER[2] = 160;
ER[3] = 1;
ER[4] = 9;
ER[5] = 81;
ER[6] = 62;
ER[7] = 1;
#ifdef Libisofs_aaip_2_0
memcpy(ER + 8, "AAIP_0200", 9);
memcpy(ER + 17,
"AL PROVIDES VIA AAIP 2.0 SUPPORT FOR ARBITRARY FILE ATTRIBUTES"
" IN ISO 9660 IMAGES", 81);
memcpy(ER + 98,
"PLEASE CONTACT THE LIBBURNIA PROJECT VIA LIBBURNIA-PROJECT.ORG",
62);
#else /* Libisofs_aaip_1_0 */
#else /* Libisofs_aaip_2_0 */
memcpy(AA + 8, "AAIP_0002", 9);
memcpy(AA + 17,
"AA PROVIDES VIA AAIP 0.2 SUPPORT FOR ARBITRARY FILE ATTRIBUTES"
memcpy(ER + 8, "AAIP_0100", 9);
memcpy(ER + 17,
"AA PROVIDES VIA AAIP 1.0 SUPPORT FOR ARBITRARY FILE ATTRIBUTES"
" IN ISO 9660 IMAGES", 81);
#endif /* ! Libisofs_aaip_1_0 */
memcpy(AA + 98,
memcpy(ER + 98,
"PLEASE CONTACT THE LIBBURNIA PROJECT VIA LIBBURNIA-PROJECT.ORG",
62);
#endif /* ! Libisofs_aaip_2_0 */
/** This always goes to continuation area */
return susp_append_ce(t, susp, AA);
return susp_append_ce(t, susp, ER);
}
@ -775,8 +777,8 @@ int aaip_xinfo_func(void *data, int flag)
/**
* Compute SUA lentgth and eventual Continuation Area length of field NM and
* eventually fields SL and AA. Because CA usage makes necessary the use of
* Compute SUA length and eventual Continuation Area length of field NM and
* eventually fields SL and AL. Because CA usage makes necessary the use of
* a CE entry of 28 bytes in SUA, this computation fails if not the 28 bytes
* are taken into account at start. In this case the caller should retry with
* bit0 set.
@ -789,7 +791,7 @@ int aaip_xinfo_func(void *data, int flag)
* -1= not enough SUA space for 28 bytes of CE entry
*/
static
int susp_calc_nm_sl_aa(Ecma119Image *t, Ecma119Node *n, size_t space,
int susp_calc_nm_sl_al(Ecma119Image *t, Ecma119Node *n, size_t space,
size_t *su_size, size_t *ce, int flag)
{
char *name;
@ -942,7 +944,7 @@ int susp_calc_nm_sl_aa(Ecma119Image *t, Ecma119Node *n, size_t space,
/* let the expert decide where to add num_aapt */
if (num_aapt > 0) {
sua_free = space - *su_size;
aaip_add_AA(t, NULL, NULL, num_aapt, &sua_free, ce, 1);
aaip_add_AL(t, NULL, NULL, num_aapt, &sua_free, ce, 1);
*su_size = space - sua_free;
if (*ce > 0 && !(flag & 1))
goto unannounced_ca;
@ -991,7 +993,7 @@ size_t rrip_calc_len(Ecma119Image *t, Ecma119Node *n, int type, size_t space,
su_size += 5;
#ifdef Libisofs_with_rrip_rR
/* obsolete RR field (once in AAIP-1.09) */
/* obsolete RR field (once in RRIP-1.09) */
su_size += 5;
#endif
@ -1026,9 +1028,9 @@ size_t rrip_calc_len(Ecma119Image *t, Ecma119Node *n, int type, size_t space,
if (type == 0) {
/* Try without CE */
ret = susp_calc_nm_sl_aa(t, n, space, &su_size, ce, 0);
ret = susp_calc_nm_sl_al(t, n, space, &su_size, ce, 0);
if (ret == 0) /* Retry with CE */
susp_calc_nm_sl_aa(t, n, space, &su_size, ce, 1);
susp_calc_nm_sl_al(t, n, space, &su_size, ce, 1);
} else {
@ -1110,7 +1112,7 @@ int add_aa_string(Ecma119Image *t, Ecma119Node *n, struct susp_info *info,
if (aapt == NULL)
return ISO_OUT_OF_MEM;
memcpy(aapt, xipt, num_aapt);
ret = aaip_add_AA(t, info, &aapt, num_aapt, sua_free, ce_len,
ret = aaip_add_AL(t, info, &aapt, num_aapt, sua_free, ce_len,
flag & 1);
if (ret < 0)
return ret;
@ -1264,12 +1266,12 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type,
sua_free = space - info->suf_len;
/* Try whether NM, SL, AA will fit into SUA */
/* Try whether NM, SL, AL will fit into SUA */
su_size_pd = info->suf_len;
ce_len_pd = ce_len;
ret = susp_calc_nm_sl_aa(t, n, space, &su_size_pd, &ce_len_pd, 0);
ret = susp_calc_nm_sl_al(t, n, space, &su_size_pd, &ce_len_pd, 0);
if (ret == 0) { /* Have to use CA. 28 bytes of CE are necessary */
susp_calc_nm_sl_aa(t, n, space, &su_size_pd, &ce_len_pd, 1);
susp_calc_nm_sl_al(t, n, space, &su_size_pd, &ce_len_pd, 1);
sua_free -= 28;
ce_is_predicted = 1;
}
@ -1493,7 +1495,7 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type,
}
}
/* Obtain AA field string from node
/* Obtain AAIP field string from node
and write it to directory entry or CE area.
*/
ret = ISO_SUCCESS;

@ -118,14 +118,19 @@ struct rr_SL {
};
/** Arbitrary Attribute (AAIP, see doc/susp_aaip_1_0.txt) */
struct rr_AA {
/** Outdated Arbitrary Attribute (AAIP, see doc/susp_aaip_1_0.txt)
* It collided with pre-SUSP Apple AA field.
*/
struct aaip_AA {
uint8_t flags[1];
uint8_t comps[1];
};
/* >>> AAIP-2 : struct rr_AL like struct rr_AA */
/** Arbitrary Attribute (AAIP, see doc/susp_aaip_2_0.txt) */
struct aaip_AL {
uint8_t flags[1];
uint8_t comps[1];
};
/**
@ -146,10 +151,8 @@ struct susp_sys_user_entry
struct rr_NM NM;
struct rr_CL CL;
struct rr_SL SL;
struct rr_AA AA;
/* >>> AAIP-2 : struct rr_AL */
struct aaip_AA AA;
struct aaip_AL AL;
} data; /* 5 to 4+len_sue */
};
@ -283,8 +286,8 @@ int read_rr_PN(struct susp_sys_user_entry *pn, struct stat *st);
/**
* Collects the AA field string from single AA fields.
* (see doc/susp_aaip_0_2.txt)
* Collects the AAIP field string from single AAIP fields.
* (see doc/susp_aaip_1_0.txt)
* @param aa_string Storage location of the emerging string.
* Begin with *aa_string == NULL, or own malloc() storage.
* @param aa_size Current allocated size of aa_string.
@ -293,14 +296,24 @@ int read_rr_PN(struct susp_sys_user_entry *pn, struct stat *st);
* Begin with *aa_len == 0
* @param prev_field Returns the index of start of the previous field
* in the string.
* @param is_done The current completion state of the AA field string.
* @param is_done The current completion state of the AAIP field string.
* Fields will be ignored as soon as it is 1.
* Begin with *is_done == 0
* @param flag Unused yet. Submit 0.
* @return
* 1 on success, < 0 on error
*/
int read_aaip_AA(struct susp_sys_user_entry *sue,
unsigned char **aa_string, size_t *aa_size, size_t *aa_len,
size_t *prev_field, int *is_done, int flag);
/**
* Collects the AAIP field string from single AL fields.
* (see doc/susp_aaip_2_0.txt)
*/
int read_aaip_AL(struct susp_sys_user_entry *sue,
unsigned char **aa_string, size_t *aa_size, size_t *aa_len,
size_t *prev_field, int *is_done, int flag);
#endif /* LIBISO_ROCKRIDGE_H */

@ -435,6 +435,8 @@ int read_rr_PN(struct susp_sys_user_entry *pn, struct stat *st)
}
/* AA is the field signature of AAIP versions < 2.0
*/
int read_aaip_AA(struct susp_sys_user_entry *sue,
unsigned char **aa_string, size_t *aa_size, size_t *aa_len,
size_t *prev_field, int *is_done, int flag)
@ -443,8 +445,7 @@ int read_aaip_AA(struct susp_sys_user_entry *sue,
if (*is_done) {
/* AAIP-2
To coexist with Apple ISO :
/* To coexist with Apple ISO :
Gracefully react on eventually trailing Apple AA
*/
if (sue->version[0] != 1 || sue->len_sue[0] == 7)
@ -457,8 +458,7 @@ int read_aaip_AA(struct susp_sys_user_entry *sue,
/* Eventually create or grow storage */
if (*aa_size == 0 || *aa_string == NULL) {
/* AAIP-2
Gracefully react on eventually leading Apple AA
/* Gracefully react on eventually leading Apple AA
*/
if (sue->version[0] != 1 || sue->len_sue[0] < 9) {
return ISO_SUCCESS;
@ -470,8 +470,7 @@ int read_aaip_AA(struct susp_sys_user_entry *sue,
} else if (*aa_len + sue->len_sue[0] > *aa_size) {
if (sue->version[0] != 1) {
/* AAIP-2
Apple ISO within the AAIP field group is not AAIP compliant
/* Apple ISO within the AAIP field group is not AAIP compliant
*/
return ISO_WRONG_RR;
}
@ -492,25 +491,92 @@ int read_aaip_AA(struct susp_sys_user_entry *sue,
/* Compose new SUSP header with signature aa[], cont == 0 */
aapt = *aa_string + *aa_len;
/* >>> AAIP-2
Change to new signature (AL ?)
*/
aapt[0] = 'A';
#ifdef Libisofs_aaip_2_0
aapt[1] = 'L';
#else /* Libisofs_aaip_2_0 */
aapt[1] = 'A';
#endif /* ! Libisofs_aaip_2_0 */
aapt[2] = sue->len_sue[0];
aapt[3] = 1;
aapt[4] = 0;
/* Append sue payload */
#ifdef Libisofs_aaip_2_0
memcpy(aapt + 5, sue->data.AL.comps, sue->len_sue[0] - 5);
*is_done = !(sue->data.AL.flags[0] & 1);
#else /* Libisofs_aaip_2_0 */
memcpy(aapt + 5, sue->data.AA.comps, sue->len_sue[0] - 5);
*is_done = !(sue->data.AA.flags[0] & 1);
#endif /* ! Libisofs_aaip_2_0 */
*aa_len += sue->len_sue[0];
return ISO_SUCCESS;
}
/* AL is the obsolete field signature of AAIP versions >= 2.0
*/
int read_aaip_AL(struct susp_sys_user_entry *sue,
unsigned char **aa_string, size_t *aa_size, size_t *aa_len,
size_t *prev_field, int *is_done, int flag)
{
unsigned char *aapt;
if (*is_done)
return ISO_WRONG_RR;
if (sue->version[0] != 1)
return ISO_WRONG_RR;
/* Eventually create or grow storage */
if (*aa_size == 0 || *aa_string == NULL) {
*aa_size = *aa_len + sue->len_sue[0];
*aa_string = calloc(*aa_size, 1);
*aa_len = 0;
} else if (*aa_len + sue->len_sue[0] > *aa_size) {
*aa_size += *aa_len + sue->len_sue[0];
*aa_string = realloc(*aa_string, *aa_size);
}
if (*aa_string == NULL)
return ISO_OUT_OF_MEM;
if (*aa_len > 0) {
/* Mark prev_field as being continued */
(*aa_string)[*prev_field + 4] = 1;
}
*prev_field = *aa_len;
/* Compose new SUSP header with signature aa[], cont == 0 */
aapt = *aa_string + *aa_len;
aapt[0] = 'A';
#ifdef Libisofs_aaip_2_0
aapt[1] = 'L';
#else /* Libisofs_aaip_2_0 */
aapt[1] = 'A';
#endif /* ! Libisofs_aaip_2_0 */
aapt[2] = sue->len_sue[0];
aapt[3] = 1;
aapt[4] = 0;
/* Append sue payload */
#ifdef Libisofs_aaip_2_0
memcpy(aapt + 5, sue->data.AL.comps, sue->len_sue[0] - 5);
*is_done = !(sue->data.AL.flags[0] & 1);
#else /* Libisofs_aaip_2_0 */
memcpy(aapt + 5, sue->data.AA.comps, sue->len_sue[0] - 5);
*is_done = !(sue->data.AA.flags[0] & 1);
#endif /* ! Libisofs_aaip_2_0 */
*aa_len += sue->len_sue[0];
return ISO_SUCCESS;
}
/* >>> AAIP-2
read_aaip_AL() like read_aaip_AA()
*/

Loading…
Cancel
Save