[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Lost] iso9660



So ich hab jetzt mal alles POSIX rausgenommen, was ich gefunden habe. Da
man aber für Rockridge ein paar Sachen aus sys/stat.h braucht, habe ich
diese einfach nach rockridge.h übernommen (und ein 'r' als Präfix).

Kevin Wolf schrieb:
> Im zitieren Code die Änderungen, die es braucht, um auf LOST überhaupt mal 
> kompiliert zu werden. Außerdem sind in LOST noch kleinere POSIX-Ergänzungen 
> nötig, damit ich einen Lauftest machen kann. Das ist natürlich generell kein 
> gutes Zeichen, CDI-Treiber sollten möglichst kein POSIX voraussetzen. An den 
> entsprechenden Stellen würde ich daher zumindest mal ein FIXME hinschreiben.

diff -urNp tmp/dir.c iso9660/dir.c
--- tmp/dir.c	1970-01-01 01:00:00.000000000 +0100
+++ iso9660/dir.c	2008-09-21 15:10:49.000000000 +0200
@@ -0,0 +1,187 @@
+/*
+ * iso9660 - An iso9660 CDI driver with Rockridge support
+ *
+ * Copyright (C) 2008 Janosch Gräf
+ *
+ * This program is free software; you can redistribute it and/or modify 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.
+ *
+ * This program 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
+ * this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#include "cdi/fs.h"
+#include "cdi/lists.h"
+#include "cdi/cache.h"
+#include "cdi/misc.h"
+
+#include "directory_record.h"
+#include "volume_descriptor.h"
+#include "iso9660def.h"
+
+#ifdef ISO9660_USE_ROCKRIDGE
+  #include "rockridge.h"
+#endif
+
+#include "iso9660_cdi.h"
+
+#ifdef ISO9660_LOWER_FILENAMES
+  #include <ctype.h>
+#endif
+
+/**
+ * Convert ISO9660 identifier to file name
+ *  @param ident Identifier
+ *  @param len Length of identifier
+ *  @return Name (should be passed to free())
+ */
+static char *parse_name(char *ident,size_t len) {
+  if (ident[len-2]==';') len -= 2;
+  if (ident[len-1]=='.') len--;
+  char *name = memcpy(malloc(len+1),ident,len);
+#ifdef ISO9660_LOWER_FILENAMES
+  size_t i;
+  for (i=0;i<len;i++) name[i] = tolower(name[i]);
+#endif
+  name[len] = 0;
+  return name;
+}
+
+/**
+ * Converts POSIX file mode to CDI class
+ *  @param mode POSIX filemode
+ *  @param special Reference for CDI special type
+ *  @return CDI class
+ */
+#ifdef ISO9660_USE_ROCKRIDGE
+static cdi_fs_res_class_t parse_class(rmode_t mode,cdi_fs_res_type_t *special) {
+  cdi_fs_res_class_t class = CDI_FS_CLASS_FILE;
+  if (RS_ISBLK(mode)) {
+    class = CDI_FS_CLASS_SPECIAL;
+    if (special!=NULL) *special = CDI_FS_BLOCK;
+  }
+  else if (RS_ISCHR(mode)) {
+    class = CDI_FS_CLASS_SPECIAL;
+    if (special!=NULL) *special = CDI_FS_BLOCK;
+  }
+  else if (RS_ISFIFO(mode)) {
+    class = CDI_FS_CLASS_SPECIAL;
+    if (special!=NULL) *special = CDI_FS_FIFO;
+  }
+  else if (RS_ISSOCK(mode)) {
+    class = CDI_FS_CLASS_SPECIAL;
+    if (special!=NULL) *special = CDI_FS_SOCKET;
+  }
+  else if (RS_ISREG(mode)) class = CDI_FS_CLASS_FILE;
+  else if (RS_ISDIR(mode)) class = CDI_FS_CLASS_DIR;
+  else if (RS_ISLNK(mode)) class = CDI_FS_CLASS_LINK;
+  return class;
+}
+#endif
+
+/**
+ * Converts ISO9660 time to CDI time
+ *  @param date ISO9660-Zeit
+ *  @return CDI time
+ */
+static inline uint64_t parse_date(struct iso9660_dirrec_date *date) {
+  return cdi_time_by_date(date->year,date->month-1,date->day)+cdi_time_offset(date->hour,date->minute,date->second);
+}
+
+/**
+ * Loads a ISO9660 directory entry
+ *  @param dirrec Directory entry
+ *  @param parent Parent resource
+ *  @param voldesc Volume descriptor
+ *  @return Resource
+ */
+struct iso9660_fs_res *iso9660_dirrec_load(struct iso9660_dirrec *dirrec,struct iso9660_fs_res *parent,struct iso9660_voldesc_prim *voldesc) {
+  char *name = NULL;
+  uint64_t ctime = 0;
+  uint64_t atime = 0;
+  uint64_t mtime = 0;
+  cdi_fs_res_class_t class = 0;
+  cdi_fs_res_type_t type = 0;
+
+#ifdef ISO9660_USE_ROCKRIDGE
+  rmode_t mode;
+  if (iso9660_rockridge_scan(dirrec,&name,&mode,NULL,NULL,NULL,&atime,&ctime,&mtime)==0) {
+    class = parse_class(mode,&type);
+  }
+  else {
+    name = NULL;
+    class = 0;
+#endif
+    ctime = parse_date(&(dirrec->date_creation));
+    atime = ctime;
+    mtime = ctime;
+#ifdef ISO9660_USE_ROCKRIDGE
+  }
+#endif
+  if (name==NULL) name = parse_name((char*)dirrec->identifier,dirrec->identifier_length);
+  if (class==0) class = (dirrec->flags&ISO9660_DIRREC_DIR)?CDI_FS_CLASS_DIR:CDI_FS_CLASS_FILE;
+
+  struct iso9660_fs_res *new = iso9660_fs_res_create(name,parent,class,type);
+  if (voldesc!=NULL) new->voldesc = voldesc;
+  new->ctime = ctime;
+  new->atime = atime;
+  new->mtime = mtime;
+  new->data_sector = dirrec->data_sector;
+  new->data_size = dirrec->data_size;
+
+  free(name);
+  return new;
+}
+
+/**
+ * Loads a directory
+ *  @param res Resource to load as directory
+ *  @return Directory list
+ */
+cdi_list_t iso9660_dir_load(struct iso9660_fs_res *res) {
+  debug("iso9660_dir_load(0x%x(%s))\n",res,res->res.name);
+  struct iso9660_dirrec *dirrec;
+  size_t i = 0;
+  cdi_list_t dirlist = cdi_list_create();
+  size_t curpos = 0;
+
+  while (1) {
+    uint8_t size;
+
+    iso9660_read(res,curpos,1,&size);
+    //cdi_cache_entry_read(res->cache_entry,curpos,1,&size);
+    if (size==0) break;
+
+    dirrec = malloc(size);
+    iso9660_read(res,curpos,size,dirrec);
+    //cdi_cache_entry_read(res->cache_entry,curpos,size,dirrec);
+
+    if (i>1) cdi_list_push(dirlist,iso9660_dirrec_load(dirrec,res,NULL));
+
+    curpos += size;
+    i++;
+  }
+
+  return dirlist;
+}
+
+/**
+ * CDI FS Call to read a directory
+ *  @param stream CDI stream
+ *  @return Directory list
+ */
+cdi_list_t iso9660_fs_dir_list(struct cdi_fs_stream *stream) {
+  struct iso9660_fs_res *res = (struct iso9660_fs_res*)stream->res;
+
+  return res->res.children;
+}
diff -urNp tmp/directory_record.h iso9660/directory_record.h
--- tmp/directory_record.h	1970-01-01 01:00:00.000000000 +0100
+++ iso9660/directory_record.h	2008-09-21 14:21:55.000000000 +0200
@@ -0,0 +1,95 @@
+/*
+ * iso9660 - An iso9660 CDI driver with Rockridge support
+ *
+ * Copyright (C) 2008 Janosch Gräf
+ *
+ * This program is free software; you can redistribute it and/or modify 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.
+ *
+ * This program 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
+ * this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _DIRECTORY_RECORD_H_
+#define _DIRECTORY_RECORD_H_
+
+#include <stdint.h>
+
+// Date from ISO9660 directory entry
+struct iso9660_dirrec_date {
+  // Number of years since 1900
+  uint8_t year;
+
+  // Month (1=January, 2=February)
+  uint8_t month;
+
+  // Day of month
+  uint8_t day;
+
+  // Hour
+  uint8_t hour;
+
+  // Minute
+  uint8_t minute;
+
+  // Second
+  uint8_t second;
+
+  // GMT offset (in 15min intervals)
+  int8_t gmtoff;
+} __attribute__ ((packed));
+
+#define ISO9660_DIRREC_HIDDEN   1
+#define ISO9660_DIRREC_DIR      2
+#define ISO9660_DIRREC_ASSOC    4
+#define ISO9660_DIRREC_RECFMT   8
+#define ISO9660_DIRREC_PERM     16
+#define ISO9660_DIRREC_NOTFINAL 128
+
+// ISO9660 directory entry
+struct iso9660_dirrec {
+  // Size of this record (must be even)
+  uint8_t record_size;
+
+  // Number of sectors in extended attribute record
+  uint8_t num_sectors_extattrrec;
+
+  // First sector for file/directory data (0 if empty)
+  uint32_t data_sector;
+  uint32_t data_sector_be;
+
+  // File/directory data size
+  uint32_t data_size;
+  uint32_t data_size_be;
+
+  // Date of creation
+  struct iso9660_dirrec_date date_creation;
+
+  // File flags
+  uint8_t flags;
+
+  // Unit size for interleaved files (should be 0)
+  uint8_t interleaved_unit_size;
+
+  // Gap size for interleaved files (should be 0)
+  uint8_t interleaved_gap_size;
+
+  // Volume sequence number
+  uint16_t volume_seq;
+  uint16_t volume_seq_be;
+
+  // Identifier length
+  uint8_t identifier_length;
+
+  // Identifier
+  uint8_t identifier[1];
+} __attribute__ ((packed));
+
+#endif
diff -urNp tmp/file.c iso9660/file.c
--- tmp/file.c	1970-01-01 01:00:00.000000000 +0100
+++ iso9660/file.c	2008-09-21 13:58:07.000000000 +0200
@@ -0,0 +1,43 @@
+/*
+ * iso9660 - An iso9660 CDI driver with Rockridge support
+ *
+ * Copyright (C) 2008 Janosch Gräf
+ *
+ * This program is free software; you can redistribute it and/or modify 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.
+ *
+ * This program 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
+ * this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cdi/fs.h"
+#include "cdi/cache.h"
+
+#include "iso9660_cdi.h"
+
+/**
+ * Reads from file
+ *  @param stream CDI FS stream
+ *  @param start Offset in flie
+ *  @param size How many bytes to read
+ *  @param buffer Buffer to store data in
+ *  @return How many bytes read
+ */
+size_t iso9660_fs_file_read(struct cdi_fs_stream *stream,uint64_t start,size_t size,void *buffer) {
+  debug("iso9660_fs_file_read(0x%x,0x%x,0x%x,0x%x,0x%x)\n",stream,start,size,buffer);
+  struct iso9660_fs_res *res = (struct iso9660_fs_res*)stream->res;
+
+  if (start>res->data_size) return 0;
+  if (start+size>res->data_size) size = res->data_size-start;
+
+  iso9660_read(res,start,size,buffer);
+  //cdi_cache_entry_read(res->cache_entry,start,size,buffer);
+  return size;
+}
diff -urNp tmp/init.c iso9660/init.c
--- tmp/init.c	1970-01-01 01:00:00.000000000 +0100
+++ iso9660/init.c	2008-09-21 13:58:38.000000000 +0200
@@ -0,0 +1,57 @@
+/*
+ * iso9660 - An iso9660 CDI driver with Rockridge support
+ *
+ * Copyright (C) 2008 Janosch Gräf
+ *
+ * This program is free software; you can redistribute it and/or modify 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.
+ *
+ * This program 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
+ * this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+
+#include "cdi/fs.h"
+#include "cdi/cache.h"
+
+#include "iso9660_cdi.h"
+
+#include "volume_descriptor.h"
+
+/**
+ * Initializes a ISO9660 filesystem
+ *  @param fs Filesystem to initialize
+ *  @return If initialization was successful
+ */
+int iso9660_fs_init(struct cdi_fs_filesystem *fs) {
+  debug("iso9660_fs_init(0x%x)\n",fs);
+  struct iso9660_voldesc_prim *voldesc = malloc(sizeof(struct iso9660_voldesc_prim));
+  if (iso9660_voldesc_load(fs,ISO9660_VOLDESC_PRIM,voldesc)!=-1) {
+    struct iso9660_fs_res *root_res = iso9660_dirrec_load(&voldesc->root_dir,NULL,voldesc);
+    root_res->cache = cdi_cache_create(voldesc->sector_size,0,iso9660_sector_read_cache,NULL,fs);
+    fs->root_res = (struct cdi_fs_res*)root_res;
+    return 1;
+  }
+  else return 0;
+}
+
+/**
+ * Destroys a FS
+ *  @param fs Filesystem to destroy
+ *  @return If destroy was successful
+ */
+int iso9660_fs_destroy(struct cdi_fs_filesystem *fs) {
+  fprintf(stderr,"iso9660_fs_destroy(0x%x)\n",fs);
+  struct iso9660_fs_res *root_res = (struct iso9660_fs_res*)(fs->root_res);
+  free(root_res->voldesc);
+  cdi_cache_destroy(root_res->cache);
+  return iso9660_fs_res_destroy(root_res);
+}
diff -urNp tmp/iso9660_cdi.h iso9660/iso9660_cdi.h
--- tmp/iso9660_cdi.h	1970-01-01 01:00:00.000000000 +0100
+++ iso9660/iso9660_cdi.h	2008-09-21 14:27:58.000000000 +0200
@@ -0,0 +1,94 @@
+/*
+ * iso9660 - An iso9660 CDI driver with Rockridge support
+ *
+ * Copyright (C) 2008 Janosch Gräf
+ *
+ * This program is free software; you can redistribute it and/or modify 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.
+ *
+ * This program 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
+ * this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _ISO9660_CDI_H_
+#define _ISO9660_CDI_H_
+
+#include <stdint.h>
+#include <stddef.h>
+
+#include "cdi/fs.h"
+#include "cdi/cache.h"
+#include "cdi/lists.h"
+
+#include "iso9660def.h"
+#include "volume_descriptor.h"
+
+// ISO9660 Resource
+struct iso9660_fs_res {
+  struct cdi_fs_res res;
+
+  // Creation time
+  uint64_t ctime;
+
+  // Access time
+  uint64_t atime;
+
+  // Modification time
+  uint64_t mtime;
+
+  // First sector with resource data
+  uint64_t data_sector;
+
+  // Size of resource data
+  uint32_t data_size;
+
+  // File class
+  cdi_fs_res_class_t class;
+
+  // Primary volume descriptor
+  struct iso9660_voldesc_prim *voldesc;
+
+  // Cache
+  struct cdi_cache *cache;
+};
+
+// init.c
+int iso9660_fs_init(struct cdi_fs_filesystem *fs);
+int iso9660_fs_destroy(struct cdi_fs_filesystem *fs);
+
+// res.c
+struct iso9660_fs_res *iso9660_fs_res_create(const char *name,struct iso9660_fs_res *parent,cdi_fs_res_class_t class,cdi_fs_res_type_t type);
+int iso9660_fs_res_destroy(struct iso9660_fs_res *res);
+int iso9660_fs_res_load(struct cdi_fs_stream *stream);
+int iso9660_fs_res_unload(struct cdi_fs_stream *stream);
+int64_t iso9660_fs_res_meta_read(struct cdi_fs_stream *stream,cdi_fs_meta_t meta);
+
+// file.c
+size_t iso9660_fs_file_read(struct cdi_fs_stream *stream,uint64_t start,size_t size,void *buffer);
+
+// dir.c
+cdi_list_t iso9660_dir_load(struct iso9660_fs_res *res);
+struct iso9660_fs_res *iso9660_dirrec_load(struct iso9660_dirrec *dirrec,struct iso9660_fs_res *parent,struct iso9660_voldesc_prim *voldesc);
+cdi_list_t iso9660_fs_dir_list(struct cdi_fs_stream *stream);
+
+// sector.c
+#define iso9660_sector_read(fs,start,size,buffer) cdi_fs_data_read(fs,start,size,buffer)
+size_t iso9660_read(struct iso9660_fs_res *res,size_t pos,size_t size,void *buffer);
+int iso9660_sector_read_cache(struct cdi_cache *cache,uint64_t block,size_t count,void *dest,void *prv);
+
+// resources.c
+extern struct cdi_fs_res_res    iso9660_fs_res_res;
+extern struct cdi_fs_res_file   iso9660_fs_res_file;
+extern struct cdi_fs_res_dir    iso9660_fs_res_dir;
+
+// Debug
+int debug(const char *fmt,...);
+
+#endif
diff -urNp tmp/iso9660def.h iso9660/iso9660def.h
--- tmp/iso9660def.h	1970-01-01 01:00:00.000000000 +0100
+++ iso9660/iso9660def.h	2008-09-21 15:13:28.000000000 +0200
@@ -0,0 +1,38 @@
+/*
+ * iso9660 - An iso9660 CDI driver with Rockridge support
+ *
+ * Copyright (C) 2008 Janosch Gräf
+ *
+ * This program is free software; you can redistribute it and/or modify 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.
+ *
+ * This program 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
+ * this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _ISO9660DEF_H_
+#define _ISO9660DEF_H_
+
+// Default sector size. Used to load volume descriptors
+#define ISO9660_DEFAULT_SECTOR_SIZE 2048
+
+// Number of first used sector (first volume descriptor)
+#define ISO9660_FIRST_SECTOR        16
+
+// Define if you want to use lower filenames
+// (if you don't use an extension that supports lower filenames)
+#define ISO9660_LOWER_FILENAMES
+
+#ifndef ISO9660_USE_ROCKRIDGE
+  // Define if you want to use Rockridge extension
+  #define ISO9660_USE_ROCKRIDGE
+#endif
+
+#endif
diff -urNp tmp/main.c iso9660/main.c
--- tmp/main.c	1970-01-01 01:00:00.000000000 +0100
+++ iso9660/main.c	2008-09-21 14:32:42.000000000 +0200
@@ -0,0 +1,95 @@
+/*
+ * iso9660 - An iso9660 CDI driver with Rockridge support
+ *
+ * Copyright (C) 2008 Janosch Gräf
+ *
+ * This program is free software; you can redistribute it and/or modify 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.
+ *
+ * This program 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
+ * this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "cdi/fs.h"
+
+#include "iso9660_cdi.h"
+
+struct iso9660_driver {
+  struct cdi_fs_driver drv;
+};
+
+static struct iso9660_driver iso9660_driver;
+static const char* driver_name = "iso9660";
+
+static int iso9660_driver_init(struct iso9660_driver *driver);
+static void iso9660_driver_destroy(struct cdi_driver* driver);
+
+#ifdef CDI_STANDALONE
+int main()
+#else
+int init_iso9660()
+#endif
+{
+    cdi_init();
+
+    if (iso9660_driver_init(&iso9660_driver)!=0) return -1;
+    cdi_fs_driver_register((struct cdi_fs_driver*)&iso9660_driver);
+
+#ifdef CDI_STANDALONE
+    cdi_run_drivers();
+#endif
+
+    return 0;
+}
+
+/**
+ * Initializes the data structures for the iso9660 driver
+ */
+static int iso9660_driver_init(struct iso9660_driver *driver) {
+    // Konstruktor der Vaterklasse
+    cdi_fs_driver_init((struct cdi_fs_driver*)driver);
+
+    // Namen setzen
+    driver->drv.drv.name = driver_name;
+    driver->drv.fs_init = iso9660_fs_init;
+    driver->drv.fs_destroy = iso9660_fs_destroy;
+    driver->drv.drv.destroy = iso9660_driver_destroy;
+    return 0;
+}
+
+/**
+ * Deinitialize the data structures for the iso9660 driver
+ */
+static void iso9660_driver_destroy(struct cdi_driver* driver)
+{
+    cdi_fs_driver_destroy((struct cdi_fs_driver*)driver);
+}
+
+/**
+ * If DEBUG is definded, it outputs the debug message onto the stream
+ * defined with DEBUG
+ *  @param fmt Format (see printf)
+ *  @param ... Parameters
+ *  @return Amount of output characters
+ */
+int debug(const char *fmt,...) {
+#ifdef DEBUG
+  va_list args;
+  va_start(args,fmt);
+  int ret = vfprintf(DEBUG,fmt,args);
+  va_end(args);
+  return ret;
+#else
+  return 0;
+#endif
+}
diff -urNp tmp/Makefile iso9660/Makefile
--- tmp/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ iso9660/Makefile	2008-09-20 20:14:09.000000000 +0200
@@ -0,0 +1,13 @@
+-include ../../Makefile.config
+
+all:
+	$(CC) -o iso9660 *.c -lcdi
+	$(STRIP) iso9660
+	cp iso9660 ../../files/bin
+
+debug:
+	$(CC) -o iso9660 *.c -lcdi
+	$(OBJDUMP) -d -S iso9660 > iso9660.objdump
+
+clean:
+	rm iso9660
diff -urNp tmp/res.c iso9660/res.c
--- tmp/res.c	1970-01-01 01:00:00.000000000 +0100
+++ iso9660/res.c	2008-09-21 13:59:04.000000000 +0200
@@ -0,0 +1,148 @@
+/*
+ * iso9660 - An iso9660 CDI driver with Rockridge support
+ *
+ * Copyright (C) 2008 Janosch Gräf
+ *
+ * This program is free software; you can redistribute it and/or modify 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.
+ *
+ * This program 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
+ * this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "cdi/lists.h"
+#include "cdi/fs.h"
+#include "cdi/cache.h"
+
+#include "volume_descriptor.h"
+
+#include "iso9660_cdi.h"
+
+/**
+ * Creates a new resource
+ *  @param name Name of resource
+ *  @param parent Parent resource
+ *  @param class File class
+ *  @param type Special file type
+ *  @return ISO9660 class
+ */
+struct iso9660_fs_res *iso9660_fs_res_create(const char *name,struct iso9660_fs_res *parent,cdi_fs_res_class_t class,cdi_fs_res_type_t type) {
+  debug("iso9660_fs_res_create(%s,0x%x,%d)\n",name,parent,class);
+  struct iso9660_fs_res *res = malloc(sizeof(struct iso9660_fs_res));
+
+  memset(res,0,sizeof(struct iso9660_fs_res));
+  res->res.name = strdup(name);
+  res->res.res = &iso9660_fs_res_res;
+  res->res.parent = (struct cdi_fs_res*)parent;
+  res->class = class;
+  res->res.type = type;
+  if (class==CDI_FS_CLASS_DIR) res->res.dir = &iso9660_fs_res_dir;
+  else res->res.file = &iso9660_fs_res_file;
+  res->res.flags.read = 1;
+  res->res.flags.execute = 1;
+  res->res.flags.browse = 1;
+  res->res.flags.read_link = 1;
+
+  if (parent!=NULL) {
+    res->voldesc = parent->voldesc;
+    res->cache = parent->cache;
+  }
+  return res;
+}
+
+/**
+ * Destroys a resource
+ *  @param res ISO9660 resource
+ *  @return 0=success; -1=failure
+ */
+int iso9660_fs_res_destroy(struct iso9660_fs_res *res) {
+  debug("iso9660_fs_res_destroy(0x%x)\n",res);
+  free(res->res.name);
+  if (res->res.children!=NULL) {
+    size_t i;
+    struct iso9660_fs_res *child;
+    for (i=0;(child = cdi_list_get(res->res.children,i));i++) iso9660_fs_res_destroy(child);
+    cdi_list_destroy(res->res.children);
+  }
+  return 0;
+}
+
+/**
+ * Loads a resource
+ *  @param stream CDI FS stream
+ *  @return 0=success; -1=failure
+ */
+int iso9660_fs_res_load(struct cdi_fs_stream *stream) {
+  struct iso9660_fs_res *res = (struct iso9660_fs_res*)stream->res;
+
+  if (!res->res.loaded) {
+    // Create cache
+    //size_t i;
+    //for (i=0;i<res->data_size;i+=res->voldesc->sector_size) cdi_cache_entry_new(res->cache,res->data_offset+i,res->voldesc->sector_size);
+
+    if (res->class==CDI_FS_CLASS_DIR) res->res.children = iso9660_dir_load(res);
+    else res->res.children = cdi_list_create();
+    res->res.loaded = 1;
+  }
+  return 1;
+}
+
+/**
+ * Unloads a resource
+ *  @param stream CDI FS stream
+ *  @return 0=success; -1=failure
+ */
+int iso9660_fs_res_unload(struct cdi_fs_stream *stream) {
+  struct iso9660_fs_res *res = (struct iso9660_fs_res*)stream->res;
+
+  if (res->res.loaded) {
+    // Destroy children
+    struct iso9660_fs_res *child;
+    while ((child = cdi_list_pop(res->res.children))) iso9660_fs_res_destroy(child);
+    cdi_list_destroy(res->res.children);
+
+    res->res.loaded = 0;
+  }
+  return 1;
+}
+
+/**
+ * Reads meta data from resource
+ *  @param stream CDI FS stream
+ *  @param meta Type of meta data
+ *  @return Meta data
+ */
+int64_t iso9660_fs_res_meta_read(struct cdi_fs_stream *stream,cdi_fs_meta_t meta) {
+  struct iso9660_fs_res *res = (struct iso9660_fs_res*)stream->res;
+  switch (meta) {
+    case CDI_FS_META_SIZE:
+      return res->data_size;
+
+    case CDI_FS_META_USEDBLOCKS:
+      return (res->data_size-1)/res->voldesc->sector_size+1;
+
+    case CDI_FS_META_BESTBLOCKSZ:
+    case CDI_FS_META_BLOCKSZ:
+      return res->voldesc->sector_size;
+
+    case CDI_FS_META_CREATETIME:
+      return res->ctime;
+
+    case CDI_FS_META_ACCESSTIME:
+      return res->atime;
+
+    case CDI_FS_META_CHANGETIME:
+      return res->mtime;
+  }
+  return 0;
+}
diff -urNp tmp/resources.c iso9660/resources.c
--- tmp/resources.c	1970-01-01 01:00:00.000000000 +0100
+++ iso9660/resources.c	2008-09-20 20:39:27.000000000 +0200
@@ -0,0 +1,38 @@
+/*
+ * iso9660 - An iso9660 CDI driver with Rockridge support
+ *
+ * Copyright (C) 2008 Janosch Gräf
+ *
+ * This program is free software; you can redistribute it and/or modify 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.
+ *
+ * This program 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
+ * this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "iso9660_cdi.h"
+
+struct cdi_fs_res_res iso9660_fs_res_res = {
+    .load = iso9660_fs_res_load,
+    .unload = iso9660_fs_res_unload,
+    .meta_read = iso9660_fs_res_meta_read,
+};
+
+struct cdi_fs_res_file iso9660_fs_res_file = {
+    // Prinzipiell haben wir nur ausfuehrbare Dateien, der Rest wird mit den
+    // Berechtigungen geregelt
+    .executable = 1,
+
+    .read = iso9660_fs_file_read,
+};
+
+struct cdi_fs_res_dir iso9660_fs_res_dir = {
+    .list = iso9660_fs_dir_list,
+};
diff -urNp tmp/rockridge.c iso9660/rockridge.c
--- tmp/rockridge.c	1970-01-01 01:00:00.000000000 +0100
+++ iso9660/rockridge.c	2008-09-20 23:03:31.000000000 +0200
@@ -0,0 +1,89 @@
+/*
+ * iso9660 - An iso9660 CDI driver with Rockridge support
+ *
+ * Copyright (C) 2008 Janosch Gräf
+ *
+ * This program is free software; you can redistribute it and/or modify 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.
+ *
+ * This program 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
+ * this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "iso9660def.h"
+#ifdef ISO9660_USE_ROCKRIDGE
+
+#include <stdint.h>
+#include <stddef.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "cdi/lists.h"
+
+#include "rockridge.h"
+#include "directory_record.h"
+
+/**
+ * Scans system use area in directory record for rockridge entries
+ *  @param dirrec Directory record
+ *  @param _name Reference for POSIX name
+ *  @param mode Reference for file mode
+ *  @param uid Reference for UID
+ *  @param gid Reference for GID
+ *  @param nlink Reference for number of hardlinks
+ *  @param atime Reference for access time
+ *  @param ctime Reference for createtion time
+ *  @param mtime Reference for modification time
+ *  @return 0=success; -1=failure
+ */
+int iso9660_rockridge_scan(struct iso9660_dirrec *dirrec,char **_name,mode_t *mode,uid_t *uid,gid_t *gid,nlink_t *nlink,uint64_t *atime,uint64_t *ctime,uint64_t *mtime) {
+  struct iso9660_rockridge *sue = ((void*)(dirrec->identifier))+dirrec->identifier_length;
+  if ((((uintptr_t)sue)&1)==1) sue = ((void*)sue)+1;
+
+  if (sue->sig!=ISO9660_ROCKRIDGE_SIG_RR) return -1;
+
+  char *name = NULL;
+  size_t name_size = 0;
+
+  while (sue->sig!=ISO9660_ROCKRIDGE_SIG_ST && sue->sig!=0 && ((uintptr_t)sue-(uintptr_t)dirrec)+4<dirrec->record_size) {
+    if (sue->sig==ISO9660_ROCKRIDGE_SIG_PX) {
+      struct iso9660_rockridge_px *sue_px = (struct iso9660_rockridge_px*)sue;
+      if (mode!=NULL) *mode = sue_px->mode;
+      if (nlink!=NULL) *nlink = sue_px->nlink;
+      if (uid!=NULL) *uid = sue_px->uid;
+      if (gid!=NULL) *gid = sue_px->gid;
+    }
+    else if (sue->sig==ISO9660_ROCKRIDGE_SIG_NM) {
+      struct iso9660_rockridge_nm *sue_nm = (struct iso9660_rockridge_nm*)sue;
+      if (sue_nm->flags&ISO9660_ROCKRIDGE_NAMEFLAG_CURRENT) *_name = strdup(".");
+      else if (sue_nm->flags&ISO9660_ROCKRIDGE_NAMEFLAG_PARENT) *_name = strdup("..");
+      else {
+        size_t part_size = sue->size-offsetof(struct iso9660_rockridge_nm,name);
+        name = realloc(name,name_size+part_size+1);
+        memcpy(name+name_size,sue_nm->name,part_size);
+        name_size += part_size;
+      }
+    }
+    sue = ((void*)sue)+sue->size;
+  }
+
+  if (name!=NULL) {
+    if (_name!=NULL) {
+      name[name_size] = 0;
+      *_name = name;
+    }
+    else free(name);
+  }
+
+  return 0;
+}
+
+#endif
diff -urNp tmp/rockridge.h iso9660/rockridge.h
--- tmp/rockridge.h	1970-01-01 01:00:00.000000000 +0100
+++ iso9660/rockridge.h	2008-09-21 15:11:13.000000000 +0200
@@ -0,0 +1,181 @@
+/*
+ * iso9660 - An iso9660 CDI driver with Rockridge support
+ *
+ * Copyright (C) 2008 Janosch Gräf
+ *
+ * This program is free software; you can redistribute it and/or modify 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.
+ *
+ * This program 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
+ * this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _ISO9660_ROCKRIDGE_H_
+#define _ISO9660_ROCKRIDGE_H_
+
+#include <sys/types.h>
+#include <stdint.h>
+
+#include "directory_record.h"
+
+#define ISO9660_ROCKRIDGE_VERSION 1
+
+#define ISO9660_ROCKRIDGE_SL_FLAG_LAST 1
+
+#define ISO9660_ROCKRIDGE_NAMEFLAG_CONTINUE 1
+#define ISO9660_ROCKRIDGE_NAMEFLAG_CURRENT  2
+#define ISO9660_ROCKRIDGE_NAMEFLAG_PARENT   4
+#define ISO9660_ROCKRIDGE_NAMEFLAG_ROOT     8
+
+#define ISO9660_ROCKRIDGE_TFFLAG_CREATION   1
+#define ISO9660_ROCKRIDGE_TFFLAG_MODIFY     2
+#define ISO9660_ROCKRIDGE_TFFLAG_ACCESS     4
+#define ISO9660_ROCKRIDGE_TFFLAG_ATTRIBUTES 8
+#define ISO9660_ROCKRIDGE_TFFLAG_BACKUP     16
+#define ISO9660_ROCKRIDGE_TFFLAG_EXPIRATION 32
+#define ISO9660_ROCKRIDGE_TFFLAG_EFFECTIVE  64
+#define ISO9660_ROCKRIDGE_TFFLAG_LONGFORM   128
+
+#define ISO9660_ROCKRIDGE_SIG_SP ('S'|('P'<<8))
+#define ISO9660_ROCKRIDGE_SIG_ST ('S'|('T'<<8))
+#define ISO9660_ROCKRIDGE_SIG_RR ('R'|('R'<<8)) ///< @todo Actually the SUE must start with SP and not with RR
+#define ISO9660_ROCKRIDGE_SIG_PX ('P'|('X'<<8))
+#define ISO9660_ROCKRIDGE_SIG_PN ('P'|('N'<<8))
+#define ISO9660_ROCKRIDGE_SIG_SL ('S'|('L'<<8))
+#define ISO9660_ROCKRIDGE_SIG_NM ('N'|('M'<<8))
+#define ISO9660_ROCKRIDGE_SIG_CL ('C'|('L'<<8))
+#define ISO9660_ROCKRIDGE_SIG_PL ('P'|('L'<<8))
+#define ISO9660_ROCKRIDGE_SIG_RE ('R'|('E'<<8))
+#define ISO9660_ROCKRIDGE_SIG_RF ('R'|('F'<<8))
+#define ISO9660_ROCKRIDGE_SIG_SF ('S'|('F'<<8))
+
+// Some POSIX stat stuff
+
+#define RS_IFMT   00170000
+#define RS_IFSOCK 00140000
+#define RS_IFLNK  00120000
+#define RS_IFREG  00100000
+#define RS_IFBLK  00060000
+#define RS_IFDIR  00040000
+#define RS_IFCHR  00020000
+#define RS_IFIFO  00010000
+
+#define RS_ISLNK(m)  (((m)&RS_IFMT)==RS_IFLNK)
+#define RS_ISREG(m)  (((m)&RS_IFMT)==RS_IFREG)
+#define RS_ISDIR(m)  (((m)&RS_IFMT)==RS_IFDIR)
+#define RS_ISCHR(m)  (((m)&RS_IFMT)==RS_IFCHR)
+#define RS_ISBLK(m)  (((m)&RS_IFMT)==RS_IFBLK)
+#define RS_ISFIFO(m) (((m)&RS_IFMT)==RS_IFIFO)
+#define RS_ISSOCK(m) (((m)&RS_IFMT)==RS_IFSOCK)
+
+typedef unsigned int rmode_t;
+
+// Rockridge System Use Entry
+struct iso9660_rockridge {
+  // Field signature
+  uint16_t sig;
+
+  // Size of field
+  uint8_t size;
+
+  // Version
+  uint8_t version;
+} __attribute__ ((packed));
+
+/// @todo Actually the SUE must start with SP and not with RR
+struct iso9660_rockridge_rr {
+  // Size: 5
+  struct iso9660_rockridge header;
+  uint8_t unknown;
+} __attribute__ ((packed));
+
+// Rockridge System Use Entry for file permissions
+struct iso9660_rockridge_px {
+  // Size: 44
+  struct iso9660_rockridge header;
+
+  // File mode (like in sys/stat.h)
+  uint32_t mode;
+  uint32_t mode_be;
+
+  // Number of links (like in sys/stat.h)
+  uint32_t nlink;
+  uint32_t nlink_be;
+
+  // Owner UID
+  uint32_t uid;
+  uint32_t uid_be;
+
+  // Owner GID
+  uint32_t gid;
+  uint32_t gid_be;
+
+  // File serial number
+  uint32_t serial;
+  uint32_t serial_be;
+} __attribute__ ((packed));
+
+// Rockridge System Use Entry for device nodes
+struct iso9660_rockridge_pn {
+  // Size: 20
+  struct iso9660_rockridge header;
+
+  // Device number
+  uint32_t devhi;
+  uint32_t devhi_be;
+  uint32_t devlo;
+  uint32_t devlo_be;
+} __attribute__ ((packed));
+
+// Rockridge SL Component
+struct iso9660_rockridge_sl_component {
+  uint8_t flags;
+  uint8_t len;
+  uint8_t content[0];
+} __attribute__ ((packed));
+
+// Rockridge System Use Entry for symbolic links
+struct iso9660_rockridge_sl {
+  // Size:
+  struct iso9660_rockridge header;
+
+  // Flags
+  uint8_t flags;
+
+  // Component Area
+  struct iso9660_rockridge_sl_component component_area[0];
+} __attribute__ ((packed));
+
+// Rockridge System Use Entry for POSIX names
+struct iso9660_rockridge_nm {
+  // Size:
+  struct iso9660_rockridge header;
+
+  // Flags
+  uint8_t flags;
+
+  // Name content
+  uint8_t name[1];
+} __attribute__ ((packed));
+
+// Rockridge System Use Entry for timestamps
+struct iso9660_rockridge_tf {
+  // Size:
+  struct iso9660_rockridge header;
+
+  // Flags (Type of timestamp
+  uint8_t flags;
+
+  uint32_t timestamps[0];
+} __attribute__ ((packed));
+
+int iso9660_rockridge_scan(struct iso9660_dirrec *dirrec,char **_name,mode_t *mode,uid_t *uid,gid_t *gid,nlink_t *nlink,uint64_t *atime,uint64_t *ctime,uint64_t *mtime);
+
+#endif
diff -urNp tmp/sector.c iso9660/sector.c
--- tmp/sector.c	1970-01-01 01:00:00.000000000 +0100
+++ iso9660/sector.c	2008-09-21 14:33:35.000000000 +0200
@@ -0,0 +1,70 @@
+/*
+ * iso9660 - An iso9660 CDI driver with Rockridge support
+ *
+ * Copyright (C) 2008 Janosch Gräf
+ *
+ * This program is free software; you can redistribute it and/or modify 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.
+ *
+ * This program 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
+ * this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdint.h>
+
+#include "cdi/fs.h"
+#include "cdi/cache.h"
+
+#include "iso9660def.h"
+
+#include "iso9660_cdi.h"
+
+/**
+ * Reads data from device for cache
+ *  @param cache CDI cache
+ *  @param block Block to read
+ *  @param count How many blocks to read
+ *  @param dest Buffer to store data in
+ *  @param prv Private data (CDI filesystem)
+ */
+int iso9660_sector_read_cache(struct cdi_cache *cache,uint64_t block,size_t count,void *dest,void *prv) {
+  debug("iso9660_sector_read_cache(0x%x,0x%x,0x%x,0x%x,0x%x,0x%x)\n",cache,block,count,dest,prv);
+  uint64_t start = ((uint64_t)block)*ISO9660_DEFAULT_SECTOR_SIZE;
+  size_t size = count*ISO9660_DEFAULT_SECTOR_SIZE;
+  return iso9660_sector_read(prv,start,size,dest)/ISO9660_DEFAULT_SECTOR_SIZE;
+}
+
+/**
+ * Read data from resource
+ *  @param res Resource to read data from
+ *  @param pos Position in resource
+ *  @param size How many bytes to read
+ *  @param Buffer Buffer to store data in
+ *  @return How many bytes read
+ */
+size_t iso9660_read(struct iso9660_fs_res *res,size_t pos,size_t size,void *buffer) {
+  size_t block = pos/res->voldesc->sector_size;
+  size_t offset = pos%res->voldesc->sector_size;
+  size_t rem_size = size;
+
+  while (rem_size>0) {
+    //debug("Block: 0x%x\n",res->data_sector+block++);
+    struct cdi_cache_block *cache_block = cdi_cache_block_get(res->cache,res->data_sector+block++);
+    size_t cur_size = rem_size>res->voldesc->sector_size?res->voldesc->sector_size:rem_size;
+    memcpy(buffer,cache_block->data+offset,cur_size);
+    cdi_cache_block_release(res->cache,cache_block);
+    buffer += cur_size;
+    rem_size -= cur_size;
+    offset = 0;
+  }
+
+  return size;
+}
+
diff -urNp tmp/volume_descriptor.c iso9660/volume_descriptor.c
--- tmp/volume_descriptor.c	1970-01-01 01:00:00.000000000 +0100
+++ iso9660/volume_descriptor.c	2008-09-21 13:59:20.000000000 +0200
@@ -0,0 +1,69 @@
+/*
+ * iso9660 - An iso9660 CDI driver with Rockridge support
+ *
+ * Copyright (C) 2008 Janosch Gräf
+ *
+ * This program is free software; you can redistribute it and/or modify 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.
+ *
+ * This program 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
+ * this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdint.h>
+
+#include "cdi/fs.h"
+
+#include "iso9660_cdi.h"
+
+#include "iso9660def.h"
+#include "volume_descriptor.h"
+
+/**
+ * Checks signature of volume descriptor
+ *  @param sig Signature
+ *  @return If signature is right
+ */
+static int iso9660_voldesc_checksig(uint8_t sig[6]) {
+  size_t i;
+  char right[6] = {'C','D','0','0','1',1};
+  for (i=0;i<6;i++) {
+    if (sig[i]!=right[i]) return 0;
+  }
+  return 1;
+}
+
+/**
+ * Loads a volume descriptor
+ *  @param fs Filesystem
+ *  @param type Type of volume descriptor
+ *  @param buf Buffer for volume descriptor
+ *  @return 0=success; -1=failure
+ */
+int iso9660_voldesc_load(struct cdi_fs_filesystem *fs,iso9660_voldesc_type_t type,void *buf) {
+  debug("iso9660_voldesc_load(0x%x,%d,0x%x)\n",fs,type,buf);
+  struct iso9660_voldesc header;
+  size_t i;
+
+  for (i=ISO9660_FIRST_SECTOR;header.type!=type && header.type!=ISO9660_VOLDESC_TERM;i++) {
+    iso9660_sector_read(fs,i*ISO9660_DEFAULT_SECTOR_SIZE,sizeof(header),&header);
+    if (!iso9660_voldesc_checksig(header.signature)) return -1;
+  }
+  i--;
+
+  if (header.type==type) {
+    iso9660_sector_read(fs,i*ISO9660_DEFAULT_SECTOR_SIZE,sizeof(struct iso9660_voldesc_prim),buf);
+    return 0;
+  }
+  else {
+    debug("Volume Descriptor: Wrong type: %d\n",header.type);
+    return -1;
+  }
+}
diff -urNp tmp/volume_descriptor.h iso9660/volume_descriptor.h
--- tmp/volume_descriptor.h	1970-01-01 01:00:00.000000000 +0100
+++ iso9660/volume_descriptor.h	2008-09-21 15:04:57.000000000 +0200
@@ -0,0 +1,150 @@
+/*
+ * iso9660 - An iso9660 CDI driver with Rockridge support
+ *
+ * Copyright (C) 2008 Janosch Gräf
+ *
+ * This program is free software; you can redistribute it and/or modify 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.
+ *
+ * This program 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
+ * this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _VOLUME_DESCRIPTOR_H_
+#define _VOLUME_DESCRIPTOR_H_
+
+#include <stdint.h>
+
+#include "directory_record.h"
+
+// ISO9660 volume descriptor type
+typedef enum {
+  ISO9660_VOLDESC_TERM = 255,
+  ISO9660_VOLDESC_PRIM = 1
+} iso9660_voldesc_type_t;
+
+// ISO9660 volume descriptor header
+struct iso9660_voldesc {
+  iso9660_voldesc_type_t type:8;
+  uint8_t signature[6];
+} __attribute__ ((packed));
+
+// Date from ISO9660 volume descriptor
+struct i9660_voldesc_date {
+  // Year (as ASCII)
+  uint32_t year[4];
+
+  // Month (as ASCII; 01=January, 02=February...)
+  uint8_t month[2];
+
+  // Day of month (as ASCII)
+  uint8_t day[2];
+
+  // Hour (as ASCII)
+  uint8_t hour[2];
+
+  // Minute (as ASCII)
+  uint8_t minute[2];
+
+  // Second (as ASCII)
+  uint8_t second[2];
+
+  // Centisecond (as ASCII; hundredths of a second)
+  uint8_t centisecond[2];
+
+  // Offset to GMT (in 15min intervals)
+  int8_t gmtoff;
+} __attribute__ ((packed));
+
+struct iso9660_voldesc_prim {
+  // Volume Descriptor Header
+  struct iso9660_voldesc header;
+
+  // Zeros (0)
+  uint8_t zero1;
+
+  // System Identifier
+  uint8_t system_identifier[32];
+
+  // Volume Identifier
+  uint8_t volume_identifier[32];
+
+  // Zeros (0)
+  uint8_t zero2[8];
+
+  // Total number of sectors
+  uint32_t num_sectors;
+  uint32_t num_sectors_be;
+
+  // Zeros (0)
+  uint8_t zero3[32];
+
+  // Set size (1)
+  uint16_t set_size;
+  uint16_t set_size_be;
+
+  // Sequence number (1)
+  uint16_t seq_num;
+  uint16_t seq_num_be;
+
+  // Sector size (must be 2048)
+  uint16_t sector_size;
+  uint16_t sector_size_be;
+
+  // Size of path table
+  uint32_t pathtable_size;
+  uint32_t pathtable_size_be;
+
+  // First sectors of each path table
+  uint32_t pathtable1_sector;
+  uint32_t pathtable2_sector;
+  uint32_t pathtable1_sector_be;
+  uint32_t pathtable2_sector_be;
+
+  // Root directory record
+  struct iso9660_dirrec root_dir;
+
+  // Volume Set Identifier
+  uint8_t volume_set_identifier[128];
+
+  // Publisher Identifier
+  uint8_t publisher_identifier[128];
+
+  // Data Preparer Identifier
+  uint8_t datapreparer_identifier[128];
+
+  // Application Identifier
+  uint8_t application_identifier[128];
+
+  // Copyright File Identifier
+  uint8_t copyright_file_identifier[37];
+
+  // Abstract File Identifier
+  uint8_t abstract_file_identifier[37];
+
+  // Bibliographical File Identifier
+  uint8_t bibliographical_file_identifier[37];
+
+  // Date of volume creation
+  struct i9660_voldesc_date date_creation;
+
+  // Date of most recent modification
+  struct i9660_voldesc_date date_modification;
+
+  // Date when volume expires
+  struct i9660_voldesc_date date_expire;
+
+  // Date when volume is effective
+  struct i9660_voldesc_date date_effective;
+} __attribute__ ((packed));
+
+int iso9660_voldesc_load(struct cdi_fs_filesystem *fs,iso9660_voldesc_type_t type,void *buf);
+
+#endif