commit - 9d31a1d8a43396fe66a94b1110e395d134bebf3f
commit + c34b20a267f11d16c26b79b2979d91fc9a75132f
blob - 85fdbb17fe65945c8f9d5c7e0ae4996976cd62b6
blob + 8ca7884bfbdf28f02f05c54fa74ff4c901619efc
--- lib/fileindex.c
+++ lib/fileindex.c
#include <stdlib.h>
#include <string.h>
#include <sha1.h>
+#include <endian.h>
#include "got_error.h"
#include "got_fileindex_lib.h"
const struct got_error *
-got_fileindex_entry_open(struct got_fileindex_entry **entry, const char *path,
- uint8_t *blob_sha1)
+got_fileindex_entry_open(struct got_fileindex_entry **entry,
+ const char *ondisk_path, const char *relpath, uint8_t *blob_sha1)
{
struct stat sb;
size_t len;
- if (lstat(path, &sb) != 0)
+ if (lstat(ondisk_path, &sb) != 0)
return got_error_from_errno();
*entry = calloc(1, sizeof(**entry));
if (*entry == NULL)
return got_error(GOT_ERR_NO_MEM);
- (*entry)->path = strdup(path);
+ (*entry)->path = strdup(relpath);
if ((*entry)->path == NULL) {
free(*entry);
*entry = NULL;
(*entry)->mode |= ((sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) <<
GOT_INDEX_ENTRY_MODE_PERMS_SHIFT);
memcpy((*entry)->blob_sha1, blob_sha1, SHA1_DIGEST_LENGTH);
- len = strlen(path);
+ len = strlen(relpath);
if (len > GOT_INDEX_ENTRY_F_PATH_LEN)
len = GOT_INDEX_ENTRY_F_PATH_LEN;
(*entry)->flags |= len;
free(fileindex);
}
+static const struct got_error *
+write_fileindex_val64(SHA1_CTX *ctx, uint64_t val, FILE *outfile)
+{
+ uint8_t buf[sizeof(uint64_t)];
+ size_t n;
+
+ val = htobe64(val);
+ memcpy(buf, &val, sizeof(val));
+ SHA1Update(ctx, buf, sizeof(val));
+ n = fwrite(buf, 1, sizeof(val), outfile);
+ if (n != sizeof(val))
+ return got_ferror(outfile, GOT_ERR_IO);
+ return NULL;
+}
+
+static const struct got_error *
+write_fileindex_val32(SHA1_CTX *ctx, uint32_t val, FILE *outfile)
+{
+ uint8_t buf[sizeof(uint32_t)];
+ size_t n;
+
+ val = htobe32(val);
+ memcpy(buf, &val, sizeof(val));
+ SHA1Update(ctx, buf, sizeof(val));
+ n = fwrite(buf, 1, sizeof(val), outfile);
+ if (n != sizeof(val))
+ return got_ferror(outfile, GOT_ERR_IO);
+ return NULL;
+}
+
+static const struct got_error *
+write_fileindex_val16(SHA1_CTX *ctx, uint16_t val, FILE *outfile)
+{
+ uint8_t buf[sizeof(uint16_t)];
+ size_t n;
+
+ val = htobe16(val);
+ memcpy(buf, &val, sizeof(val));
+ SHA1Update(ctx, buf, sizeof(val));
+ n = fwrite(buf, 1, sizeof(val), outfile);
+ if (n != sizeof(val))
+ return got_ferror(outfile, GOT_ERR_IO);
+ return NULL;
+}
+
+static const struct got_error *
+write_fileindex_path(SHA1_CTX *ctx, const char *path, FILE *outfile)
+{
+ size_t n, len, pad;
+ static const uint8_t zero[8] = { 0 };
+
+ len = strlen(path);
+ pad = (len % 8);
+
+ SHA1Update(ctx, path, len);
+ n = fwrite(path, 1, len, outfile);
+ if (n != len)
+ return got_ferror(outfile, GOT_ERR_IO);
+ if (pad == 0)
+ return NULL;
+ SHA1Update(ctx, zero, pad);
+ n = fwrite(zero, 1, pad, outfile);
+ if (n != pad)
+ return got_ferror(outfile, GOT_ERR_IO);
+ return NULL;
+}
+
+static const struct got_error *
+write_fileindex_entry(SHA1_CTX *ctx, struct got_fileindex_entry *entry,
+ FILE *outfile)
+{
+ const struct got_error *err;
+ size_t n, len, pad;
+
+ err = write_fileindex_val64(ctx, entry->ctime_sec, outfile);
+ if (err)
+ return err;
+ err = write_fileindex_val64(ctx, entry->ctime_nsec, outfile);
+ if (err)
+ return err;
+ err = write_fileindex_val64(ctx, entry->mtime_sec, outfile);
+ if (err)
+ return err;
+ err = write_fileindex_val64(ctx, entry->mtime_nsec, outfile);
+ if (err)
+ return err;
+
+ err = write_fileindex_val32(ctx, entry->uid, outfile);
+ if (err)
+ return err;
+ err = write_fileindex_val32(ctx, entry->gid, outfile);
+ if (err)
+ return err;
+ err = write_fileindex_val32(ctx, entry->size, outfile);
+ if (err)
+ return err;
+
+ err = write_fileindex_val16(ctx, entry->mode, outfile);
+ if (err)
+ return err;
+
+ SHA1Update(ctx, entry->blob_sha1, SHA1_DIGEST_LENGTH);
+ n = fwrite(entry->blob_sha1, 1, SHA1_DIGEST_LENGTH, outfile);
+ if (n != SHA1_DIGEST_LENGTH)
+ return got_ferror(outfile, GOT_ERR_IO);
+
+ err = write_fileindex_val32(ctx, entry->flags, outfile);
+ if (err)
+ return err;
+
+ err = write_fileindex_path(ctx, entry->path, outfile);
+ return err;
+}
+
const struct got_error *
got_fileindex_write(struct got_fileindex *fileindex, FILE *outfile)
{
+ struct got_fileindex_hdr hdr;
+ struct got_fileindex_entry *entry;
+ SHA1_CTX ctx;
+ uint8_t sha1[SHA1_DIGEST_LENGTH];
+ size_t n;
+ const size_t len = sizeof(hdr.signature) + sizeof(hdr.version) +
+ sizeof(hdr.nentries);
+ uint8_t buf[len];
+
+ SHA1Init(&ctx);
+
+ hdr.signature = htobe32(GOT_FILE_INDEX_SIGNATURE);
+ hdr.version = htobe32(GOT_FILE_INDEX_VERSION);
+ hdr.nentries = htobe32(fileindex->nentries);
+
+ memcpy(buf, &hdr, len);
+ SHA1Update(&ctx, buf, len);
+ n = fwrite(buf, 1, len, outfile);
+ if (n != len)
+ return got_ferror(outfile, GOT_ERR_IO);
+
+ TAILQ_FOREACH(entry, &fileindex->entries, entry) {
+ const struct got_error *err;
+ err = write_fileindex_entry(&ctx, entry, outfile);
+ if (err)
+ return err;
+ }
+
+ SHA1Final(sha1, &ctx);
+ n = fwrite(sha1, 1, sizeof(sha1), outfile);
+ if (n != sizeof(sha1))
+ return got_ferror(outfile, GOT_ERR_IO);
+
return NULL;
}
blob - 546f7ddd279eba8e6792b2ea8e126f4bc0d3d40b
blob + 018f4f25c636bf8cfb37d7b1765211c73acae8e9
--- lib/got_fileindex_lib.h
+++ lib/got_fileindex_lib.h
/* On-disk file index header structure. */
struct got_fileindex_hdr {
uint32_t signature; /* big-endian */
+#define GOT_FILE_INDEX_SIGNATURE 0x676f7449 /* 'g', 'o', 't', 'I' */
uint32_t version; /* big-endian */
#define GOT_FILE_INDEX_VERSION 1
uint32_t nentries; /* big-endian */
};
const struct got_error *got_fileindex_entry_open(struct got_fileindex_entry **,
- const char *, uint8_t *);
+ const char *, const char *, uint8_t *);
void got_fileindex_entry_close(struct got_fileindex_entry *);
struct got_fileindex *got_fileindex_open(void);
void got_fileindex_close(struct got_fileindex *);
blob - c8140c77f4fb12393cc353436d2ef004276aae3c
blob + e7ba544ae402ec0cfcc1c84183ca0c8278771fd4
--- lib/worktree.c
+++ lib/worktree.c
const char *path, struct got_blob_object *blob, struct got_repository *repo)
{
const struct got_error *err = NULL;
- char *abspath;
+ char *ondisk_path;
int fd;
size_t len, hdrlen;
struct got_fileindex_entry *entry;
- if (asprintf(&abspath, "%s/%s", worktree->root_path,
+ if (asprintf(&ondisk_path, "%s/%s", worktree->root_path,
apply_path_prefix(worktree, path)) == -1)
return got_error(GOT_ERR_NO_MEM);
- fd = open(abspath, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW,
+ fd = open(ondisk_path, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW,
GOT_DEFAULT_FILE_MODE);
if (fd == -1) {
err = got_error_from_errno();
if (errno == EEXIST) {
struct stat sb;
- if (lstat(abspath, &sb) == -1) {
+ if (lstat(ondisk_path, &sb) == -1) {
err = got_error_from_errno();
} else if (!S_ISREG(sb.st_mode)) {
/* TODO file is obstructed; do something */
fsync(fd);
- err = got_fileindex_entry_open(&entry, abspath, blob->id.sha1);
+ err = got_fileindex_entry_open(&entry, ondisk_path,
+ apply_path_prefix(worktree, path), blob->id.sha1);
if (err)
goto done;
goto done;
done:
close(fd);
- free(abspath);
+ free(ondisk_path);
return err;
}