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)
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
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/>.
24 #include "cdi/lists.h"
25 #include "cdi/cache.h"
28 #include "directory_record.h"
29 #include "volume_descriptor.h"
30 #include "iso9660def.h"
32 #ifdef ISO9660_USE_ROCKRIDGE
33 #include "rockridge.h"
36 #include "iso9660_cdi.h"
38 #ifdef ISO9660_LOWER_FILENAMES
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
54 for (i
=0;i
<len
;i
++) name
[i
] = tolower(name
[i
]);
61 * Converts POSIX file mode to CDI class
62 * @param mode POSIX filemode
63 * @param special Reference for CDI special type
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
;
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
;
93 * Converts ISO9660 time to CDI time
94 * @param date ISO9660-Zeit
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
108 struct iso9660_fs_res
*iso9660_dirrec_load(struct iso9660_dirrec
*dirrec
,struct iso9660_fs_res
*parent
,struct iso9660_voldesc_prim
*voldesc
) {
113 cdi_fs_res_class_t
class = 0;
114 cdi_fs_res_type_t type
= 0;
116 #ifdef ISO9660_USE_ROCKRIDGE
118 if (iso9660_rockridge_scan(dirrec
,&name
,&mode
,NULL
,NULL
,NULL
,&atime
,&ctime
,&mtime
)==0) {
119 class = parse_class(mode
,&type
);
125 ctime
= parse_date(&(dirrec
->date_creation
));
128 #ifdef ISO9660_USE_ROCKRIDGE
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
;
139 new->data_sector
= dirrec
->data_sector
;
140 new->data_size
= dirrec
->data_size
;
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
;
155 cdi_list_t dirlist
= cdi_list_create();
158 while (curpos
<res
->data_size
) {
161 iso9660_read(res
,curpos
,1,&size
);
162 if (size
==0) curpos
++;
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
));
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
;