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/>.
23 #include "cdi/lists.h"
24 #include "cdi/cache.h"
27 #include "directory_record.h"
28 #include "volume_descriptor.h"
29 #include "iso9660def.h"
31 #ifdef ISO9660_USE_ROCKRIDGE
32 #include "rockridge.h"
35 #include "iso9660_cdi.h"
37 #ifdef ISO9660_LOWER_FILENAMES
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
53 for (i
=0;i
<len
;i
++) name
[i
] = tolower(name
[i
]);
60 * Converts POSIX file mode to CDI class
61 * @param mode POSIX filemode
62 * @param special Reference for CDI special type
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
;
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
;
92 * Converts ISO9660 time to CDI time
93 * @param date ISO9660-Zeit
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
107 struct iso9660_fs_res
*iso9660_dirrec_load(struct iso9660_dirrec
*dirrec
,struct iso9660_fs_res
*parent
,struct iso9660_voldesc_prim
*voldesc
) {
112 cdi_fs_res_class_t
class = 0;
113 cdi_fs_res_type_t type
= 0;
115 #ifdef ISO9660_USE_ROCKRIDGE
117 if (iso9660_rockridge_scan(dirrec
,&name
,&mode
,NULL
,NULL
,NULL
,&atime
,&ctime
,&mtime
)==0) {
118 class = parse_class(mode
,&type
);
124 ctime
= parse_date(&(dirrec
->date_creation
));
127 #ifdef ISO9660_USE_ROCKRIDGE
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
;
138 new->data_sector
= dirrec
->data_sector
;
139 new->data_size
= dirrec
->data_size
;
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
;
154 cdi_list_t dirlist
= cdi_list_create();
157 while (curpos
<res
->data_size
) {
160 iso9660_read(res
,curpos
,1,&size
);
161 if (size
==0) curpos
++;
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
));
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
;