udftools

- Main Page
- Classes
- Files

- File List
- File Members

All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
main.c
Go to the documentation of this file.
1 /*
2 * main.c
3 *
4 * Copyright (c) 2001-2002 Ben Fennema <bfennema@falcon.csc.calpoly.edu>
5 * Copyright (c) 2014 Pali Rohár <pali.rohar@gmail.com>
6 * All rights reserved.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 *
22 */
23
29 #include "config.h"
30
31 #include <malloc.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <fcntl.h>
37 #include <unistd.h>
38 #include <time.h>
39 #include <sys/time.h>
40 #include <errno.h>
41 #include <limits.h>
42 #include <sys/ioctl.h>
43 #include <linux/fs.h>
44 #include <linux/fd.h>
45
46 #include "mkudffs.h"
47 #include "defaults.h"
48 #include "options.h"
49
50 static int valid_offset(int fd, off_t offset)
51 {
52 char ch;
53
54 if (lseek(fd, offset, SEEK_SET) < 0)
55 return 0;
56 if (read(fd, &ch, 1) < 1)
57 return 0;
58 return 1;
59 }
60
61 uint32_t get_blocks(int fd, int blocksize, uint32_t opt_blocks)
62 {
63 uint64_t blocks;
64 #ifdef BLKGETSIZE64
65 uint64_t size64;
66 #endif
67 #ifdef BLKGETSIZE
68 long size;
69 #endif
70 #ifdef FDGETPRM
71 struct floppy_struct this_floppy;
72 #endif
73 struct stat buf;
74
75 if (opt_blocks)
76 return opt_blocks;
77
78 #ifdef BLKGETSIZE64
79 if (ioctl(fd, BLKGETSIZE64, &size64) >= 0)
80 blocks = size64 / blocksize;
81 else
82 #endif
83 #ifdef BLKGETSIZE
84 if (ioctl(fd, BLKGETSIZE, &size) >= 0)
85 blocks = size / (blocksize / 512);
86 else
87 #endif
88 #ifdef FDGETPRM
89 if (ioctl(fd, FDGETPRM, &this_floppy) >= 0)
90 blocks = this_floppy.size / (blocksize / 512);
91 else
92 #endif
93 if (fstat(fd, &buf) == 0 && S_ISREG(buf.st_mode))
94 blocks = buf.st_size / blocksize;
95 else
96 {
97 off_t high, low;
98
99 for (low=0, high = 1024; valid_offset(fd, high); high *= 2)
100 low = high;
101 while (low < high - 1)
102 {
103 const off_t mid = (low + high) / 2;
104
105 if (valid_offset(fd, mid))
106 low = mid;
107 else
108 high = mid;
109 }
110
111 valid_offset(fd, 0);
112 blocks = (low + 1) / blocksize;
113 }
114
115 if (blocks > UINT32_MAX)
116 {
117 fprintf(stderr, "mkudffs: Warning: Disk is too big, using only %lu blocks\n", (unsigned long int)UINT32_MAX);
118 return UINT32_MAX;
119 }
120
121 return blocks;
122 }
123
124 void detect_blocksize(int fd, struct udf_disc *disc)
125 {
126 int size;
127 uint16_t bs;
128
129 #ifdef BLKSSZGET
130 if (ioctl(fd, BLKSSZGET, &size) != 0)
131 return;
132
133 disc->blocksize = size;
134 for (bs=512,disc->blocksize_bits=9; disc->blocksize_bits<13; disc->blocksize_bits++,bs<<=1)
135 {
136 if (disc->blocksize == bs)
137 break;
138 }
139 if (disc->blocksize_bits == 13)
140 {
141 disc->blocksize = 2048;
142 disc->blocksize_bits = 11;
143 }
144 disc->udf_lvd[0]->logicalBlockSize = cpu_to_le32(disc->blocksize);
145 #endif
146 }
147
148 int write_func(struct udf_disc *disc, struct udf_extent *ext)
149 {
150 static char *buffer = NULL;
151 static size_t bufferlen = 0;
152 int fd = *(int *)disc->write_data;
153 ssize_t length, offset;
154 struct udf_desc *desc;
155 struct udf_data *data;
156
157 if (buffer == NULL)
158 {
159 bufferlen = disc->blocksize;
160 buffer = calloc(bufferlen, 1);
161 }
162
163 if (!(ext->space_type & (USPACE|RESERVED)))
164 {
165 desc = ext->head;
166 while (desc != NULL)
167 {
168 if (lseek(fd, (off_t)(ext->start + desc->offset) << disc->blocksize_bits, SEEK_SET) < 0)
169 return -1;
170 data = desc->data;
171 offset = 0;
172 while (data != NULL)
173 {
174 if (data->length + offset > bufferlen)
175 {
176 bufferlen = (data->length + offset + disc->blocksize - 1) & ~(disc->blocksize - 1);
177 buffer = realloc(buffer, bufferlen);
178 }
179 memcpy(buffer + offset, data->buffer, data->length);
180 offset += data->length;
181 data = data->next;
182 }
183 length = (offset + disc->blocksize - 1) & ~(disc->blocksize - 1);
184 if (offset != length)
185 memset(buffer + offset, 0x00, length - offset);
186 if (write(fd, buffer, length) != length)
187 return -1;
188 desc = desc->next;
189 }
190 }
191 return 0;
192 }
193
194 int main(int argc, char *argv[])
195 {
196 struct udf_disc disc;
197 char filename[NAME_MAX];
198 char buf[128*3];
199 int fd;
200 int blocksize = -1;
201 int len;
202
203 udf_init_disc(&disc);
204 parse_args(argc, argv, &disc, filename, &blocksize);
205 fd = open(filename, O_RDWR | O_CREAT, 0660);
206 if (fd == -1) {
207 fprintf(stderr, "mkudffs: Error: Cannot open device '%s': %s\n", filename, strerror(errno));
208 exit(1);
209 }
210
211 if (blocksize == -1)
212 detect_blocksize(fd, &disc);
213
214 disc.head->blocks = get_blocks(fd, disc.blocksize, disc.head->blocks);
215 disc.write = write_func;
216 disc.write_data = &fd;
217
218 printf("filename=%s\n", filename);
219
220 memset(buf, 0, sizeof(buf));
221 len = decode_utf8(disc.udf_lvd[0]->logicalVolIdent, buf, 128);
222 buf[len] = 0;
223 printf("label=%s\n", buf);
224
225 memset(buf, 0, sizeof(buf));
226 len = decode_utf8(disc.udf_pvd[0]->volSetIdent, buf, 128);
227 buf[len] = 0;
228 printf("uuid=%.16s\n", buf);
229
230 printf("blocksize=%u\n", (unsigned int)disc.blocksize);
231 printf("blocks=%lu\n", (unsigned long int)disc.head->blocks);
232 printf("udfrev=%x\n", (unsigned int)disc.udf_rev);
233
234 if (((disc.flags & FLAG_BRIDGE) && disc.head->blocks < 513) || disc.head->blocks < 281)
235 {
236 fprintf(stderr, "mkudffs: Error: Not enough blocks on device '%s', try decreasing blocksize\n", filename);
237 exit(1);
238 }
239
240 split_space(&disc);
241
242 setup_vrs(&disc);
243 setup_anchor(&disc);
244 setup_partition(&disc);
245 setup_vds(&disc);
246
247 dump_space(&disc);
248
249 if (write_disc(&disc) < 0) {
250 fprintf(stderr, "mkudffs: Error: Cannot write to device '%s': %s\n", filename, strerror(errno));
251 return 1;
252 }
253
254 return 0;
255 }
udf_disc::write_data
void * write_data
Definition: libudffs.h:108
udf_extent::blocks
uint32_t blocks
Definition: libudffs.h:135
FLAG_BRIDGE
#define FLAG_BRIDGE
Definition: libudffs.h:53
cpu_to_le32
#define cpu_to_le32(x)
Definition: bswap.h:247
udf_disc::blocksize
uint16_t blocksize
Definition: libudffs.h:98
main
int main(int argc, char *argv[])
Definition: main.c:237
logicalVolDesc::logicalBlockSize
uint32_t logicalBlockSize
Definition: ecma_167.h:302
USPACE
Definition: libudffs.h:72
NAME_MAX
#define NAME_MAX
Definition: cdrwtool.h:57
setup_vrs
void setup_vrs(struct udf_disc *disc)
Definition: mkudffs.c:367
mkudffs.h
valid_offset
static int valid_offset(int fd, off_t offset)
Definition: main.c:50
decode_utf8
size_t decode_utf8(dstring *, char *, size_t)
Definition: unicode.c:32
udf_disc::udf_pvd
struct primaryVolDesc * udf_pvd[2]
Definition: libudffs.h:112
options.h
udf_disc::head
struct udf_extent * head
Definition: libudffs.h:127
RESERVED
Definition: libudffs.h:63
setup_partition
void setup_partition(struct udf_disc *disc)
Definition: mkudffs.c:449
cdrw_disc::offset
unsigned long offset
Definition: cdrwtool.h:77
udf_desc::data
struct udf_data * data
Definition: libudffs.h:149
dump_space
void dump_space(struct udf_disc *disc)
Definition: mkudffs.c:331
udf_init_disc
void udf_init_disc(struct udf_disc *disc)
Definition: mkudffs.c:46
primaryVolDesc::volSetIdent
dstring volSetIdent[128]
Definition: ecma_167.h:215
write_disc
int write_disc(struct udf_disc *disc)
Definition: mkudffs.c:351
udf_data
Definition: libudffs.h:155
split_space
void split_space(struct udf_disc *disc)
Definition: mkudffs.c:198
setup_anchor
void setup_anchor(struct udf_disc *disc)
Definition: mkudffs.c:402
udf_extent
Definition: libudffs.h:131
udf_extent::start
uint32_t start
Definition: libudffs.h:134
detect_blocksize
void detect_blocksize(int fd, struct udf_disc *disc)
Definition: main.c:124
logicalVolDesc::logicalVolIdent
dstring logicalVolIdent[128]
Definition: ecma_167.h:301
udf_disc::flags
uint32_t flags
Definition: libudffs.h:100
parse_args
void parse_args(int argc, char *argv[], struct cdrw_disc *disc, char *device)
Definition: options.c:69
udf_desc
Definition: libudffs.h:144
udf_disc
Definition: libudffs.h:95
udf_extent::head
struct udf_desc * head
Definition: libudffs.h:137
get_blocks
uint32_t get_blocks(int fd, int blocksize, uint32_t opt_blocks)
Definition: main.c:61
write_func
int write_func(struct udf_disc *disc, struct udf_extent *ext)
Definition: main.c:42
udf_disc::blocksize_bits
uint8_t blocksize_bits
Definition: libudffs.h:99
udf_disc::udf_rev
uint16_t udf_rev
Definition: libudffs.h:97
setup_vds
void setup_vds(struct udf_disc *disc)
Definition: mkudffs.c:758
udf_disc::write
int(* write)(struct udf_disc *, struct udf_extent *)
Definition: libudffs.h:107
udf_extent::space_type
enum udf_space_type space_type
Definition: libudffs.h:133
udf_disc::udf_lvd
struct logicalVolDesc * udf_lvd[2]
Definition: libudffs.h:113
defaults.h