|
36 | 36 |
|
37 | 37 | #include "libudffs.h" |
38 | 38 | #include "options.h" |
| 39 | +#include "../udftune/updatedisc.h" |
39 | 40 | #include "../udfinfo/readdisc.h" |
40 | 41 |
|
41 | | -static uint64_t get_size(int fd) |
42 | | -{ |
43 | | - struct stat st; |
44 | | - uint64_t size; |
45 | | - off_t offset; |
46 | | - |
47 | | - if (fstat(fd, &st) == 0) |
48 | | - { |
49 | | - if (S_ISBLK(st.st_mode) && ioctl(fd, BLKGETSIZE64, &size) == 0) |
50 | | - return size; |
51 | | - else if (S_ISREG(st.st_mode)) |
52 | | - return st.st_size; |
53 | | - } |
54 | | - |
55 | | - offset = lseek(fd, 0, SEEK_END); |
56 | | - if (offset == (off_t)-1) |
57 | | - { |
58 | | - fprintf(stderr, "%s: Error: Cannot detect size of disk: %s\n", appname, strerror(errno)); |
59 | | - exit(1); |
60 | | - } |
61 | | - |
62 | | - if (lseek(fd, 0, SEEK_SET) != 0) |
63 | | - { |
64 | | - fprintf(stderr, "%s: Error: Cannot seek to start of disk: %s\n", appname, strerror(errno)); |
65 | | - exit(1); |
66 | | - } |
67 | | - |
68 | | - return offset; |
69 | | -} |
70 | | - |
71 | | -static int get_sector_size(int fd) |
72 | | -{ |
73 | | - int size; |
74 | | - |
75 | | - if (ioctl(fd, BLKSSZGET, &size) != 0) |
76 | | - return 0; |
77 | | - |
78 | | - if (size < 512 || size > 32768 || (size & (size - 1))) |
79 | | - { |
80 | | - fprintf(stderr, "%s: Warning: Disk logical sector size (%d) is not suitable for UDF\n", appname, size); |
81 | | - return 0; |
82 | | - } |
83 | | - |
84 | | - return size; |
85 | | -} |
86 | | - |
87 | | -static uint16_t compute_crc(void *desc, size_t length) |
88 | | -{ |
89 | | - return udf_crc((uint8_t *)desc + sizeof(tag), length - sizeof(tag), 0); |
90 | | -} |
91 | | - |
92 | | -static uint8_t compute_checksum(tag *tag) |
93 | | -{ |
94 | | - uint8_t i, checksum = 0; |
95 | | - for (i = 0; i < 16; i++) |
96 | | - { |
97 | | - if (i == 4) |
98 | | - continue; |
99 | | - checksum += ((uint8_t *)tag)[i]; |
100 | | - } |
101 | | - return checksum; |
102 | | -} |
103 | | - |
104 | | -static int check_desc(void *desc, size_t length) |
105 | | -{ |
106 | | - tag *tag = desc; |
107 | | - uint16_t crc_length = le16_to_cpu(tag->descCRCLength); |
108 | | - if (crc_length > length - sizeof(*tag)) |
109 | | - return 0; |
110 | | - if (compute_checksum(tag) != tag->tagChecksum) |
111 | | - return 0; |
112 | | - if (compute_crc(desc, sizeof(*tag) + crc_length) != le16_to_cpu(tag->descCRC)) |
113 | | - return 0; |
114 | | - return 1; |
115 | | -} |
116 | | - |
117 | | -static void update_desc(void *desc, size_t length) |
118 | | -{ |
119 | | - tag *tag = desc; |
120 | | - if (length > le16_to_cpu(tag->descCRCLength) + sizeof(*tag)) |
121 | | - length = le16_to_cpu(tag->descCRCLength) + sizeof(*tag); |
122 | | - tag->descCRC = cpu_to_le16(compute_crc(desc, length)); |
123 | | - tag->tagChecksum = compute_checksum(tag); |
124 | | -} |
125 | | - |
126 | | -static void write_desc(int fd, struct udf_disc *disc, enum udf_space_type type, uint16_t ident, void *buffer) |
127 | | -{ |
128 | | - struct udf_extent *ext; |
129 | | - struct udf_desc *desc; |
130 | | - off_t off; |
131 | | - off_t offset; |
132 | | - ssize_t ret; |
133 | | - |
134 | | - ext = disc->head; |
135 | | - while ((ext = next_extent(ext, type))) |
136 | | - { |
137 | | - desc = ext->head; |
138 | | - while ((desc = next_desc(desc, ident))) |
139 | | - { |
140 | | - if (!desc->data || desc->data->buffer != buffer) |
141 | | - continue; |
142 | | - |
143 | | - printf(" ... at block %"PRIu32"\n", ext->start + desc->offset); |
144 | | - |
145 | | - offset = (off_t)disc->blocksize * (ext->start + desc->offset); |
146 | | - off = lseek(fd, offset, SEEK_SET); |
147 | | - if (off != (off_t)-1 && off != offset) |
148 | | - { |
149 | | - errno = EIO; |
150 | | - off = (off_t)-1; |
151 | | - } |
152 | | - if (off == (off_t)-1) |
153 | | - { |
154 | | - fprintf(stderr, "%s: Error: lseek failed: %s\n", appname, strerror(errno)); |
155 | | - return; |
156 | | - } |
157 | | - |
158 | | - if (!(disc->flags & FLAG_NO_WRITE)) |
159 | | - { |
160 | | - ret = write_nointr(fd, desc->data->buffer, desc->data->length); |
161 | | - if (ret >= 0 && (size_t)ret != desc->data->length) |
162 | | - { |
163 | | - errno = EIO; |
164 | | - ret = -1; |
165 | | - } |
166 | | - if (ret < 0) |
167 | | - { |
168 | | - fprintf(stderr, "%s: Error: write failed: %s\n", appname, strerror(errno)); |
169 | | - return; |
170 | | - } |
171 | | - } |
172 | | - |
173 | | - return; |
174 | | - } |
175 | | - } |
176 | | - |
177 | | - fprintf(stderr, "%s: Error: Cannot find needed block for write\n", appname); |
178 | | - return; |
179 | | -} |
180 | | - |
181 | 42 | int main(int argc, char *argv[]) |
182 | 43 | { |
183 | 44 | struct udf_disc disc; |
|
0 commit comments