/* iso9660.c - iso9660 implementation with extensions:
SUSP, Rock Ridge. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc.
*
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/datetime.h>
GRUB_MOD_LICENSE ("GPLv3+");
#define GRUB_ISO9660_VOLDESC_BOOT 0
/* The head of a volume descriptor. */
struct grub_iso9660_voldesc
{
} __attribute__ ((packed));
struct grub_iso9660_date2
{
} __attribute__ ((packed));
/* A directory entry. */
struct grub_iso9660_dir
{
} __attribute__ ((packed));
struct grub_iso9660_date
{
} __attribute__ ((packed));
/* The primary volume descriptor. Only little endian is used. */
struct grub_iso9660_primary_voldesc
{
} __attribute__ ((packed));
/* A single entry in the path table. */
struct grub_iso9660_path
{
} __attribute__ ((packed));
/* An entry in the System Usage area of the directory entry. */
struct grub_iso9660_susp_entry
{
} __attribute__ ((packed));
/* The CE entry. This is used to describe the next block where data
can be found. */
struct grub_iso9660_susp_ce
{
} __attribute__ ((packed));
struct grub_iso9660_data
{
int rockridge;
int susp_skip;
int joliet;
};
struct grub_fshelp_node
{
int have_symlink;
char symlink[0];
};
enum
{
FLAG_TYPE_PLAIN = 0,
};
static grub_err_t
{
return GRUB_ERR_NONE;
}
static int
{
return 0;
return 1;
}
static grub_err_t
{
grub_size_t i = 0;
while (len > 0)
{
while (i < node->have_dirents
{
i++;
}
if (i == node->have_dirents)
if (err)
return err;
}
return GRUB_ERR_NONE;
}
/* Iterate over the susp entries, starting with block SUA_BLOCK on the
offset SUA_POS with a size of SUA_SIZE bytes. Hook is called for
every entry. */
static grub_err_t
grub_err_t (*hook)
(struct grub_iso9660_susp_entry *entry))
{
char *sua;
int is_ce = 0;
auto grub_err_t load_sua (void);
/* Load a part of the System Usage Area. */
{
if (!sua)
return grub_errno;
if (is_ce)
else
if (err)
return err;
return 0;
}
if (sua_size <= 0)
return GRUB_ERR_NONE;
if (load_sua ())
return grub_errno;
entry = (struct grub_iso9660_susp_entry *)
{
/* The last entry. */
break;
/* Additional entries are stored elsewhere. */
{
is_ce = 1;
if (load_sua ())
return grub_errno;
}
{
return 0;
}
}
return 0;
}
static char *
{
char *p;
int i;
grub_uint16_t t[len];
if (! p)
return p;
for (i=0; i<len; i++)
return p;
}
static grub_err_t
{
int sua_pos;
int sua_size;
char *sua;
{
/* The "ER" entry is used to detect extensions. The
`IEEE_P1285' extension means Rock ridge. */
{
return 1;
}
return 0;
}
/* Read the system use area and test it to see if SUSP is
supported. */
<< GRUB_ISO9660_LOG2_BLKSZ), 0,
if (!sua_size)
return GRUB_ERR_NONE;
if (! sua)
return grub_errno;
{
}
/* Test if the SUSP protocol is used on this filesystem. */
{
rootnode.have_symlink = 0;
/* The 2nd data byte stored how many bytes are skipped every time
to get to the SUA (System Usage Area). */
/* Iterate over the entries in the SUA area to detect
extensions. */
{
return grub_errno;
}
}
return GRUB_ERR_NONE;
}
static struct grub_iso9660_data *
{
int block;
if (! data)
return 0;
block = 16;
do
{
int copy_voldesc = 0;
/* Read the superblock. */
sizeof (struct grub_iso9660_primary_voldesc),
(char *) &voldesc))
{
goto fail;
}
{
goto fail;
}
copy_voldesc = 1;
&&
{
copy_voldesc = 1;
}
if (copy_voldesc)
{
sizeof (struct grub_iso9660_primary_voldesc));
if (set_rockridge (data))
goto fail;
}
block++;
return data;
fail:
return 0;
}
static char *
{
return node->have_symlink
}
static grub_off_t
{
grub_size_t i;
for (i = 0; i < node->have_dirents; i++)
return ret;
}
static int
int NESTED_FUNC_ATTR
enum grub_fshelp_filetype filetype,
{
char *filename = 0;
int filename_alloc = 0;
char *symlink = 0;
/* Extend the symlink. */
int len2);
int len2)
{
if (! symlink)
return;
}
{
/* The filename in the rock ridge entry. */
{
/* The flags are stored at the data position 0, here the
filename type is stored. */
filename = ".";
filename = "..";
{
char *old;
if (filename_alloc)
{
}
else
{
filename_alloc = 1;
filename[0] = 0;
}
if (!filename)
{
return grub_errno;
}
filename_alloc = 1;
}
}
/* The mode information (st_mode). */
{
/* At position 0 of the PX record the st_mode information is
stored (little-endian). */
switch (mode)
{
case GRUB_ISO9660_FSTYPE_DIR:
break;
case GRUB_ISO9660_FSTYPE_REG:
break;
break;
default:
}
}
{
/* The symlink is not stored as a POSIX symlink, translate it. */
{
/* The current position is the `Component Flag'. */
{
case 0:
{
/* The data on pos + 2 is the actual data, pos + 1
is the length. Both are part of the `Component
Record'. */
break;
}
case 2:
break;
case 4:
break;
case 8:
break;
}
/* In pos + 1 the length of the `Component Record' is
stored. */
}
/* Check if `grub_realloc' failed. */
if (grub_errno)
return grub_errno;
}
return 0;
}
{
symlink = 0;
return 0;
/* The end of the block, skip to the next one. */
{
continue;
}
{
filename = 0;
filename_alloc = 0;
return 0;
/* Read the name. */
return 0;
if (!node)
return 0;
/* Setup a new node. */
node->have_symlink = 0;
/* If the filetype was not stored using rockridge, use
whatever is stored in the iso9660 filesystem. */
if (type == GRUB_FSHELP_UNKNOWN)
{
else
}
/* The filename was not stored in a rock ridge entry. Read it
from the iso9660 filesystem. */
if (!filename)
{
if (filename)
*filename = '\0';
/* . and .. */
{
continue;
}
else
}
{
if (semicolon)
*semicolon = '\0';
if (filename_alloc)
filename_alloc = 1;
}
{
{
if (filename_alloc)
return 0;
}
{
sizeof (struct grub_fshelp_node)
+ ((node->alloc_dirents
if (!new_node)
{
if (filename_alloc)
return 0;
}
}
}
if (symlink)
{
{
sizeof (struct grub_fshelp_node)
+ ((node->alloc_dirents
if (!new_node)
{
if (filename_alloc)
return 0;
}
}
}
{
if (filename_alloc)
return 1;
}
if (filename_alloc)
}
}
return 0;
}
static grub_err_t
const struct grub_dirhook_info *info))
{
enum grub_fshelp_filetype filetype,
enum grub_fshelp_filetype filetype,
{
}
if (! data)
goto fail;
rootnode.alloc_dirents = 0;
rootnode.have_symlink = 0;
/* Use the fshelp function to traverse the path. */
goto fail;
/* List the files in the directory. */
fail:
return grub_errno;
}
/* Open a file named NAME and initialize FILE. */
static grub_err_t
{
if (!data)
goto fail;
rootnode.alloc_dirents = 0;
rootnode.have_symlink = 0;
/* Use the fshelp function to traverse the path. */
goto fail;
return 0;
fail:
return grub_errno;
}
static grub_ssize_t
{
/* XXX: The file is stored in as a single extent. */
if (grub_errno)
return -1;
return len;
}
static grub_err_t
{
return GRUB_ERR_NONE;
}
static grub_err_t
{
if (data)
{
else
if (*label)
{
char *ptr;
ptr--;
*ptr-- = 0;
}
}
else
*label = 0;
return grub_errno;
}
static grub_err_t
{
if (data)
{
{
}
else
{
}
}
else
return grub_errno;
}
/* Get writing time of filesystem. */
static grub_err_t
{
if (!data)
{
return grub_errno;
}
return err;
}
{
.name = "iso9660",
.dir = grub_iso9660_dir,
.next = 0
};
{
}
{
}