1 /*
2  * This file has been modified for the cdrkit suite.
3  *
4  * The behaviour and appearence of the program code below can differ to a major
5  * extent from the version distributed by the original author(s).
6  *
7  * For details, see Changelog file distributed with the cdrkit package. If you
8  * received this file from another source then ask the distributing person for
9  * a log of modifications.
10  *
11  */
12 
13 /* @(#)dvd_reader.c	1.3 04/03/04 joerg */
14 /*
15  * Copyright (C) 2001, 2002 Billy Biggs <vektor@dumbterm.net>,
16  *                          H�kan Hjort <d95hjort@dtek.chalmers.se>,
17  *                          Olaf Beck <olaf_sc@yahoo.com>
18  *			    (I only did the cut down no other contribs)
19  *			    J�rg Schilling <schilling@fokus.gmd.de>
20  *			    (making the code portable)
21  * This program is free software; you can redistribute it and/or modify
22  * it under the terms of the GNU General Public License as published by
23  * the Free Software Foundation; either version 2 of the License, or (at
24  * your option) any later version.
25  *
26  * This program is distributed in the hope that it will be useful, but
27  * WITHOUT ANY WARRANTY; without even the implied warranty of
28  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
29  * General Public License for more details.
30  *
31  * You should have received a copy of the GNU General Public License
32  * along with this program; if not, write to the Free Software
33  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
34  */
35 
36 /*
37  * NOTE: This is a cut down version of libdvdread for genisoimage, due
38  * to portability issues with the current libdvdread according to
39  * the maintainer of genisoimage.
40  * This cut down version only reads from a harddisk file structure
41  * and it only implements the functions necessary inorder to make
42  * genisoimage produce valid DVD-Video images.
43  * DON'T USE THIS LIBRARY IN ANY OTHER PROGRAM GET THE REAL
44  * LIBDVDREAD INSTEAD
45  */
46 #ifdef DVD_VIDEO
47 
48 #include "genisoimage.h"
49 #include <fctldefs.h>
50 #include <schily.h>
51 
52 #include "dvd_reader.h"
53 
54 struct dvd_file_s {
55 	/* Basic information. */
56 	dvd_reader_t	*dvd;
57 
58 	/* Calculated at open-time, size in blocks. */
59 	ssize_t		filesize;
60 };
61 
62 
63 void		DVDCloseFile(dvd_file_t *dvd_file);
64 static	dvd_file_t *DVDOpenFilePath(dvd_reader_t *dvd, char *filename);
65 static	dvd_file_t *DVDOpenVOBPath(dvd_reader_t *dvd, int title, int menu);
66 dvd_file_t *DVDOpenFile(dvd_reader_t *dvd, int titlenum,
67 								dvd_read_domain_t domain);
68 static	dvd_reader_t *DVDOpenPath(const char *path_root);
69 dvd_reader_t *DVDOpen(const char *path);
70 void		DVDClose(dvd_reader_t *dvd);
71 ssize_t		DVDFileSize(dvd_file_t *dvd_file);
72 
73 
74 /*
75  * Free a DVD file
76  */
77 void
DVDCloseFile(dvd_file_t * dvd_file)78 DVDCloseFile(dvd_file_t *dvd_file)
79 {
80 	free(dvd_file);
81 	dvd_file = 0;
82 }
83 
84 
85 /*
86  * Stat a IFO or BUP file from a DVD directory tree.
87  */
88 static dvd_file_t *
DVDOpenFilePath(dvd_reader_t * dvd,char * filename)89 DVDOpenFilePath(dvd_reader_t *dvd, char *filename)
90 {
91 
92 	char		full_path[PATH_MAX + 1];
93 	dvd_file_t	*dvd_file;
94 	struct stat	fileinfo;
95 
96 	/* Get the full path of the file. */
97 
98 	snprintf(full_path, sizeof (full_path),
99 				"%s/%s", dvd->path_root, filename);
100 
101 
102 	dvd_file = (dvd_file_t *) e_malloc(sizeof (dvd_file_t));
103 	if (!dvd_file)
104 		return (0);
105 	dvd_file->dvd = dvd;
106 	dvd_file->filesize = 0;
107 
108 	if (stat(full_path, &fileinfo) < 0) {
109 		free(dvd_file);
110 		return (0);
111 	}
112 	dvd_file->filesize = fileinfo.st_size / DVD_VIDEO_LB_LEN;
113 
114 	return (dvd_file);
115 }
116 
117 
118 /*
119  * Stat a VOB file from a DVD directory tree.
120  */
121 static dvd_file_t *
DVDOpenVOBPath(dvd_reader_t * dvd,int title,int menu)122 DVDOpenVOBPath(dvd_reader_t *dvd, int title, int menu)
123 {
124 
125 	char		filename[PATH_MAX + 1];
126 	struct stat	fileinfo;
127 	dvd_file_t	*dvd_file;
128 	int		i;
129 
130 	dvd_file = (dvd_file_t *) e_malloc(sizeof (dvd_file_t));
131 	if (!dvd_file)
132 		return (0);
133 	dvd_file->dvd = dvd;
134 	dvd_file->filesize = 0;
135 
136 	if (menu) {
137 		if (title == 0) {
138 			snprintf(filename, sizeof (filename),
139 				"%s/VIDEO_TS/VIDEO_TS.VOB", dvd->path_root);
140 		} else {
141 			snprintf(filename, sizeof (filename),
142 				"%s/VIDEO_TS/VTS_%02i_0.VOB", dvd->path_root, title);
143 		}
144 		if (stat(filename, &fileinfo) < 0) {
145 			free(dvd_file);
146 			return (0);
147 		}
148 		dvd_file->filesize = fileinfo.st_size / DVD_VIDEO_LB_LEN;
149 	} else {
150 		for (i = 0; i < 9; ++i) {
151 
152 			snprintf(filename, sizeof (filename),
153 				"%s/VIDEO_TS/VTS_%02i_%i.VOB", dvd->path_root, title, i + 1);
154 			if (stat(filename, &fileinfo) < 0) {
155 					break;
156 			}
157 
158 			dvd_file->filesize += fileinfo.st_size / DVD_VIDEO_LB_LEN;
159 		}
160 	}
161 
162 	return (dvd_file);
163 }
164 
165 /*
166  * Stat a DVD file from a DVD directory tree
167  */
168 EXPORT dvd_file_t *
DVDOpenFile(dvd_reader_t * dvd,int titlenum,dvd_read_domain_t domain)169 DVDOpenFile(dvd_reader_t *dvd, int titlenum, dvd_read_domain_t domain)
170 {
171 	char		filename[MAX_UDF_FILE_NAME_LEN];
172 
173 	switch (domain) {
174 
175 	case DVD_READ_INFO_FILE:
176 		if (titlenum == 0) {
177 			snprintf(filename, sizeof (filename),
178 					"/VIDEO_TS/VIDEO_TS.IFO");
179 		} else {
180 			snprintf(filename, sizeof (filename),
181 					"/VIDEO_TS/VTS_%02i_0.IFO", titlenum);
182 		}
183 		break;
184 
185 	case DVD_READ_INFO_BACKUP_FILE:
186 		if (titlenum == 0) {
187 			snprintf(filename, sizeof (filename),
188 					"/VIDEO_TS/VIDEO_TS.BUP");
189 		} else {
190 			snprintf(filename, sizeof (filename),
191 					"/VIDEO_TS/VTS_%02i_0.BUP", titlenum);
192 		}
193 		break;
194 
195 	case DVD_READ_MENU_VOBS:
196 		return (DVDOpenVOBPath(dvd, titlenum, 1));
197 
198 	case DVD_READ_TITLE_VOBS:
199 		if (titlenum == 0)
200 			return (0);
201 		return (DVDOpenVOBPath(dvd, titlenum, 0));
202 
203 	default:
204 #ifdef	USE_LIBSCHILY
205 		errmsgno(EX_BAD, "Invalid domain for file open.\n");
206 #else
207 		fprintf(stderr, "Invalid domain for file open.\n");
208 #endif
209 		return (0);
210 	}
211 	return (DVDOpenFilePath(dvd, filename));
212 }
213 
214 
215 
216 /*
217  * Stat a DVD directory structure
218  */
219 static dvd_reader_t *
DVDOpenPath(const char * path_root)220 DVDOpenPath(const char *path_root)
221 {
222 	dvd_reader_t	*dvd;
223 
224 	dvd = (dvd_reader_t *) e_malloc(sizeof (dvd_reader_t));
225 	if (!dvd)
226 		return (0);
227 	dvd->path_root = strdup(path_root);
228 
229 	return (dvd);
230 }
231 
232 
233 /*
234  * Stat a DVD structure - this one only works with directory structures
235  */
236 dvd_reader_t *
DVDOpen(const char * path)237 DVDOpen(const char *path)
238 {
239 	struct stat	fileinfo;
240 	int		ret;
241 
242 	if (!path)
243 		return (0);
244 
245 	ret = stat(path, &fileinfo);
246 	if (ret < 0) {
247 	/* If we can't stat the file, give up */
248 #ifdef	USE_LIBSCHILY
249 		errmsg("Can't stat %s\n", path);
250 #else
251 		fprintf(stderr, "Can't stat %s\n", path);
252 		perror("");
253 #endif
254 		return (0);
255 	}
256 
257 
258 	if (S_ISDIR(fileinfo.st_mode)) {
259 		return (DVDOpenPath(path));
260 	}
261 
262 	/* If it's none of the above, screw it. */
263 #ifdef	USE_LIBSCHILY
264 	errmsgno(EX_BAD, "Could not open %s\n", path);
265 #else
266 	fprintf(stderr, "Could not open %s\n", path);
267 #endif
268 	return (0);
269 }
270 
271 /*
272  * Free a DVD structure - this one will only close a directory tree
273  */
274 void
DVDClose(dvd_reader_t * dvd)275 DVDClose(dvd_reader_t *dvd)
276 {
277 	if (dvd) {
278 		if (dvd->path_root) free(dvd->path_root);
279 		free(dvd);
280 		dvd = 0;
281 	}
282 }
283 
284 
285 
286 /*
287  * Return the size of a DVD file
288  */
289 ssize_t
DVDFileSize(dvd_file_t * dvd_file)290 DVDFileSize(dvd_file_t *dvd_file)
291 {
292 	return (dvd_file->filesize);
293 }
294 
295 #endif /* DVD_VIDEO */
296