1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define _FILE_OFFSET_BITS 64
18 #define _LARGEFILE64_SOURCE 1
19 
20 #include <algorithm>
21 #include <fcntl.h>
22 #include <inttypes.h>
23 #include <limits.h>
24 #include <stdbool.h>
25 #include <stddef.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30 #include <unistd.h>
31 #include <zlib.h>
32 
33 #include "defs.h"
34 #include "output_file.h"
35 #include "sparse_crc32.h"
36 #include "sparse_format.h"
37 
38 #include <android-base/mapped_file.h>
39 
40 #ifndef _WIN32
41 #define O_BINARY 0
42 #else
43 #define ftruncate64 ftruncate
44 #endif
45 
46 #if defined(__APPLE__) && defined(__MACH__)
47 #define lseek64 lseek
48 #define ftruncate64 ftruncate
49 #define off64_t off_t
50 #endif
51 
52 #define SPARSE_HEADER_MAJOR_VER 1
53 #define SPARSE_HEADER_MINOR_VER 0
54 #define SPARSE_HEADER_LEN (sizeof(sparse_header_t))
55 #define CHUNK_HEADER_LEN (sizeof(chunk_header_t))
56 
57 #define container_of(inner, outer_t, elem) ((outer_t*)((char*)(inner)-offsetof(outer_t, elem)))
58 
59 struct output_file_ops {
60   int (*open)(struct output_file*, int fd);
61   int (*skip)(struct output_file*, int64_t);
62   int (*pad)(struct output_file*, int64_t);
63   int (*write)(struct output_file*, void*, size_t);
64   void (*close)(struct output_file*);
65 };
66 
67 struct sparse_file_ops {
68   int (*write_data_chunk)(struct output_file* out, unsigned int len, void* data);
69   int (*write_fill_chunk)(struct output_file* out, unsigned int len, uint32_t fill_val);
70   int (*write_skip_chunk)(struct output_file* out, int64_t len);
71   int (*write_end_chunk)(struct output_file* out);
72 };
73 
74 struct output_file {
75   int64_t cur_out_ptr;
76   unsigned int chunk_cnt;
77   uint32_t crc32;
78   struct output_file_ops* ops;
79   struct sparse_file_ops* sparse_ops;
80   int use_crc;
81   unsigned int block_size;
82   int64_t len;
83   char* zero_buf;
84   uint32_t* fill_buf;
85   char* buf;
86 };
87 
88 struct output_file_gz {
89   struct output_file out;
90   gzFile gz_fd;
91 };
92 
93 #define to_output_file_gz(_o) container_of((_o), struct output_file_gz, out)
94 
95 struct output_file_normal {
96   struct output_file out;
97   int fd;
98 };
99 
100 #define to_output_file_normal(_o) container_of((_o), struct output_file_normal, out)
101 
102 struct output_file_callback {
103   struct output_file out;
104   void* priv;
105   int (*write)(void* priv, const void* buf, size_t len);
106 };
107 
108 #define to_output_file_callback(_o) container_of((_o), struct output_file_callback, out)
109 
file_open(struct output_file * out,int fd)110 static int file_open(struct output_file* out, int fd) {
111   struct output_file_normal* outn = to_output_file_normal(out);
112 
113   outn->fd = fd;
114   return 0;
115 }
116 
file_skip(struct output_file * out,int64_t cnt)117 static int file_skip(struct output_file* out, int64_t cnt) {
118   off64_t ret;
119   struct output_file_normal* outn = to_output_file_normal(out);
120 
121   ret = lseek64(outn->fd, cnt, SEEK_CUR);
122   if (ret < 0) {
123     error_errno("lseek64");
124     return -1;
125   }
126   return 0;
127 }
128 
file_pad(struct output_file * out,int64_t len)129 static int file_pad(struct output_file* out, int64_t len) {
130   int ret;
131   struct output_file_normal* outn = to_output_file_normal(out);
132 
133   ret = ftruncate64(outn->fd, len);
134   if (ret < 0) {
135     return -errno;
136   }
137 
138   return 0;
139 }
140 
file_write(struct output_file * out,void * data,size_t len)141 static int file_write(struct output_file* out, void* data, size_t len) {
142   ssize_t ret;
143   struct output_file_normal* outn = to_output_file_normal(out);
144 
145   while (len > 0) {
146     ret = write(outn->fd, data, len);
147     if (ret < 0) {
148       if (errno == EINTR) {
149         continue;
150       }
151       error_errno("write");
152       return -1;
153     }
154 
155     data = (char*)data + ret;
156     len -= ret;
157   }
158 
159   return 0;
160 }
161 
file_close(struct output_file * out)162 static void file_close(struct output_file* out) {
163   struct output_file_normal* outn = to_output_file_normal(out);
164 
165   free(outn);
166 }
167 
168 static struct output_file_ops file_ops = {
169     .open = file_open,
170     .skip = file_skip,
171     .pad = file_pad,
172     .write = file_write,
173     .close = file_close,
174 };
175 
gz_file_open(struct output_file * out,int fd)176 static int gz_file_open(struct output_file* out, int fd) {
177   struct output_file_gz* outgz = to_output_file_gz(out);
178 
179   outgz->gz_fd = gzdopen(fd, "wb9");
180   if (!outgz->gz_fd) {
181     error_errno("gzopen");
182     return -errno;
183   }
184 
185   return 0;
186 }
187 
gz_file_skip(struct output_file * out,int64_t cnt)188 static int gz_file_skip(struct output_file* out, int64_t cnt) {
189   off64_t ret;
190   struct output_file_gz* outgz = to_output_file_gz(out);
191 
192   ret = gzseek(outgz->gz_fd, cnt, SEEK_CUR);
193   if (ret < 0) {
194     error_errno("gzseek");
195     return -1;
196   }
197   return 0;
198 }
199 
gz_file_pad(struct output_file * out,int64_t len)200 static int gz_file_pad(struct output_file* out, int64_t len) {
201   off64_t ret;
202   struct output_file_gz* outgz = to_output_file_gz(out);
203 
204   ret = gztell(outgz->gz_fd);
205   if (ret < 0) {
206     return -1;
207   }
208 
209   if (ret >= len) {
210     return 0;
211   }
212 
213   ret = gzseek(outgz->gz_fd, len - 1, SEEK_SET);
214   if (ret < 0) {
215     return -1;
216   }
217 
218   gzwrite(outgz->gz_fd, "", 1);
219 
220   return 0;
221 }
222 
gz_file_write(struct output_file * out,void * data,size_t len)223 static int gz_file_write(struct output_file* out, void* data, size_t len) {
224   int ret;
225   struct output_file_gz* outgz = to_output_file_gz(out);
226 
227   while (len > 0) {
228     ret = gzwrite(outgz->gz_fd, data, std::min<unsigned int>(len, (unsigned int)INT_MAX));
229     if (ret == 0) {
230       error("gzwrite %s", gzerror(outgz->gz_fd, nullptr));
231       return -1;
232     }
233     len -= ret;
234     data = (char*)data + ret;
235   }
236 
237   return 0;
238 }
239 
gz_file_close(struct output_file * out)240 static void gz_file_close(struct output_file* out) {
241   struct output_file_gz* outgz = to_output_file_gz(out);
242 
243   gzclose(outgz->gz_fd);
244   free(outgz);
245 }
246 
247 static struct output_file_ops gz_file_ops = {
248     .open = gz_file_open,
249     .skip = gz_file_skip,
250     .pad = gz_file_pad,
251     .write = gz_file_write,
252     .close = gz_file_close,
253 };
254 
callback_file_open(struct output_file * out __unused,int fd __unused)255 static int callback_file_open(struct output_file* out __unused, int fd __unused) {
256   return 0;
257 }
258 
callback_file_skip(struct output_file * out,int64_t off)259 static int callback_file_skip(struct output_file* out, int64_t off) {
260   struct output_file_callback* outc = to_output_file_callback(out);
261   int to_write;
262   int ret;
263 
264   while (off > 0) {
265     to_write = std::min(off, (int64_t)INT_MAX);
266     ret = outc->write(outc->priv, nullptr, to_write);
267     if (ret < 0) {
268       return ret;
269     }
270     off -= to_write;
271   }
272 
273   return 0;
274 }
275 
callback_file_pad(struct output_file * out __unused,int64_t len __unused)276 static int callback_file_pad(struct output_file* out __unused, int64_t len __unused) {
277   return -1;
278 }
279 
callback_file_write(struct output_file * out,void * data,size_t len)280 static int callback_file_write(struct output_file* out, void* data, size_t len) {
281   struct output_file_callback* outc = to_output_file_callback(out);
282 
283   return outc->write(outc->priv, data, len);
284 }
285 
callback_file_close(struct output_file * out)286 static void callback_file_close(struct output_file* out) {
287   struct output_file_callback* outc = to_output_file_callback(out);
288 
289   free(outc);
290 }
291 
292 static struct output_file_ops callback_file_ops = {
293     .open = callback_file_open,
294     .skip = callback_file_skip,
295     .pad = callback_file_pad,
296     .write = callback_file_write,
297     .close = callback_file_close,
298 };
299 
read_all(int fd,void * buf,size_t len)300 int read_all(int fd, void* buf, size_t len) {
301   size_t total = 0;
302   int ret;
303   char* ptr = reinterpret_cast<char*>(buf);
304 
305   while (total < len) {
306     ret = read(fd, ptr, len - total);
307 
308     if (ret < 0) return -errno;
309 
310     if (ret == 0) return -EINVAL;
311 
312     ptr += ret;
313     total += ret;
314   }
315 
316   return 0;
317 }
318 
write_sparse_skip_chunk(struct output_file * out,int64_t skip_len)319 static int write_sparse_skip_chunk(struct output_file* out, int64_t skip_len) {
320   chunk_header_t chunk_header;
321   int ret;
322 
323   if (skip_len % out->block_size) {
324     error("don't care size %" PRIi64 " is not a multiple of the block size %u", skip_len,
325           out->block_size);
326     return -1;
327   }
328 
329   /* We are skipping data, so emit a don't care chunk. */
330   chunk_header.chunk_type = CHUNK_TYPE_DONT_CARE;
331   chunk_header.reserved1 = 0;
332   chunk_header.chunk_sz = skip_len / out->block_size;
333   chunk_header.total_sz = CHUNK_HEADER_LEN;
334   ret = out->ops->write(out, &chunk_header, sizeof(chunk_header));
335   if (ret < 0) return -1;
336 
337   out->cur_out_ptr += skip_len;
338   out->chunk_cnt++;
339 
340   return 0;
341 }
342 
write_sparse_fill_chunk(struct output_file * out,unsigned int len,uint32_t fill_val)343 static int write_sparse_fill_chunk(struct output_file* out, unsigned int len, uint32_t fill_val) {
344   chunk_header_t chunk_header;
345   int rnd_up_len, count;
346   int ret;
347 
348   /* Round up the fill length to a multiple of the block size */
349   rnd_up_len = ALIGN(len, out->block_size);
350 
351   /* Finally we can safely emit a chunk of data */
352   chunk_header.chunk_type = CHUNK_TYPE_FILL;
353   chunk_header.reserved1 = 0;
354   chunk_header.chunk_sz = rnd_up_len / out->block_size;
355   chunk_header.total_sz = CHUNK_HEADER_LEN + sizeof(fill_val);
356   ret = out->ops->write(out, &chunk_header, sizeof(chunk_header));
357 
358   if (ret < 0) return -1;
359   ret = out->ops->write(out, &fill_val, sizeof(fill_val));
360   if (ret < 0) return -1;
361 
362   if (out->use_crc) {
363     count = out->block_size / sizeof(uint32_t);
364     while (count--) out->crc32 = sparse_crc32(out->crc32, &fill_val, sizeof(uint32_t));
365   }
366 
367   out->cur_out_ptr += rnd_up_len;
368   out->chunk_cnt++;
369 
370   return 0;
371 }
372 
write_sparse_data_chunk(struct output_file * out,unsigned int len,void * data)373 static int write_sparse_data_chunk(struct output_file* out, unsigned int len, void* data) {
374   chunk_header_t chunk_header;
375   int rnd_up_len, zero_len;
376   int ret;
377 
378   /* Round up the data length to a multiple of the block size */
379   rnd_up_len = ALIGN(len, out->block_size);
380   zero_len = rnd_up_len - len;
381 
382   /* Finally we can safely emit a chunk of data */
383   chunk_header.chunk_type = CHUNK_TYPE_RAW;
384   chunk_header.reserved1 = 0;
385   chunk_header.chunk_sz = rnd_up_len / out->block_size;
386   chunk_header.total_sz = CHUNK_HEADER_LEN + rnd_up_len;
387   ret = out->ops->write(out, &chunk_header, sizeof(chunk_header));
388 
389   if (ret < 0) return -1;
390   ret = out->ops->write(out, data, len);
391   if (ret < 0) return -1;
392   if (zero_len) {
393     ret = out->ops->write(out, out->zero_buf, zero_len);
394     if (ret < 0) return -1;
395   }
396 
397   if (out->use_crc) {
398     out->crc32 = sparse_crc32(out->crc32, data, len);
399     if (zero_len) out->crc32 = sparse_crc32(out->crc32, out->zero_buf, zero_len);
400   }
401 
402   out->cur_out_ptr += rnd_up_len;
403   out->chunk_cnt++;
404 
405   return 0;
406 }
407 
write_sparse_end_chunk(struct output_file * out)408 int write_sparse_end_chunk(struct output_file* out) {
409   chunk_header_t chunk_header;
410   int ret;
411 
412   if (out->use_crc) {
413     chunk_header.chunk_type = CHUNK_TYPE_CRC32;
414     chunk_header.reserved1 = 0;
415     chunk_header.chunk_sz = 0;
416     chunk_header.total_sz = CHUNK_HEADER_LEN + 4;
417 
418     ret = out->ops->write(out, &chunk_header, sizeof(chunk_header));
419     if (ret < 0) {
420       return ret;
421     }
422     out->ops->write(out, &out->crc32, 4);
423     if (ret < 0) {
424       return ret;
425     }
426 
427     out->chunk_cnt++;
428   }
429 
430   return 0;
431 }
432 
433 static struct sparse_file_ops sparse_file_ops = {
434     .write_data_chunk = write_sparse_data_chunk,
435     .write_fill_chunk = write_sparse_fill_chunk,
436     .write_skip_chunk = write_sparse_skip_chunk,
437     .write_end_chunk = write_sparse_end_chunk,
438 };
439 
write_normal_data_chunk(struct output_file * out,unsigned int len,void * data)440 static int write_normal_data_chunk(struct output_file* out, unsigned int len, void* data) {
441   int ret;
442   unsigned int rnd_up_len = ALIGN(len, out->block_size);
443 
444   ret = out->ops->write(out, data, len);
445   if (ret < 0) {
446     return ret;
447   }
448 
449   if (rnd_up_len > len) {
450     ret = out->ops->skip(out, rnd_up_len - len);
451   }
452 
453   return ret;
454 }
455 
write_normal_fill_chunk(struct output_file * out,unsigned int len,uint32_t fill_val)456 static int write_normal_fill_chunk(struct output_file* out, unsigned int len, uint32_t fill_val) {
457   int ret;
458   unsigned int i;
459   unsigned int write_len;
460 
461   /* Initialize fill_buf with the fill_val */
462   for (i = 0; i < out->block_size / sizeof(uint32_t); i++) {
463     out->fill_buf[i] = fill_val;
464   }
465 
466   while (len) {
467     write_len = std::min(len, out->block_size);
468     ret = out->ops->write(out, out->fill_buf, write_len);
469     if (ret < 0) {
470       return ret;
471     }
472 
473     len -= write_len;
474   }
475 
476   return 0;
477 }
478 
write_normal_skip_chunk(struct output_file * out,int64_t len)479 static int write_normal_skip_chunk(struct output_file* out, int64_t len) {
480   return out->ops->skip(out, len);
481 }
482 
write_normal_end_chunk(struct output_file * out)483 int write_normal_end_chunk(struct output_file* out) {
484   return out->ops->pad(out, out->len);
485 }
486 
487 static struct sparse_file_ops normal_file_ops = {
488     .write_data_chunk = write_normal_data_chunk,
489     .write_fill_chunk = write_normal_fill_chunk,
490     .write_skip_chunk = write_normal_skip_chunk,
491     .write_end_chunk = write_normal_end_chunk,
492 };
493 
output_file_close(struct output_file * out)494 void output_file_close(struct output_file* out) {
495   out->sparse_ops->write_end_chunk(out);
496   free(out->zero_buf);
497   free(out->fill_buf);
498   out->zero_buf = nullptr;
499   out->fill_buf = nullptr;
500   out->ops->close(out);
501 }
502 
output_file_init(struct output_file * out,int block_size,int64_t len,bool sparse,int chunks,bool crc)503 static int output_file_init(struct output_file* out, int block_size, int64_t len, bool sparse,
504                             int chunks, bool crc) {
505   int ret;
506 
507   out->len = len;
508   out->block_size = block_size;
509   out->cur_out_ptr = 0LL;
510   out->chunk_cnt = 0;
511   out->crc32 = 0;
512   out->use_crc = crc;
513 
514   out->zero_buf = reinterpret_cast<char*>(calloc(block_size, 1));
515   if (!out->zero_buf) {
516     error_errno("malloc zero_buf");
517     return -ENOMEM;
518   }
519 
520   out->fill_buf = reinterpret_cast<uint32_t*>(calloc(block_size, 1));
521   if (!out->fill_buf) {
522     error_errno("malloc fill_buf");
523     ret = -ENOMEM;
524     goto err_fill_buf;
525   }
526 
527   if (sparse) {
528     out->sparse_ops = &sparse_file_ops;
529   } else {
530     out->sparse_ops = &normal_file_ops;
531   }
532 
533   if (sparse) {
534     sparse_header_t sparse_header = {
535         .magic = SPARSE_HEADER_MAGIC,
536         .major_version = SPARSE_HEADER_MAJOR_VER,
537         .minor_version = SPARSE_HEADER_MINOR_VER,
538         .file_hdr_sz = SPARSE_HEADER_LEN,
539         .chunk_hdr_sz = CHUNK_HEADER_LEN,
540         .blk_sz = out->block_size,
541         .total_blks = static_cast<unsigned>(DIV_ROUND_UP(out->len, out->block_size)),
542         .total_chunks = static_cast<unsigned>(chunks),
543         .image_checksum = 0};
544 
545     if (out->use_crc) {
546       sparse_header.total_chunks++;
547     }
548 
549     ret = out->ops->write(out, &sparse_header, sizeof(sparse_header));
550     if (ret < 0) {
551       goto err_write;
552     }
553   }
554 
555   return 0;
556 
557 err_write:
558   free(out->fill_buf);
559 err_fill_buf:
560   free(out->zero_buf);
561   return ret;
562 }
563 
output_file_new_gz(void)564 static struct output_file* output_file_new_gz(void) {
565   struct output_file_gz* outgz =
566       reinterpret_cast<struct output_file_gz*>(calloc(1, sizeof(struct output_file_gz)));
567   if (!outgz) {
568     error_errno("malloc struct outgz");
569     return nullptr;
570   }
571 
572   outgz->out.ops = &gz_file_ops;
573 
574   return &outgz->out;
575 }
576 
output_file_new_normal(void)577 static struct output_file* output_file_new_normal(void) {
578   struct output_file_normal* outn =
579       reinterpret_cast<struct output_file_normal*>(calloc(1, sizeof(struct output_file_normal)));
580   if (!outn) {
581     error_errno("malloc struct outn");
582     return nullptr;
583   }
584 
585   outn->out.ops = &file_ops;
586 
587   return &outn->out;
588 }
589 
output_file_open_callback(int (* write)(void *,const void *,size_t),void * priv,unsigned int block_size,int64_t len,int gz __unused,int sparse,int chunks,int crc)590 struct output_file* output_file_open_callback(int (*write)(void*, const void*, size_t), void* priv,
591                                               unsigned int block_size, int64_t len, int gz __unused,
592                                               int sparse, int chunks, int crc) {
593   int ret;
594   struct output_file_callback* outc;
595 
596   outc =
597       reinterpret_cast<struct output_file_callback*>(calloc(1, sizeof(struct output_file_callback)));
598   if (!outc) {
599     error_errno("malloc struct outc");
600     return nullptr;
601   }
602 
603   outc->out.ops = &callback_file_ops;
604   outc->priv = priv;
605   outc->write = write;
606 
607   ret = output_file_init(&outc->out, block_size, len, sparse, chunks, crc);
608   if (ret < 0) {
609     free(outc);
610     return nullptr;
611   }
612 
613   return &outc->out;
614 }
615 
output_file_open_fd(int fd,unsigned int block_size,int64_t len,int gz,int sparse,int chunks,int crc)616 struct output_file* output_file_open_fd(int fd, unsigned int block_size, int64_t len, int gz,
617                                         int sparse, int chunks, int crc) {
618   int ret;
619   struct output_file* out;
620 
621   if (gz) {
622     out = output_file_new_gz();
623   } else {
624     out = output_file_new_normal();
625   }
626   if (!out) {
627     return nullptr;
628   }
629 
630   out->ops->open(out, fd);
631 
632   ret = output_file_init(out, block_size, len, sparse, chunks, crc);
633   if (ret < 0) {
634     free(out);
635     return nullptr;
636   }
637 
638   return out;
639 }
640 
641 /* Write a contiguous region of data blocks from a memory buffer */
write_data_chunk(struct output_file * out,unsigned int len,void * data)642 int write_data_chunk(struct output_file* out, unsigned int len, void* data) {
643   return out->sparse_ops->write_data_chunk(out, len, data);
644 }
645 
646 /* Write a contiguous region of data blocks with a fill value */
write_fill_chunk(struct output_file * out,unsigned int len,uint32_t fill_val)647 int write_fill_chunk(struct output_file* out, unsigned int len, uint32_t fill_val) {
648   return out->sparse_ops->write_fill_chunk(out, len, fill_val);
649 }
650 
write_fd_chunk(struct output_file * out,unsigned int len,int fd,int64_t offset)651 int write_fd_chunk(struct output_file* out, unsigned int len, int fd, int64_t offset) {
652   auto m = android::base::MappedFile::FromFd(fd, offset, len, PROT_READ);
653   if (!m) return -errno;
654 
655   return out->sparse_ops->write_data_chunk(out, m->size(), m->data());
656 }
657 
658 /* Write a contiguous region of data blocks from a file */
write_file_chunk(struct output_file * out,unsigned int len,const char * file,int64_t offset)659 int write_file_chunk(struct output_file* out, unsigned int len, const char* file, int64_t offset) {
660   int ret;
661 
662   int file_fd = open(file, O_RDONLY | O_BINARY);
663   if (file_fd < 0) {
664     return -errno;
665   }
666 
667   ret = write_fd_chunk(out, len, file_fd, offset);
668 
669   close(file_fd);
670 
671   return ret;
672 }
673 
write_skip_chunk(struct output_file * out,int64_t len)674 int write_skip_chunk(struct output_file* out, int64_t len) {
675   return out->sparse_ops->write_skip_chunk(out, len);
676 }
677