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 
iso9660_is_directory(struct iso_directory_record * idr)11 static inline int iso9660_is_directory(struct iso_directory_record * idr)
12 {
13 	return ((idr->flags[0] & 2) != 0);
14 }
15 
iso9660_opendir_node(iso9660_VOLUME * volume,struct iso_directory_record * node)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 
idr_new(struct iso_directory_record * idr)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 
seek_name(iso9660_VOLUME * volume,struct iso_directory_record * idr,char * name)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 
iso9660_get_node(iso9660_VOLUME * volume,struct iso_directory_record * dirnode,const char * path)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 
iso9660_opendir(iso9660_VOLUME * volume,const char * name)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 }
134