Imported Upstream version 3.2.6
[platform/upstream/ccache.git] / manifest.c
1 /*
2  * Copyright (C) 2009-2016 Joel Rosdahl
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the Free
6  * Software Foundation; either version 3 of the License, or (at your option)
7  * any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc., 51
16  * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18
19 #include "ccache.h"
20 #include "hashtable_itr.h"
21 #include "hashutil.h"
22 #include "manifest.h"
23 #include "murmurhashneutral2.h"
24
25 #include <zlib.h>
26
27 /*
28  * Sketchy specification of the manifest disk format:
29  *
30  * <magic>         magic number                        (4 bytes)
31  * <version>       file format version                 (1 byte unsigned int)
32  * <hash_size>     size of the hash fields (in bytes)  (1 byte unsigned int)
33  * <reserved>      reserved for future use             (2 bytes)
34  * ----------------------------------------------------------------------------
35  * <n>             number of include file paths        (4 bytes unsigned int)
36  * <path_0>        path to include file                (NUL-terminated string,
37  * ...                                                  at most 1024 bytes)
38  * <path_n-1>
39  * ----------------------------------------------------------------------------
40  * <n>             number of include file hash entries (4 bytes unsigned int)
41  * <index[0]>      index of include file path          (4 bytes unsigned int)
42  * <hash[0]>       hash of include file                (<hash_size> bytes)
43  * <size[0]>       size of include file                (4 bytes unsigned int)
44  * <mtime[0]>      mtime of include file               (8 bytes signed int)
45  * <ctime[0]>      ctime of include file               (8 bytes signed int)
46  * ...
47  * <index[n-1]>
48  * <hash[n-1]>
49  * <size[n-1]>
50  * <mtime[n-1]>
51  * <ctime[n-1]>
52  * ----------------------------------------------------------------------------
53  * <n>             number of object name entries       (4 bytes unsigned int)
54  * <m[0]>          number of include file hash indexes (4 bytes unsigned int)
55  * <index[0][0]>   include file hash index             (4 bytes unsigned int)
56  * ...
57  * <index[0][m[0]-1]>
58  * <hash[0]>       hash part of object name            (<hash_size> bytes)
59  * <size[0]>       size part of object name            (4 bytes unsigned int)
60  * ...
61  * <m[n-1]>        number of include file hash indexes
62  * <index[n-1][0]> include file hash index
63  * ...
64  * <index[n-1][m[n-1]]>
65  * <hash[n-1]>
66  * <size[n-1]>
67  */
68
69 static const uint32_t MAGIC = 0x63436d46U;
70 static const uint32_t MAX_MANIFEST_ENTRIES = 100;
71 static const uint32_t MAX_MANIFEST_FILE_INFO_ENTRIES = 10000;
72
73 #define ccache_static_assert(e) \
74   do { enum { ccache_static_assert__ = 1/(e) }; } while (false)
75
76 struct file_info {
77         /* Index to n_files. */
78         uint32_t index;
79         /* Hash of referenced file. */
80         uint8_t hash[16];
81         /* Size of referenced file. */
82         uint32_t size;
83         /* mtime of referenced file. */
84         int64_t mtime;
85         /* ctime of referenced file. */
86         int64_t ctime;
87 };
88
89 struct object {
90         /* Number of entries in file_info_indexes. */
91         uint32_t n_file_info_indexes;
92         /* Indexes to file_infos. */
93         uint32_t *file_info_indexes;
94         /* Hash of the object itself. */
95         struct file_hash hash;
96 };
97
98 struct manifest {
99         /* Version of decoded file. */
100         uint8_t version;
101
102         /* Reserved for future use. */
103         uint16_t reserved;
104
105         /* Size of hash fields (in bytes). */
106         uint8_t hash_size;
107
108         /* Referenced include files. */
109         uint32_t n_files;
110         char **files;
111
112         /* Information about referenced include files. */
113         uint32_t n_file_infos;
114         struct file_info *file_infos;
115
116         /* Object names plus references to include file hashes. */
117         uint32_t n_objects;
118         struct object *objects;
119 };
120
121 struct file_stats {
122         uint32_t size;
123         int64_t mtime;
124         int64_t ctime;
125 };
126
127 static unsigned int
128 hash_from_file_info(void *key)
129 {
130         ccache_static_assert(sizeof(struct file_info) == 40); /* No padding. */
131         return murmurhashneutral2(key, sizeof(struct file_info), 0);
132 }
133
134 static int
135 file_infos_equal(void *key1, void *key2)
136 {
137         struct file_info *fi1 = (struct file_info *)key1;
138         struct file_info *fi2 = (struct file_info *)key2;
139         return fi1->index == fi2->index
140                && memcmp(fi1->hash, fi2->hash, 16) == 0
141                && fi1->size == fi2->size
142                && fi1->mtime == fi2->mtime
143                && fi1->ctime == fi2->ctime;
144 }
145
146 static void
147 free_manifest(struct manifest *mf)
148 {
149         uint32_t i;
150         for (i = 0; i < mf->n_files; i++) {
151                 free(mf->files[i]);
152         }
153         free(mf->files);
154         free(mf->file_infos);
155         for (i = 0; i < mf->n_objects; i++) {
156                 free(mf->objects[i].file_info_indexes);
157         }
158         free(mf->objects);
159         free(mf);
160 }
161
162 #define READ_BYTE(var) \
163   do { \
164                 int ch_; \
165                 ch_ = gzgetc(f); \
166                 if (ch_ == EOF) { \
167                         goto error; \
168                 } \
169                 (var) = ch_ & 0xFF; \
170         } while (false)
171
172 #define READ_INT(size, var) \
173   do { \
174                 int ch_; \
175                 size_t i_; \
176                 (var) = 0; \
177                 for (i_ = 0; i_ < (size); i_++) { \
178                         ch_ = gzgetc(f); \
179                         if (ch_ == EOF) { \
180                                 goto error; \
181                         } \
182                         (var) <<= 8; \
183                         (var) |= ch_ & 0xFF; \
184                 } \
185         } while (false)
186
187 #define READ_STR(var) \
188   do { \
189                 char buf_[1024]; \
190                 size_t i_; \
191                 int ch_; \
192                 for (i_ = 0; i_ < sizeof(buf_); i_++) { \
193                         ch_ = gzgetc(f); \
194                         if (ch_ == EOF) { \
195                                 goto error; \
196                         } \
197                         buf_[i_] = ch_; \
198                         if (ch_ == '\0') { \
199                                 break; \
200                         } \
201                 } \
202                 if (i_ == sizeof(buf_)) { \
203                         goto error; \
204                 } \
205                 (var) = x_strdup(buf_); \
206         } while (false)
207
208 #define READ_BYTES(n, var) \
209   do { \
210                 size_t i_; \
211                 int ch_; \
212                 for (i_ = 0; i_ < (n); i_++) { \
213                         ch_ = gzgetc(f); \
214                         if (ch_ == EOF) { \
215                                 goto error; \
216                         } \
217                         (var)[i_] = ch_; \
218                 } \
219         } while (false)
220
221 static struct manifest *
222 create_empty_manifest(void)
223 {
224         struct manifest *mf;
225
226         mf = x_malloc(sizeof(*mf));
227         mf->hash_size = 16;
228         mf->n_files = 0;
229         mf->files = NULL;
230         mf->n_file_infos = 0;
231         mf->file_infos = NULL;
232         mf->n_objects = 0;
233         mf->objects = NULL;
234
235         return mf;
236 }
237
238 static struct manifest *
239 read_manifest(gzFile f)
240 {
241         struct manifest *mf;
242         uint32_t i, j;
243         uint32_t magic;
244
245         mf = create_empty_manifest();
246
247         READ_INT(4, magic);
248         if (magic != MAGIC) {
249                 cc_log("Manifest file has bad magic number %u", magic);
250                 free_manifest(mf);
251                 return NULL;
252         }
253         READ_BYTE(mf->version);
254         if (mf->version != MANIFEST_VERSION) {
255                 cc_log("Manifest file has unknown version %u", mf->version);
256                 free_manifest(mf);
257                 return NULL;
258         }
259
260         READ_BYTE(mf->hash_size);
261         if (mf->hash_size != 16) {
262                 /* Temporary measure until we support different hash algorithms. */
263                 cc_log("Manifest file has unsupported hash size %u", mf->hash_size);
264                 free_manifest(mf);
265                 return NULL;
266         }
267
268         READ_INT(2, mf->reserved);
269
270         READ_INT(4, mf->n_files);
271         mf->files = x_calloc(mf->n_files, sizeof(*mf->files));
272         for (i = 0; i < mf->n_files; i++) {
273                 READ_STR(mf->files[i]);
274         }
275
276         READ_INT(4, mf->n_file_infos);
277         mf->file_infos = x_calloc(mf->n_file_infos, sizeof(*mf->file_infos));
278         for (i = 0; i < mf->n_file_infos; i++) {
279                 READ_INT(4, mf->file_infos[i].index);
280                 READ_BYTES(mf->hash_size, mf->file_infos[i].hash);
281                 READ_INT(4, mf->file_infos[i].size);
282                 READ_INT(8, mf->file_infos[i].mtime);
283                 READ_INT(8, mf->file_infos[i].ctime);
284         }
285
286         READ_INT(4, mf->n_objects);
287         mf->objects = x_calloc(mf->n_objects, sizeof(*mf->objects));
288         for (i = 0; i < mf->n_objects; i++) {
289                 READ_INT(4, mf->objects[i].n_file_info_indexes);
290                 mf->objects[i].file_info_indexes =
291                   x_calloc(mf->objects[i].n_file_info_indexes,
292                            sizeof(*mf->objects[i].file_info_indexes));
293                 for (j = 0; j < mf->objects[i].n_file_info_indexes; j++) {
294                         READ_INT(4, mf->objects[i].file_info_indexes[j]);
295                 }
296                 READ_BYTES(mf->hash_size, mf->objects[i].hash.hash);
297                 READ_INT(4, mf->objects[i].hash.size);
298         }
299
300         return mf;
301
302 error:
303         cc_log("Corrupt manifest file");
304         free_manifest(mf);
305         return NULL;
306 }
307
308 #define WRITE_INT(size, var) \
309   do { \
310                 uint8_t ch_; \
311                 size_t i_; \
312                 for (i_ = 0; i_ < (size); i_++) { \
313                         ch_ = ((var) >> (8 * ((size) - i_ - 1))); \
314                         if (gzputc(f, ch_) == EOF) { \
315                                 goto error; \
316                         } \
317                 } \
318         } while (false)
319
320 #define WRITE_STR(var) \
321   do { \
322                 if (gzputs(f, var) == EOF || gzputc(f, '\0') == EOF) { \
323                         goto error; \
324                 } \
325         } while (false)
326
327 #define WRITE_BYTES(n, var) \
328   do { \
329                 size_t i_; \
330                 for (i_ = 0; i_ < (n); i_++) { \
331                         if (gzputc(f, (var)[i_]) == EOF) { \
332                                 goto error; \
333                         } \
334                 } \
335         } while (false)
336
337 static int
338 write_manifest(gzFile f, const struct manifest *mf)
339 {
340         uint32_t i, j;
341
342         WRITE_INT(4, MAGIC);
343         WRITE_INT(1, MANIFEST_VERSION);
344         WRITE_INT(1, 16);
345         WRITE_INT(2, 0);
346
347         WRITE_INT(4, mf->n_files);
348         for (i = 0; i < mf->n_files; i++) {
349                 WRITE_STR(mf->files[i]);
350         }
351
352         WRITE_INT(4, mf->n_file_infos);
353         for (i = 0; i < mf->n_file_infos; i++) {
354                 WRITE_INT(4, mf->file_infos[i].index);
355                 WRITE_BYTES(mf->hash_size, mf->file_infos[i].hash);
356                 WRITE_INT(4, mf->file_infos[i].size);
357                 WRITE_INT(8, mf->file_infos[i].mtime);
358                 WRITE_INT(8, mf->file_infos[i].ctime);
359         }
360
361         WRITE_INT(4, mf->n_objects);
362         for (i = 0; i < mf->n_objects; i++) {
363                 WRITE_INT(4, mf->objects[i].n_file_info_indexes);
364                 for (j = 0; j < mf->objects[i].n_file_info_indexes; j++) {
365                         WRITE_INT(4, mf->objects[i].file_info_indexes[j]);
366                 }
367                 WRITE_BYTES(mf->hash_size, mf->objects[i].hash.hash);
368                 WRITE_INT(4, mf->objects[i].hash.size);
369         }
370
371         return 1;
372
373 error:
374         cc_log("Error writing to manifest file");
375         return 0;
376 }
377
378 static int
379 verify_object(struct conf *conf, struct manifest *mf, struct object *obj,
380               struct hashtable *stated_files, struct hashtable *hashed_files)
381 {
382         uint32_t i;
383         struct file_hash *actual;
384         struct mdfour hash;
385         int result;
386
387         for (i = 0; i < obj->n_file_info_indexes; i++) {
388                 struct file_info *fi = &mf->file_infos[obj->file_info_indexes[i]];
389                 char *path = mf->files[fi->index];
390                 struct file_stats *st = hashtable_search(stated_files, path);
391                 if (!st) {
392                         struct stat file_stat;
393                         if (x_stat(path, &file_stat) != 0) {
394                                 return 0;
395                         }
396                         st = x_malloc(sizeof(*st));
397                         st->size = file_stat.st_size;
398                         st->mtime = file_stat.st_mtime;
399                         st->ctime = file_stat.st_ctime;
400                         hashtable_insert(stated_files, x_strdup(path), st);
401                 }
402
403                 if (conf->sloppiness & SLOPPY_FILE_STAT_MATCHES) {
404                         /*
405                          * st->ctime is sometimes 0, so we can't check that both st->ctime and
406                          * st->mtime are greater than time_of_compilation. But it's sufficient to
407                          * check that either is.
408                          */
409                         if (fi->size == st->size
410                             && fi->mtime == st->mtime
411                             && fi->ctime == st->ctime
412                             && MAX(st->mtime, st->ctime) >= time_of_compilation) {
413                                 cc_log("size/mtime/ctime hit for %s", path);
414                                 continue;
415                         } else {
416                                 cc_log("size/mtime/ctime miss for %s", path);
417                         }
418                 }
419
420                 actual = hashtable_search(hashed_files, path);
421                 if (!actual) {
422                         actual = x_malloc(sizeof(*actual));
423                         hash_start(&hash);
424                         result = hash_source_code_file(conf, &hash, path);
425                         if (result & HASH_SOURCE_CODE_ERROR) {
426                                 cc_log("Failed hashing %s", path);
427                                 free(actual);
428                                 return 0;
429                         }
430                         if (result & HASH_SOURCE_CODE_FOUND_TIME) {
431                                 free(actual);
432                                 return 0;
433                         }
434                         hash_result_as_bytes(&hash, actual->hash);
435                         actual->size = hash.totalN;
436                         hashtable_insert(hashed_files, x_strdup(path), actual);
437                 }
438                 if (memcmp(fi->hash, actual->hash, mf->hash_size) != 0
439                     || fi->size != actual->size) {
440                         return 0;
441                 }
442         }
443
444         return 1;
445 }
446
447 static struct hashtable *
448 create_string_index_map(char **strings, uint32_t len)
449 {
450         uint32_t i;
451         struct hashtable *h;
452         uint32_t *index;
453
454         h = create_hashtable(1000, hash_from_string, strings_equal);
455         for (i = 0; i < len; i++) {
456                 index = x_malloc(sizeof(*index));
457                 *index = i;
458                 hashtable_insert(h, x_strdup(strings[i]), index);
459         }
460         return h;
461 }
462
463 static struct hashtable *
464 create_file_info_index_map(struct file_info *infos, uint32_t len)
465 {
466         uint32_t i;
467         struct hashtable *h;
468         struct file_info *fi;
469         uint32_t *index;
470
471         h = create_hashtable(1000, hash_from_file_info, file_infos_equal);
472         for (i = 0; i < len; i++) {
473                 fi = x_malloc(sizeof(*fi));
474                 *fi = infos[i];
475                 index = x_malloc(sizeof(*index));
476                 *index = i;
477                 hashtable_insert(h, fi, index);
478         }
479         return h;
480 }
481
482 static uint32_t
483 get_include_file_index(struct manifest *mf, char *path,
484                        struct hashtable *mf_files)
485 {
486         uint32_t *index;
487         uint32_t n;
488
489         index = hashtable_search(mf_files, path);
490         if (index) {
491                 return *index;
492         }
493
494         n = mf->n_files;
495         mf->files = x_realloc(mf->files, (n + 1) * sizeof(*mf->files));
496         mf->n_files++;
497         mf->files[n] = x_strdup(path);
498
499         return n;
500 }
501
502 static uint32_t
503 get_file_hash_index(struct manifest *mf,
504                     char *path,
505                     struct file_hash *file_hash,
506                     struct hashtable *mf_files,
507                     struct hashtable *mf_file_infos)
508 {
509         struct file_info fi;
510         uint32_t *fi_index;
511         uint32_t n;
512         struct stat file_stat;
513
514         fi.index = get_include_file_index(mf, path, mf_files);
515         memcpy(fi.hash, file_hash->hash, sizeof(fi.hash));
516         fi.size = file_hash->size;
517
518         /*
519          * file_stat.st_{m,c}time has a resolution of 1 second, so we can cache the
520          * file's mtime and ctime only if they're at least one second older than
521          * time_of_compilation.
522          *
523          * st->ctime may be 0, so we have to check time_of_compilation against
524          * MAX(mtime, ctime).
525          */
526
527         if (stat(path, &file_stat) != -1
528             && time_of_compilation > MAX(file_stat.st_mtime, file_stat.st_ctime)) {
529                 fi.mtime = file_stat.st_mtime;
530                 fi.ctime = file_stat.st_ctime;
531         } else {
532                 fi.mtime = -1;
533                 fi.ctime = -1;
534         }
535
536         fi_index = hashtable_search(mf_file_infos, &fi);
537         if (fi_index) {
538                 return *fi_index;
539         }
540
541         n = mf->n_file_infos;
542         mf->file_infos = x_realloc(mf->file_infos, (n + 1) * sizeof(*mf->file_infos));
543         mf->n_file_infos++;
544         mf->file_infos[n] = fi;
545
546         return n;
547 }
548
549 static void
550 add_file_info_indexes(uint32_t *indexes, uint32_t size,
551                       struct manifest *mf, struct hashtable *included_files)
552 {
553         struct hashtable_itr *iter;
554         uint32_t i;
555         struct hashtable *mf_files; /* path --> index */
556         struct hashtable *mf_file_infos; /* struct file_info --> index */
557
558         if (size == 0) {
559                 return;
560         }
561
562         mf_files = create_string_index_map(mf->files, mf->n_files);
563         mf_file_infos = create_file_info_index_map(mf->file_infos, mf->n_file_infos);
564         iter = hashtable_iterator(included_files);
565         i = 0;
566         do {
567                 char *path = hashtable_iterator_key(iter);
568                 struct file_hash *file_hash = hashtable_iterator_value(iter);
569                 indexes[i] = get_file_hash_index(mf, path, file_hash, mf_files,
570                                                  mf_file_infos);
571                 i++;
572         } while (hashtable_iterator_advance(iter));
573         assert(i == size);
574
575         hashtable_destroy(mf_file_infos, 1);
576         hashtable_destroy(mf_files, 1);
577 }
578
579 static void
580 add_object_entry(struct manifest *mf,
581                  struct file_hash *object_hash,
582                  struct hashtable *included_files)
583 {
584         struct object *obj;
585         uint32_t n;
586
587         n = mf->n_objects;
588         mf->objects = x_realloc(mf->objects, (n + 1) * sizeof(*mf->objects));
589         mf->n_objects++;
590         obj = &mf->objects[n];
591
592         n = hashtable_count(included_files);
593         obj->n_file_info_indexes = n;
594         obj->file_info_indexes = x_malloc(n * sizeof(*obj->file_info_indexes));
595         add_file_info_indexes(obj->file_info_indexes, n, mf, included_files);
596         memcpy(obj->hash.hash, object_hash->hash, mf->hash_size);
597         obj->hash.size = object_hash->size;
598 }
599
600 /*
601  * Try to get the object hash from a manifest file. Caller frees. Returns NULL
602  * on failure.
603  */
604 struct file_hash *
605 manifest_get(struct conf *conf, const char *manifest_path)
606 {
607         int fd;
608         gzFile f = NULL;
609         struct manifest *mf = NULL;
610         struct hashtable *hashed_files = NULL; /* path --> struct file_hash */
611         struct hashtable *stated_files = NULL; /* path --> struct file_stats */
612         uint32_t i;
613         struct file_hash *fh = NULL;
614
615         fd = open(manifest_path, O_RDONLY | O_BINARY);
616         if (fd == -1) {
617                 /* Cache miss. */
618                 cc_log("No such manifest file");
619                 goto out;
620         }
621         f = gzdopen(fd, "rb");
622         if (!f) {
623                 close(fd);
624                 cc_log("Failed to gzdopen manifest file");
625                 goto out;
626         }
627         mf = read_manifest(f);
628         if (!mf) {
629                 cc_log("Error reading manifest file");
630                 goto out;
631         }
632
633         hashed_files = create_hashtable(1000, hash_from_string, strings_equal);
634         stated_files = create_hashtable(1000, hash_from_string, strings_equal);
635
636         /* Check newest object first since it's a bit more likely to match. */
637         for (i = mf->n_objects; i > 0; i--) {
638                 if (verify_object(conf, mf, &mf->objects[i - 1],
639                                   stated_files, hashed_files)) {
640                         fh = x_malloc(sizeof(*fh));
641                         *fh = mf->objects[i - 1].hash;
642                         goto out;
643                 }
644         }
645
646 out:
647         if (hashed_files) {
648                 hashtable_destroy(hashed_files, 1);
649         }
650         if (stated_files) {
651                 hashtable_destroy(stated_files, 1);
652         }
653         if (f) {
654                 gzclose(f);
655         }
656         if (mf) {
657                 free_manifest(mf);
658         }
659         return fh;
660 }
661
662 /*
663  * Put the object name into a manifest file given a set of included files.
664  * Returns true on success, otherwise false.
665  */
666 bool
667 manifest_put(const char *manifest_path, struct file_hash *object_hash,
668              struct hashtable *included_files)
669 {
670         int ret = 0;
671         int fd1;
672         int fd2;
673         gzFile f2 = NULL;
674         struct manifest *mf = NULL;
675         char *tmp_file = NULL;
676
677         /*
678          * We don't bother to acquire a lock when writing the manifest to disk. A
679          * race between two processes will only result in one lost entry, which is
680          * not a big deal, and it's also very unlikely.
681          */
682
683         fd1 = open(manifest_path, O_RDONLY | O_BINARY);
684         if (fd1 == -1) {
685                 /* New file. */
686                 mf = create_empty_manifest();
687         } else {
688                 gzFile f1 = gzdopen(fd1, "rb");
689                 if (!f1) {
690                         cc_log("Failed to gzdopen manifest file");
691                         close(fd1);
692                         goto out;
693                 }
694                 mf = read_manifest(f1);
695                 gzclose(f1);
696                 if (!mf) {
697                         cc_log("Failed to read manifest file; deleting it");
698                         x_unlink(manifest_path);
699                         mf = create_empty_manifest();
700                 }
701         }
702
703         if (mf->n_objects > MAX_MANIFEST_ENTRIES) {
704                 /*
705                  * Normally, there shouldn't be many object entries in the manifest since
706                  * new entries are added only if an include file has changed but not the
707                  * source file, and you typically change source files more often than
708                  * header files. However, it's certainly possible to imagine cases where
709                  * the manifest will grow large (for instance, a generated header file that
710                  * changes for every build), and this must be taken care of since
711                  * processing an ever growing manifest eventually will take too much time.
712                  * A good way of solving this would be to maintain the object entries in
713                  * LRU order and discarding the old ones. An easy way is to throw away all
714                  * entries when there are too many. Let's do that for now.
715                  */
716                 cc_log("More than %u entries in manifest file; discarding",
717                        MAX_MANIFEST_ENTRIES);
718                 free_manifest(mf);
719                 mf = create_empty_manifest();
720         } else if (mf->n_file_infos > MAX_MANIFEST_FILE_INFO_ENTRIES) {
721                 /* Rarely, file_info entries can grow large in pathological cases where
722                  * many included files change, but the main file does not. This also puts
723                  * an upper bound on the number of file_info entries.
724                  */
725                 cc_log("More than %u file_info entries in manifest file; discarding",
726                        MAX_MANIFEST_FILE_INFO_ENTRIES);
727                 free_manifest(mf);
728                 mf = create_empty_manifest();
729         }
730
731         tmp_file = format("%s.tmp", manifest_path);
732         fd2 = create_tmp_fd(&tmp_file);
733         f2 = gzdopen(fd2, "wb");
734         if (!f2) {
735                 cc_log("Failed to gzdopen %s", tmp_file);
736                 goto out;
737         }
738
739         add_object_entry(mf, object_hash, included_files);
740         if (write_manifest(f2, mf)) {
741                 gzclose(f2);
742                 f2 = NULL;
743                 if (x_rename(tmp_file, manifest_path) == 0) {
744                         ret = 1;
745                 } else {
746                         cc_log("Failed to rename %s to %s", tmp_file, manifest_path);
747                         goto out;
748                 }
749         } else {
750                 cc_log("Failed to write manifest file");
751                 goto out;
752         }
753
754 out:
755         if (mf) {
756                 free_manifest(mf);
757         }
758         if (tmp_file) {
759                 free(tmp_file);
760         }
761         if (f2) {
762                 gzclose(f2);
763         }
764         return ret;
765 }
766
767 bool
768 manifest_dump(const char *manifest_path, FILE *stream)
769 {
770         struct manifest *mf = NULL;
771         int fd;
772         gzFile f = NULL;
773         bool ret = false;
774         unsigned i, j;
775
776         fd = open(manifest_path, O_RDONLY | O_BINARY);
777         if (fd == -1) {
778                 fprintf(stderr, "No such manifest file: %s\n", manifest_path);
779                 goto out;
780         }
781         f = gzdopen(fd, "rb");
782         if (!f) {
783                 fprintf(stderr, "Failed to dzopen manifest file\n");
784                 close(fd);
785                 goto out;
786         }
787         mf = read_manifest(f);
788         if (!mf) {
789                 fprintf(stderr, "Error reading manifest file\n");
790                 goto out;
791         }
792
793         fprintf(stream, "Magic: %c%c%c%c\n",
794                 (MAGIC >> 24) & 0xFF,
795                 (MAGIC >> 16) & 0xFF,
796                 (MAGIC >> 8) & 0xFF,
797                 MAGIC & 0xFF);
798         fprintf(stream, "Version: %u\n", mf->version);
799         fprintf(stream, "Hash size: %u\n", (unsigned)mf->hash_size);
800         fprintf(stream, "Reserved field: %u\n", (unsigned)mf->reserved);
801         fprintf(stream, "File paths (%u):\n", (unsigned)mf->n_files);
802         for (i = 0; i < mf->n_files; ++i) {
803                 fprintf(stream, "  %u: %s\n", i, mf->files[i]);
804         }
805         fprintf(stream, "File infos (%u):\n", (unsigned)mf->n_file_infos);
806         for (i = 0; i < mf->n_file_infos; ++i) {
807                 char *hash;
808                 fprintf(stream, "  %u:\n", i);
809                 fprintf(stream, "    Path index: %u\n", mf->file_infos[i].index);
810                 hash = format_hash_as_string(mf->file_infos[i].hash, -1);
811                 fprintf(stream, "    Hash: %s\n", hash);
812                 free(hash);
813                 fprintf(stream, "    Size: %u\n", mf->file_infos[i].size);
814                 fprintf(stream, "    Mtime: %lld\n", (long long)mf->file_infos[i].mtime);
815                 fprintf(stream, "    Ctime: %lld\n", (long long)mf->file_infos[i].ctime);
816         }
817         fprintf(stream, "Results (%u):\n", (unsigned)mf->n_objects);
818         for (i = 0; i < mf->n_objects; ++i) {
819                 char *hash;
820                 fprintf(stream, "  %u:\n", i);
821                 fprintf(stream, "    File info indexes:");
822                 for (j = 0; j < mf->objects[i].n_file_info_indexes; ++j) {
823                         fprintf(stream, " %u", mf->objects[i].file_info_indexes[j]);
824                 }
825                 fprintf(stream, "\n");
826                 hash = format_hash_as_string(mf->objects[i].hash.hash, -1);
827                 fprintf(stream, "    Hash: %s\n", hash);
828                 free(hash);
829                 fprintf(stream, "    Size: %u\n", (unsigned)mf->objects[i].hash.size);
830         }
831
832         ret = true;
833
834 out:
835         if (mf) {
836                 free_manifest(mf);
837         }
838         if (f) {
839                 gzclose(f);
840         }
841         return ret;
842 }