patch genisoimage multi extent
[platform/upstream/cdrkit.git] / genisoimage / stream.c
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 /* @(#)stream.c 1.3 04/03/04 Copyright 2002-2003 J. Schilling */
14 /* Parts from @(#)stream.c      1.9 07/02/17 Copyright 2002-2007 J. Schilling */
15 /*
16  *      ISO-9660 stream (pipe) file module for genisoimage
17  *
18  *      Copyright (c) 2002-2003 J. Schilling
19  *      Implemented after an idea from M.H. Voase
20  */
21 /*
22  * This program is free software; you can redistribute it and/or modify
23  * it under the terms of the GNU General Public License version 2
24  * as published by the Free Software Foundation.
25  *
26  * This program is distributed in the hope that it will be useful,
27  * but WITHOUT ANY WARRANTY; without even the implied warranty of
28  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
29  * GNU General Public License for more details.
30  *
31  * You should have received a copy of the GNU General Public License along with
32  * this program; see the file COPYING.  If not, write to the Free Software
33  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
34  */
35
36 #include <mconfig.h>
37 #include "genisoimage.h"
38 #include "iso9660.h"
39
40 static int      size_str_file(int starting_extent);
41 static int      size_str_dir(int starting_extent);
42 static int      size_str_path(int starting_extent);
43
44 static int      gen_str_path(void);
45
46 static int      write_str_file(FILE *outfile);
47 static int      write_str_dir(FILE *outfile);
48 static int      write_str_path(FILE *outfile);
49
50 extern struct directory *root;
51 extern unsigned int     session_start;
52 extern int              stream_media_size;
53 extern char             *stream_filename;
54 extern time_t           begun;
55 extern int              volume_sequence_number;
56
57 static unsigned int     avail_extent;
58 static unsigned int     stream_extent;
59 static unsigned int     stream_size;
60 static unsigned int     stream_pad;
61 static char             *l_path;
62 static char             *m_path;
63 static struct iso_directory_record s_dir;
64 static int              stream_finished = 0;
65
66 /*
67  * Compute the size of the file
68  */
69 static int
70 size_str_file(int starting_extent)
71 {
72         int     n;
73 extern  int     dopad;
74
75         stream_extent = last_extent;    /* Start of stream file content */
76
77         avail_extent = stream_media_size;
78         n = last_extent;                /* Room for FS blocks before file */
79         n += 1;                         /* Room for the directory block */
80         stream_pad = 0;
81         if (n < 50) {
82                 stream_pad = 50 - n;
83                 n = 50;                 /* Make net. size easy to compute */
84         }
85         if (dopad)
86                 n += 150;               /* Room for final padding */
87         avail_extent -= n;
88
89         last_extent += avail_extent + stream_pad;
90
91         return (0);
92 }
93
94 /*
95  * The size of the directory record - one sector
96  */
97 static int
98 size_str_dir(int starting_extent)
99 {
100         root->extent = last_extent;
101         last_extent += 1;
102         return (0);
103 }
104
105 /*
106  * The size of the path tables - two sectors
107  */
108 static int
109 size_str_path(int starting_extent)
110 {
111         path_table[0] = starting_extent;
112         path_table[1] = 0;
113         path_table[2] = path_table[0] + 1;
114         path_table[3] = 0;
115         last_extent += 2 * 1;
116         return (0);
117 }
118
119 /*
120  * Generate the path table data
121  */
122 static int
123 gen_str_path()
124 {
125         /*
126          * Basically add the root directory entry
127          */
128         l_path = (char *)e_malloc(SECTOR_SIZE);
129         m_path = (char *)e_malloc(SECTOR_SIZE);
130         memset(l_path, 0, SECTOR_SIZE);
131         memset(m_path, 0, SECTOR_SIZE);
132         l_path[0] = 1;
133         m_path[0] = 1;
134         set_731(l_path + 2, root->extent);
135         set_732(m_path + 2, root->extent);
136         set_721(l_path + 6, 1);
137         set_722(m_path + 6, 1);
138         l_path[8] = '\0'; l_path[9] = '\0';
139         m_path[8] = '\0'; m_path[9] = '\0';
140         return (0);
141 }
142
143 /*
144  * Write the file content
145  */
146 static int
147 write_str_file(FILE *outfile)
148 {
149         unsigned int    idx = 0;
150         unsigned int    iso_blocks;
151         int             count;
152         char            *buf;
153
154         buf = e_malloc(SECTOR_SIZE);
155         stream_size = 0;
156         while ((idx + SECTOR_SIZE) < (avail_extent * SECTOR_SIZE)) {
157                 memset(buf, 0, SECTOR_SIZE);
158                 count = fread(buf, 1, SECTOR_SIZE, stdin);
159                 if (count <= 0) {
160                         stream_finished = 1;
161                         break;
162                 }
163                 idx += count;
164                 jtwrite(buf, count, 1, 0, FALSE);
165                 xfwrite(buf, count, 1, outfile, 0, FALSE);
166         }
167
168         stream_size = idx;
169         iso_blocks = ISO_BLOCKS(idx);
170         memset(buf, 0, SECTOR_SIZE);
171         if (SECTOR_SIZE * iso_blocks - idx)
172     {
173                 jtwrite(buf, SECTOR_SIZE * iso_blocks - idx, 1, 0, FALSE);
174                 xfwrite(buf, SECTOR_SIZE * iso_blocks - idx, 1, outfile, 0, FALSE);
175     }
176         /*
177          * If we didn't fill the available area, pad to directory block
178          */
179         for (count = 0; count < (avail_extent - iso_blocks); count++)
180     {
181                 jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
182                 xfwrite(buf, SECTOR_SIZE, 1, outfile, 0, FALSE);
183     }
184         for (count = 0; count < stream_pad; count++)
185     {
186                 jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
187                 xfwrite(buf, SECTOR_SIZE, 1, outfile, 0, FALSE);
188     }
189
190         last_extent_written += avail_extent + stream_pad;
191         return (0);
192 }
193
194 /*
195  * Generate and write the directory record data
196  */
197 static int
198 write_str_dir(FILE *outfile)
199 {
200         int     to_write;
201         char    *buf;
202
203         buf = e_malloc(SECTOR_SIZE); memset(buf, 0, SECTOR_SIZE);
204         memset(&s_dir, 0, sizeof (struct iso_directory_record));
205         s_dir.length[0] = 34;                   /* BAD: Hardcoded - Will fix, MHV */
206         s_dir.ext_attr_length[0] = 0;
207         set_733((char *)s_dir.extent, root->extent);
208         set_733((char *)s_dir.size, SECTOR_SIZE);
209         iso9660_date(s_dir.date, begun);
210         s_dir.flags[0] = ISO_DIRECTORY;
211         s_dir.file_unit_size[0] = 0;
212         s_dir.interleave[0] = 0;
213         set_723((char *)s_dir.volume_sequence_number, volume_sequence_number);
214         s_dir.name_len[0] = 1;
215         s_dir.name[0] = 0;      /* "." */
216         jtwrite(&s_dir, offsetof(struct iso_directory_record, name[0]) + 1, 1, 0, FALSE);
217         xfwrite(&s_dir, offsetof(struct iso_directory_record, name[0]) + 1, 1, outfile, 0, FALSE);
218         s_dir.name[0] = 1;      /* ".." */
219         jtwrite(&s_dir, offsetof(struct iso_directory_record, name[0]) + 1, 1, 0, FALSE);
220         xfwrite(&s_dir, offsetof(struct iso_directory_record, name[0]) + 1, 1, outfile, 0, FALSE);
221         memset(&s_dir, 0, sizeof (struct iso_directory_record));
222         s_dir.length[0] = 34 + strlen(stream_filename);
223         s_dir.ext_attr_length[0] = 0;
224         set_733((char *) s_dir.extent, stream_extent);
225         set_733((char *) s_dir.size, stream_size);
226         iso9660_date(s_dir.date, begun);
227         s_dir.flags[0] = 0;
228         s_dir.file_unit_size[0] = 0;
229         set_723((char *)s_dir.volume_sequence_number, volume_sequence_number);
230         s_dir.name_len[0] = strlen(stream_filename);
231         memcpy(s_dir.name, stream_filename, s_dir.name_len[0]);
232         jtwrite(&s_dir, offsetof(struct iso_directory_record, name[0])
233                 + s_dir.name_len[0], 1, 0, FALSE);
234         xfwrite(&s_dir, offsetof(struct iso_directory_record, name[0])
235                 + s_dir.name_len[0], 1, outfile, 0, FALSE);
236
237         /*
238          * This calc is: 2 single char directory entries (34) + an additional entry
239          * with filename length stream_filename + round up for even lenght count
240          */
241         to_write = (s_dir.name_len[0] % 2) ? 0 : 1;
242         jtwrite(buf, SECTOR_SIZE - ((3 * 34) + s_dir.name_len[0]) +
243                 to_write, 1, 0, FALSE);
244         xfwrite(buf, SECTOR_SIZE - ((3 * 34) + s_dir.name_len[0]) +
245                 to_write, 1, outfile, 0, FALSE);
246         free(buf);
247         last_extent_written++;
248         return (0);
249 }
250
251 /*
252  * Generate the path table data
253  */
254 static int
255 write_str_path(FILE *outfile)
256 {
257         jtwrite(l_path, SECTOR_SIZE, 1, 0, FALSE);
258         xfwrite(l_path, SECTOR_SIZE, 1, outfile, 0, FALSE);
259         last_extent_written++;
260         jtwrite(m_path, SECTOR_SIZE, 1, 0, FALSE);
261         xfwrite(m_path, SECTOR_SIZE, 1, outfile, 0, FALSE);
262         last_extent_written++;
263         free(l_path);
264         free(m_path);
265         path_table_l = NULL;
266         path_table_m = NULL;
267         return (0);
268 }
269
270 struct output_fragment strfile_desc  = { NULL, size_str_file, NULL,        write_str_file, "Stream File" };
271 struct output_fragment strdir_desc  = { NULL, size_str_dir,  NULL,         write_str_dir,  "Stream File Directory"  };
272 struct output_fragment strpath_desc = { NULL, size_str_path, gen_str_path, write_str_path, "Stream File Path table" };