See comments inline...
> Module Name: othersrc > Committed By: agc > Date: Sun Nov 25 20:20:36 UTC 2012 > > Modified Files: > othersrc/external/bsd/mat/dist: mat.c mat.h > othersrc/external/bsd/mat/libmat: shlib_version > > Log Message: > Use mmap(2) to write files, where possible. > > Fallback to write(2) when not possible. > > > To generate a diff of this commit: > cvs rdiff -u -r1.5 -r1.6 othersrc/external/bsd/mat/dist/mat.c \ > othersrc/external/bsd/mat/dist/mat.h > cvs rdiff -u -r1.1.1.1 -r1.2 othersrc/external/bsd/mat/libmat/shlib_version > > Please note that diffs are not public domain; they are subject to the > copyright notices on the relevant files. > > Modified files: > > Index: othersrc/external/bsd/mat/dist/mat.c > diff -u othersrc/external/bsd/mat/dist/mat.c:1.5 > othersrc/external/bsd/mat/dist/mat.c:1.6 > --- othersrc/external/bsd/mat/dist/mat.c:1.5 Sun Aug 12 01:42:24 2012 > +++ othersrc/external/bsd/mat/dist/mat.c Sun Nov 25 20:20:36 2012 > @@ -180,9 +180,44 @@ fillmeta(matent_t *ent, const char *f, s > ent->meta.flags = st->st_flags; > } > > +/* write to file */ > +static int > +memwrite(FILE *fp, uint64_t off, const void *p, size_t size) > +{ > + char *mapped; > + > + mapped = mmap(NULL, size, PROT_WRITE, MAP_SHARED, fileno(fp), > (off_t)off); > + if (mapped == MAP_FAILED) { > + if (write(fileno(fp), p, size) != (ssize_t)size) { > + fprintf(stderr, "short write %zu chars\n", size); > + return 0; > + } > + } else { > + lseek(fileno(fp), (off_t)(off + size - 1), SEEK_SET); > + if (write(fileno(fp), "", 1) != 1) { > + fprintf(stderr, "short write %" PRIu64 " chars\n", > size); > + return 0; > + } > + memcpy(mapped, p, size); > + munmap(mapped, size); > + } > + return 1; > +} memwrite() can return with the file still being mapped (successful mmap(), then a short write). Is that intended? No big problem if the calling program exits when memwrite() returns 0, but I did not check that. Then different formats are uses to print the size, "%u" in one case, "%" PRlu64 "" in the second case. Could be nicer if it was consistent, maybe. > + > +/* write to mat archive */ > +static int > +archive_write(mat_t *mat, const void *p, size_t size) > +{ > + if (memwrite(mat->fp, mat->off, p, size)) { > + mat->off += size; > + return 1; > + } > + return 0; > +} > + > /* write the entry's meta information to the archive */ > static int > -writemeta(int fd, matent_t *ent) > +writemeta(mat_t *mat, matent_t *ent) > { > matent_t lent; > > @@ -199,7 +234,7 @@ writemeta(int fd, matent_t *ent) > lent.meta.flags = local_htobe32(ent->meta.flags); > lent.meta.linklen = local_htobe32(ent->meta.linklen); > lent.meta.type = ent->meta.type; > - return write(fd, &lent, sizeof(lent.meta)) == sizeof(lent.meta); > + return archive_write(mat, &lent, sizeof(lent.meta)) == > sizeof(lent.meta); > } > > /* read the entry's meta information from the archive */ > @@ -420,7 +455,10 @@ extract_file(mat_t *mat, extract_t *arch > (void) fprintf(stderr, "can't create '%s'\n", name); > return 0; > } > - write(fileno(fp), &archive->s[archive->off], ent->meta.size); > + if (!memwrite(fp, 0, &archive->s[archive->off], > ent->meta.size)) { > + fprintf(stderr, "short write %" PRIu64 " chars\n", > ent->meta.size); > + return 0; > + } > tv[0].tv_sec = ent->meta.atime; > tv[0].tv_usec = 0; > tv[1].tv_sec = ent->meta.mtime; > @@ -548,8 +586,8 @@ write_meta_info(mat_t *mat, matent_t *en > (int)strlen(&f[matches[0].rm_eo]), > &f[matches[0].rm_eo]) + 1; > f = newpath; > } > - writemeta(fileno(mat->fp), ent); > - write(fileno(mat->fp), f, ent->meta.namelen); > + writemeta(mat, ent); > + archive_write(mat, f, ent->meta.namelen); > return 1; > } > > @@ -629,13 +667,13 @@ mat_add(mat_t *mat, const char *f) > return 0; > } > write_meta_info(mat, &ent, f); > - write(fileno(mat->fp), mapped, (size_t)st.st_size); > + archive_write(mat, mapped, (size_t)st.st_size); > digest_update(ent.digest, mapped, (size_t)st.st_size); > if (ent.meta.nlink > 1 && original) { > /* multi-linked, and we're the primary */ > (void) memcpy(&mat->links[primary].digest, ent.digest, > sizeof(ent.digest)); > } > - write(fileno(mat->fp), ent.digest, sizeof(ent.digest)); > + archive_write(mat, ent.digest, sizeof(ent.digest)); > munmap(mapped, (size_t)st.st_size); > (void) fclose(fp); > break; > @@ -643,10 +681,10 @@ mat_add(mat_t *mat, const char *f) > /* store hardlink to primary */ > ent.meta.linklen = mat->links[primary].namelen; > write_meta_info(mat, &ent, f); > - write(fileno(mat->fp), mat->links[primary].name, > (size_t)ent.meta.linklen); > + archive_write(mat, mat->links[primary].name, > (size_t)ent.meta.linklen); > /* get digest from primary */ > (void) memcpy(ent.digest, mat->links[primary].digest, > sizeof(ent.digest)); > - write(fileno(mat->fp), ent.digest, sizeof(ent.digest)); > + archive_write(mat, ent.digest, sizeof(ent.digest)); > break; > case 'l': > if ((cc = readlink(f, newpath, sizeof(newpath))) < 0) { > @@ -656,9 +694,9 @@ mat_add(mat_t *mat, const char *f) > newpath[cc] = 0x0; > ent.meta.linklen = (uint32_t)(cc + 1); > write_meta_info(mat, &ent, f); > - write(fileno(mat->fp), newpath, (size_t)ent.meta.linklen); > + archive_write(mat, newpath, (size_t)ent.meta.linklen); > digest_update(ent.digest, (uint8_t *)newpath, > (size_t)ent.meta.linklen); > - write(fileno(mat->fp), ent.digest, sizeof(ent.digest)); > + archive_write(mat, ent.digest, sizeof(ent.digest)); > break; > case 'b': > case 'c': > @@ -965,7 +1003,7 @@ mat_init(mat_t *mat, const char *f, cons > mat->archive = st.st_ino; > (void) memset(&header, 0x0, sizeof(header)); > header.magic = local_htobe32(MAT_MAGIC); > - write(fileno(mat->fp), &header, sizeof(header)); > + archive_write(mat, &header, sizeof(header)); > return 1; > } > if ((mat->fp = fopen(f, "r")) == NULL) { > Index: othersrc/external/bsd/mat/dist/mat.h > diff -u othersrc/external/bsd/mat/dist/mat.h:1.5 > othersrc/external/bsd/mat/dist/mat.h:1.6 > --- othersrc/external/bsd/mat/dist/mat.h:1.5 Thu Oct 13 17:20:47 2011 > +++ othersrc/external/bsd/mat/dist/mat.h Sun Nov 25 20:20:36 2012 > @@ -64,9 +64,7 @@ typedef struct matmeta_t { > uint32_t namelen; /* size of name */ > uint32_t linklen; /* size of link target */ > uint32_t flags; /* fs flags */ > -#if 0 > uint32_t xasize; /* extattr size */ > -#endif > char type; /* single char type */ > } matmeta_t; > > @@ -75,9 +73,7 @@ typedef struct matent_t { > matmeta_t meta; /* meta data */ > char *name; /* name of entry */ > uint8_t *data; /* associated data */ > -#if 0 > uint8_t *extattrs; /* extended attributes */ > -#endif > uint8_t digest[MAT_DIGEST_LEN]; /* sha256 */ > } matent_t; > > @@ -99,6 +95,7 @@ typedef struct mat_t { > const char *action; /* what action we're doing */ > FILE *fp; /* archive pointer */ > uint8_t *mapped; /* memory mapped archive */ > + uint64_t off; /* offset from start */ > size_t size; /* size of mmap */ > int verbose; /* be gobby */ > uint64_t archive; /* inode of the archive */ > > Index: othersrc/external/bsd/mat/libmat/shlib_version > diff -u othersrc/external/bsd/mat/libmat/shlib_version:1.1.1.1 > othersrc/external/bsd/mat/libmat/shlib_version:1.2 > --- othersrc/external/bsd/mat/libmat/shlib_version:1.1.1.1 Sat Jun 18 > 04:53:13 2011 > +++ othersrc/external/bsd/mat/libmat/shlib_version Sun Nov 25 20:20:36 2012 > @@ -1,2 +1,2 @@ > -major=0 > +major=1 > minor=0 >