Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openbios / fs / iso9660 / iso9660_opendir.c
1 /*
2  *
3  * (c) 2005-2009 Laurent Vivier <Laurent@vivier.eu>
4  *
5  * This file has been copied from EMILE, http://emile.sf.net
6  *
7  */
8
9 #include "libiso9660.h"
10
11 static inline int iso9660_is_directory(struct iso_directory_record * idr)
12 {
13         return ((idr->flags[0] & 2) != 0);
14 }
15
16 static iso9660_DIR* iso9660_opendir_node(iso9660_VOLUME *volume, struct iso_directory_record *node)
17 {
18         iso9660_DIR *dir;
19
20         dir = (iso9660_DIR*)malloc(sizeof(iso9660_DIR));
21         if (dir == NULL)
22                 return NULL;
23
24         dir->extent = isonum_733((char *)node->extent);
25         dir->len = isonum_733((char *)node->size);
26         dir->index =  sizeof (dir->buffer);
27         dir->volume = volume;
28
29         return dir;
30 }
31
32 static struct iso_directory_record* idr_new(struct iso_directory_record* idr)
33 {
34         struct iso_directory_record* result;
35         int size = sizeof(*idr) + (int)idr->name_len[0];
36
37         result = (struct iso_directory_record*)malloc(size);
38         memcpy(result, idr, size);
39
40         return result;
41 }
42
43 static struct iso_directory_record * seek_name(iso9660_VOLUME *volume,
44                                                struct iso_directory_record *idr,
45                                                char *name)
46 {
47         struct iso_directory_record *result;
48         char name_buf[256];
49         iso9660_DIR *dir;
50
51         dir = iso9660_opendir_node(volume, idr);
52         if (dir == NULL)
53                 return NULL;
54
55         while ((idr = iso9660_readdir(dir)) != NULL)
56         {
57                 iso9660_name(volume, idr, name_buf);
58                 if (strcasecmp(name, name_buf) == 0)
59                 {
60                         result = idr_new(idr);
61                         iso9660_closedir(dir);
62                         return result;
63                 }
64         }
65         iso9660_closedir(dir);
66         return NULL;
67 }
68
69 struct iso_directory_record* iso9660_get_node(
70                 iso9660_VOLUME *volume,
71                 struct iso_directory_record *dirnode,
72                 const char *path)
73 {
74         struct iso_directory_record* result;
75         struct iso_directory_record* current;
76         char name[256];
77         int i;
78
79         current = idr_new(dirnode);
80         while(1)
81         {
82                 /* ignore head '\' */
83
84                 while (*path && *path == '\\')
85                         path++;
86
87                 if (*path == 0)
88                         break;
89
90                 /* extract first path component */
91
92                 i = 0;
93                 while (*path && *path != '\\')
94                         name[i++] = *path++;
95                 name[i] = 0;
96
97                 /* seek first component in current directory */
98
99                 result = seek_name(volume, current, name);
100                 if (result == NULL)
101                         return NULL;
102
103                 free(current);
104                 current = result;
105         }
106         return current;
107 }
108
109 iso9660_DIR* iso9660_opendir(iso9660_VOLUME *volume, const char *name)
110 {
111         iso9660_DIR *dir;
112         struct iso_directory_record *node;
113
114         node = iso9660_get_root_node((iso9660_VOLUME*)volume);
115         if (node == NULL)
116                 return NULL;
117
118         node = iso9660_get_node((iso9660_VOLUME*)volume, node, name);
119         if (node == NULL)
120                 return NULL;
121         if (!iso9660_is_directory(node)) {
122                 free(node);
123                 return NULL;
124         }
125
126         dir = iso9660_opendir_node((iso9660_VOLUME*)volume, node);
127
128         free(node);
129
130         dir->volume = (iso9660_VOLUME*)volume;
131
132         return dir;
133 }