iso9660: new license LGPL
[meinos.git] / apps / iso9660 / dir.c
blob1b19d9e367c52b80ca5cf1ea91feb0936bb63ede
1 /*
2 iso9660 - An iso9660 CDI driver with Rockridge support
3 Copyright (C) 2008 Janosch Gräf <janosch.graef@gmx.net>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <stddef.h>
20 #include <stdlib.h>
22 #include "cdi/fs.h"
23 #include "cdi/lists.h"
24 #include "cdi/cache.h"
25 #include "cdi/misc.h"
27 #include "directory_record.h"
28 #include "volume_descriptor.h"
29 #include "iso9660def.h"
31 #ifdef ISO9660_USE_ROCKRIDGE
32 #include "rockridge.h"
33 #endif
35 #include "iso9660_cdi.h"
37 #ifdef ISO9660_LOWER_FILENAMES
38 #include <ctype.h>
39 #endif
41 /**
42 * Convert ISO9660 identifier to file name
43 * @param ident Identifier
44 * @param len Length of identifier
45 * @return Name (should be passed to free())
47 static char *parse_name(char *ident,size_t len) {
48 if (ident[len-2]==';') len -= 2;
49 if (ident[len-1]=='.') len--;
50 char *name = memcpy(malloc(len+1),ident,len);
51 #ifdef ISO9660_LOWER_FILENAMES
52 size_t i;
53 for (i=0;i<len;i++) name[i] = tolower(name[i]);
54 #endif
55 name[len] = 0;
56 return name;
59 /**
60 * Converts POSIX file mode to CDI class
61 * @param mode POSIX filemode
62 * @param special Reference for CDI special type
63 * @return CDI class
65 #ifdef ISO9660_USE_ROCKRIDGE
66 static cdi_fs_res_class_t parse_class(rmode_t mode,cdi_fs_res_type_t *special) {
67 cdi_fs_res_class_t class = CDI_FS_CLASS_FILE;
68 if (RS_ISBLK(mode)) {
69 class = CDI_FS_CLASS_SPECIAL;
70 if (special!=NULL) *special = CDI_FS_BLOCK;
72 else if (RS_ISCHR(mode)) {
73 class = CDI_FS_CLASS_SPECIAL;
74 if (special!=NULL) *special = CDI_FS_BLOCK;
76 else if (RS_ISFIFO(mode)) {
77 class = CDI_FS_CLASS_SPECIAL;
78 if (special!=NULL) *special = CDI_FS_FIFO;
80 else if (RS_ISSOCK(mode)) {
81 class = CDI_FS_CLASS_SPECIAL;
82 if (special!=NULL) *special = CDI_FS_SOCKET;
84 else if (RS_ISREG(mode)) class = CDI_FS_CLASS_FILE;
85 else if (RS_ISDIR(mode)) class = CDI_FS_CLASS_DIR;
86 else if (RS_ISLNK(mode)) class = CDI_FS_CLASS_LINK;
87 return class;
89 #endif
91 /**
92 * Converts ISO9660 time to CDI time
93 * @param date ISO9660-Zeit
94 * @return CDI time
96 static inline uint64_t parse_date(struct iso9660_dirrec_date *date) {
97 return cdi_time_by_date(date->year,date->month-1,date->day)+cdi_time_offset(date->hour,date->minute,date->second);
101 * Loads a ISO9660 directory entry
102 * @param dirrec Directory entry
103 * @param parent Parent resource
104 * @param voldesc Volume descriptor
105 * @return Resource
107 struct iso9660_fs_res *iso9660_dirrec_load(struct iso9660_dirrec *dirrec,struct iso9660_fs_res *parent,struct iso9660_voldesc_prim *voldesc) {
108 char *name = NULL;
109 uint64_t ctime = 0;
110 uint64_t atime = 0;
111 uint64_t mtime = 0;
112 cdi_fs_res_class_t class = 0;
113 cdi_fs_res_type_t type = 0;
115 #ifdef ISO9660_USE_ROCKRIDGE
116 rmode_t mode;
117 if (iso9660_rockridge_scan(dirrec,&name,&mode,NULL,NULL,NULL,&atime,&ctime,&mtime)==0) {
118 class = parse_class(mode,&type);
120 else {
121 name = NULL;
122 class = 0;
123 #endif
124 ctime = parse_date(&(dirrec->date_creation));
125 atime = ctime;
126 mtime = ctime;
127 #ifdef ISO9660_USE_ROCKRIDGE
129 #endif
130 if (name==NULL) name = parse_name((char*)dirrec->identifier,dirrec->identifier_length);
131 if (class==0) class = (dirrec->flags&ISO9660_DIRREC_DIR)?CDI_FS_CLASS_DIR:CDI_FS_CLASS_FILE;
133 struct iso9660_fs_res *new = iso9660_fs_res_create(name,parent,class,type);
134 if (voldesc!=NULL) new->voldesc = voldesc;
135 new->ctime = ctime;
136 new->atime = atime;
137 new->mtime = mtime;
138 new->data_sector = dirrec->data_sector;
139 new->data_size = dirrec->data_size;
141 free(name);
142 return new;
146 * Loads a directory
147 * @param res Resource to load as directory
148 * @return Directory list
150 cdi_list_t iso9660_dir_load(struct iso9660_fs_res *res) {
151 debug("iso9660_dir_load(0x%x(%s))\n",res,res->res.name);
152 struct iso9660_dirrec *dirrec;
153 size_t i = 0;
154 cdi_list_t dirlist = cdi_list_create();
155 size_t curpos = 0;
157 while (curpos<res->data_size) {
158 uint8_t size;
160 iso9660_read(res,curpos,1,&size);
161 if (size==0) curpos++;
162 else {
163 dirrec = malloc(size);
164 iso9660_read(res,curpos,size,dirrec);
165 if (i>1) cdi_list_push(dirlist,iso9660_dirrec_load(dirrec,res,NULL));
167 i++;
168 curpos += size;
172 return dirlist;
176 * CDI FS Call to read a directory
177 * @param stream CDI stream
178 * @return Directory list
180 cdi_list_t iso9660_fs_dir_list(struct cdi_fs_stream *stream) {
181 struct iso9660_fs_res *res = (struct iso9660_fs_res*)stream->res;
183 return res->res.children;