Added iso9660 driver (not yet working).
[planlOS.git] / system / modules / iso9660 / dir.c
blob5cda48a3e7267c84c24210ed2554c6982ce7394d
1 /*
2 * iso9660 - An iso9660 CDI driver with Rockridge support
4 * Copyright (C) 2008 Janosch Gräf
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 3 of the License, or (at your option)
9 * any later version.
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, see <http://www.gnu.org/licenses/>.
20 #include <stddef.h>
21 #include <stdlib.h>
23 #include "cdi/fs.h"
24 #include "cdi/lists.h"
25 #include "cdi/cache.h"
26 #include "cdi/misc.h"
28 #include "directory_record.h"
29 #include "volume_descriptor.h"
30 #include "iso9660def.h"
32 #ifdef ISO9660_USE_ROCKRIDGE
33 #include "rockridge.h"
34 #endif
36 #include "iso9660_cdi.h"
38 #ifdef ISO9660_LOWER_FILENAMES
39 #include <ctype.h>
40 #endif
42 /**
43 * Convert ISO9660 identifier to file name
44 * @param ident Identifier
45 * @param len Length of identifier
46 * @return Name (should be passed to free())
48 static char *parse_name(char *ident,size_t len) {
49 if (ident[len-2]==';') len -= 2;
50 if (ident[len-1]=='.') len--;
51 char *name = memcpy(malloc(len+1),ident,len);
52 #ifdef ISO9660_LOWER_FILENAMES
53 size_t i;
54 for (i=0;i<len;i++) name[i] = tolower(name[i]);
55 #endif
56 name[len] = 0;
57 return name;
60 /**
61 * Converts POSIX file mode to CDI class
62 * @param mode POSIX filemode
63 * @param special Reference for CDI special type
64 * @return CDI class
66 #ifdef ISO9660_USE_ROCKRIDGE
67 static cdi_fs_res_class_t parse_class(rmode_t mode,cdi_fs_res_type_t *special) {
68 cdi_fs_res_class_t class = CDI_FS_CLASS_FILE;
69 if (RS_ISBLK(mode)) {
70 class = CDI_FS_CLASS_SPECIAL;
71 if (special!=NULL) *special = CDI_FS_BLOCK;
73 else if (RS_ISCHR(mode)) {
74 class = CDI_FS_CLASS_SPECIAL;
75 if (special!=NULL) *special = CDI_FS_BLOCK;
77 else if (RS_ISFIFO(mode)) {
78 class = CDI_FS_CLASS_SPECIAL;
79 if (special!=NULL) *special = CDI_FS_FIFO;
81 else if (RS_ISSOCK(mode)) {
82 class = CDI_FS_CLASS_SPECIAL;
83 if (special!=NULL) *special = CDI_FS_SOCKET;
85 else if (RS_ISREG(mode)) class = CDI_FS_CLASS_FILE;
86 else if (RS_ISDIR(mode)) class = CDI_FS_CLASS_DIR;
87 else if (RS_ISLNK(mode)) class = CDI_FS_CLASS_LINK;
88 return class;
90 #endif
92 /**
93 * Converts ISO9660 time to CDI time
94 * @param date ISO9660-Zeit
95 * @return CDI time
97 static inline uint64_t parse_date(struct iso9660_dirrec_date *date) {
98 return cdi_time_by_date(date->year,date->month-1,date->day)+cdi_time_offset(date->hour,date->minute,date->second);
102 * Loads a ISO9660 directory entry
103 * @param dirrec Directory entry
104 * @param parent Parent resource
105 * @param voldesc Volume descriptor
106 * @return Resource
108 struct iso9660_fs_res *iso9660_dirrec_load(struct iso9660_dirrec *dirrec,struct iso9660_fs_res *parent,struct iso9660_voldesc_prim *voldesc) {
109 char *name = NULL;
110 uint64_t ctime = 0;
111 uint64_t atime = 0;
112 uint64_t mtime = 0;
113 cdi_fs_res_class_t class = 0;
114 cdi_fs_res_type_t type = 0;
116 #ifdef ISO9660_USE_ROCKRIDGE
117 rmode_t mode;
118 if (iso9660_rockridge_scan(dirrec,&name,&mode,NULL,NULL,NULL,&atime,&ctime,&mtime)==0) {
119 class = parse_class(mode,&type);
121 else {
122 name = NULL;
123 class = 0;
124 #endif
125 ctime = parse_date(&(dirrec->date_creation));
126 atime = ctime;
127 mtime = ctime;
128 #ifdef ISO9660_USE_ROCKRIDGE
130 #endif
131 if (name==NULL) name = parse_name((char*)dirrec->identifier,dirrec->identifier_length);
132 if (class==0) class = (dirrec->flags&ISO9660_DIRREC_DIR)?CDI_FS_CLASS_DIR:CDI_FS_CLASS_FILE;
134 struct iso9660_fs_res *new = iso9660_fs_res_create(name,parent,class,type);
135 if (voldesc!=NULL) new->voldesc = voldesc;
136 new->ctime = ctime;
137 new->atime = atime;
138 new->mtime = mtime;
139 new->data_sector = dirrec->data_sector;
140 new->data_size = dirrec->data_size;
142 free(name);
143 return new;
147 * Loads a directory
148 * @param res Resource to load as directory
149 * @return Directory list
151 cdi_list_t iso9660_dir_load(struct iso9660_fs_res *res) {
152 debug("iso9660_dir_load(0x%x(%s))\n",res,res->res.name);
153 struct iso9660_dirrec *dirrec;
154 size_t i = 0;
155 cdi_list_t dirlist = cdi_list_create();
156 size_t curpos = 0;
158 while (curpos<res->data_size) {
159 uint8_t size;
161 iso9660_read(res,curpos,1,&size);
162 if (size==0) curpos++;
163 else {
164 dirrec = malloc(size);
165 iso9660_read(res,curpos,size,dirrec);
166 if (i>1) cdi_list_push(dirlist,iso9660_dirrec_load(dirrec,res,NULL));
168 i++;
169 curpos += size;
173 return dirlist;
177 * CDI FS Call to read a directory
178 * @param stream CDI stream
179 * @return Directory list
181 cdi_list_t iso9660_fs_dir_list(struct cdi_fs_stream *stream) {
182 struct iso9660_fs_res *res = (struct iso9660_fs_res*)stream->res;
184 return res->res.children;