Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openbios / fs / iso9660 / iso9660_opendir.c
diff --git a/qemu/roms/openbios/fs/iso9660/iso9660_opendir.c b/qemu/roms/openbios/fs/iso9660/iso9660_opendir.c
new file mode 100644 (file)
index 0000000..49eab4b
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ *
+ * (c) 2005-2009 Laurent Vivier <Laurent@vivier.eu>
+ *
+ * This file has been copied from EMILE, http://emile.sf.net
+ *
+ */
+
+#include "libiso9660.h"
+
+static inline int iso9660_is_directory(struct iso_directory_record * idr)
+{
+       return ((idr->flags[0] & 2) != 0);
+}
+
+static iso9660_DIR* iso9660_opendir_node(iso9660_VOLUME *volume, struct iso_directory_record *node)
+{
+       iso9660_DIR *dir;
+
+       dir = (iso9660_DIR*)malloc(sizeof(iso9660_DIR));
+       if (dir == NULL)
+               return NULL;
+
+       dir->extent = isonum_733((char *)node->extent);
+       dir->len = isonum_733((char *)node->size);
+       dir->index =  sizeof (dir->buffer);
+       dir->volume = volume;
+
+       return dir;
+}
+
+static struct iso_directory_record* idr_new(struct iso_directory_record* idr)
+{
+       struct iso_directory_record* result;
+       int size = sizeof(*idr) + (int)idr->name_len[0];
+
+       result = (struct iso_directory_record*)malloc(size);
+       memcpy(result, idr, size);
+
+       return result;
+}
+
+static struct iso_directory_record * seek_name(iso9660_VOLUME *volume,
+                                              struct iso_directory_record *idr,
+                                              char *name)
+{
+       struct iso_directory_record *result;
+       char name_buf[256];
+       iso9660_DIR *dir;
+
+       dir = iso9660_opendir_node(volume, idr);
+       if (dir == NULL)
+               return NULL;
+
+       while ((idr = iso9660_readdir(dir)) != NULL)
+       {
+               iso9660_name(volume, idr, name_buf);
+               if (strcasecmp(name, name_buf) == 0)
+               {
+                       result = idr_new(idr);
+                       iso9660_closedir(dir);
+                       return result;
+               }
+       }
+       iso9660_closedir(dir);
+       return NULL;
+}
+
+struct iso_directory_record* iso9660_get_node(
+               iso9660_VOLUME *volume,
+               struct iso_directory_record *dirnode,
+               const char *path)
+{
+       struct iso_directory_record* result;
+       struct iso_directory_record* current;
+       char name[256];
+       int i;
+
+       current = idr_new(dirnode);
+       while(1)
+       {
+               /* ignore head '\' */
+
+               while (*path && *path == '\\')
+                       path++;
+
+               if (*path == 0)
+                       break;
+
+               /* extract first path component */
+
+               i = 0;
+               while (*path && *path != '\\')
+                       name[i++] = *path++;
+               name[i] = 0;
+
+               /* seek first component in current directory */
+
+               result = seek_name(volume, current, name);
+               if (result == NULL)
+                       return NULL;
+
+               free(current);
+               current = result;
+       }
+       return current;
+}
+
+iso9660_DIR* iso9660_opendir(iso9660_VOLUME *volume, const char *name)
+{
+       iso9660_DIR *dir;
+       struct iso_directory_record *node;
+
+       node = iso9660_get_root_node((iso9660_VOLUME*)volume);
+       if (node == NULL)
+               return NULL;
+
+       node = iso9660_get_node((iso9660_VOLUME*)volume, node, name);
+       if (node == NULL)
+               return NULL;
+       if (!iso9660_is_directory(node)) {
+               free(node);
+               return NULL;
+       }
+
+       dir = iso9660_opendir_node((iso9660_VOLUME*)volume, node);
+
+       free(node);
+
+       dir->volume = (iso9660_VOLUME*)volume;
+
+       return dir;
+}