diff options
| author | Sadeep Madurange <sadeep@asciimx.com> | 2026-03-23 19:30:53 +0800 |
|---|---|---|
| committer | Sadeep Madurange <sadeep@asciimx.com> | 2026-03-23 19:42:22 +0800 |
| commit | f3473511dd2d91a86e1e36597d05835b6d379a3c (patch) | |
| tree | 526d29eb01b8d2bb4fdf0949ccc52a310de1d929 | |
| parent | af7624d9693915d89431dbb2550c30b3b708fe33 (diff) | |
| download | cvn-f3473511dd2d91a86e1e36597d05835b6d379a3c.tar.gz | |
Copy link function and refactor into smaller functions.
| -rw-r--r-- | main.c | 133 |
1 files changed, 95 insertions, 38 deletions
@@ -3,7 +3,6 @@ #include <fcntl.h> #include <fnmatch.h> #include <ftw.h> -#include <limits.h> #include <sha1.h> #include <stdarg.h> #include <stdio.h> @@ -19,9 +18,10 @@ #define EXCLUDE_PATHS ".vcxignore" -#define BUFLEN 8192 +#define BUF_LEN 8192 #define MAX_DEPTH 256 #define MAX_PATH_LEN 4096 +#define HASH_LEN SHA1_DIGEST_STRING_LENGTH #define KIND_DEL 'D' #define KIND_MOD 'M' @@ -38,14 +38,20 @@ static inline void init_stg_area(void); static inline int cmp_links(const char *link1, const char *link2); static inline int cmp_files(const char *file1, const char *file2); -static inline void stage_file(const char *file, char kind, int islnk); +static inline void stage_entry(const char *path, char kind, int islnk); static inline void print_status(const char *file, char kind, int islnk); static inline int scan_head(const char * path, const struct stat *st, int flag, struct FTW *ftwbuf); static inline int scan_tree(const char * path, const struct stat *st, int flag, struct FTW *ftwbuf); +static inline void mkcopy(const char *path, char dst[HASH_LEN]); +static inline void mklink(const char *src, const char obj[HASH_LEN]); + static inline void mkdirs(const char *path); +static inline void copy_link(const char *src); static inline int copy_file(const char *src, const char *dst); + +static inline int linklen(const char *lnk); static inline void concat(char *dst, size_t n, const char *arg1, ...); static inline void *_xmalloc(size_t s, const char *file, int line); @@ -120,7 +126,7 @@ static inline void add(int argc, char *argv[]) errx(1, "Usage: %s [<files>]", argv[0]); init_stg_area(); - scan_res_cb = stage_file; + scan_res_cb = stage_entry; for (i = 1; i < argc; i++) { wt_path = argv[i]; @@ -206,7 +212,7 @@ static inline int cmp_files(const char *file1, const char *file2) int rc; int fd1, fd2; ssize_t r1, r2; - char buf1[BUFLEN], buf2[BUFLEN]; + char buf1[BUF_LEN], buf2[BUF_LEN]; if ((fd1 = open(file1, O_RDONLY)) < 0) err(1, "Couldn't open %s to compare", file1); @@ -216,8 +222,8 @@ static inline int cmp_files(const char *file1, const char *file2) rc = 0; do { - r1 = read(fd1, buf1, BUFLEN); - r2 = read(fd2, buf2, BUFLEN); + r1 = read(fd1, buf1, BUF_LEN); + r2 = read(fd2, buf2, BUF_LEN); if (r1 != r2 || memcmp(buf1, buf2, r1) != 0) { rc = 1; @@ -233,9 +239,14 @@ static inline int cmp_files(const char *file1, const char *file2) static inline int cmp_links(const char *link1, const char *link2) { ssize_t len1, len2; - char buf1[PATH_MAX], buf2[PATH_MAX]; + int buflen1, buflen2; + buflen1 = linklen(link1); + char buf1[buflen1]; len1 = readlink(link1, buf1, sizeof(buf1) - 1); + + buflen2 = linklen(link2); + char buf2[buflen2]; len2 = readlink(link2, buf2, sizeof(buf2) - 1); if (len1 < 0 || len2 < 0) @@ -272,42 +283,19 @@ static inline void init_stg_area(void) } } -static inline void stage_file(const char *file, char kind, int islnk) +static inline void stage_entry(const char *path, char kind, int islnk) { - int len, obj_len; - char obj_name[SHA1_DIGEST_STRING_LENGTH]; + char objname[HASH_LEN]; switch (kind) { case KIND_MOD: break; case KIND_NEW: if (!islnk) { - len = strlen(file); - obj_len = SHA1_DIGEST_STRING_LENGTH - 1; - - if (SHA1Data((const uint8_t *)file, len, obj_name) == NULL) - err(1, "Failed to compute hash for %s", file); - - size_t obj_sz = strlen(OBJ_DIR) + obj_len + 6; - char obj_path[obj_sz]; - concat(obj_path, obj_sz, OBJ_DIR, "/", obj_name, ".tmp", NULL); - copy_file(file, obj_path); - - // create link relative to tmp/ - size_t lnkt_sz = strlen("../obj/") + obj_len + 5; - char lnk_target[lnkt_sz]; - concat(lnk_target, lnkt_sz, "../obj/", obj_name, ".tmp", NULL); - - size_t lnkp_sz = strlen(TMP_DIR) + len + 2; - char lnk_path[lnkp_sz]; - concat(lnk_path, lnkp_sz, TMP_DIR, "/", file, NULL); - - mkdirs(lnk_path); - if (symlink(lnk_target, lnk_path) != 0) - err(1, "symlink error on %s", file); - } else { - - } + mkcopy(path, objname); + mklink(path, objname); + } else + copy_link(path); break; case KIND_DEL: break; @@ -316,11 +304,58 @@ static inline void stage_file(const char *file, char kind, int islnk) } } +static inline void mkcopy(const char *path, char dst[HASH_LEN]) +{ + int len, obj_len; + char obj_name[HASH_LEN]; + + len = strlen(path); + obj_len = HASH_LEN - 1; + if (SHA1Data((const uint8_t *)path, len, obj_name) == NULL) + err(1, "Failed to compute hash for %s", path); + + size_t obj_sz = strlen(OBJ_DIR) + obj_len + 6; + char obj_path[obj_sz]; + concat(obj_path, obj_sz, OBJ_DIR, "/", obj_name, ".tmp", NULL); + copy_file(path, obj_path); +} + +static inline void mklink(const char *src, const char obj[HASH_LEN]) +{ + // HASH_LEN includes null byte + size_t lnkt_sz = strlen("../obj/") + HASH_LEN + 4; + char lnk_target[lnkt_sz]; + concat(lnk_target, lnkt_sz, "../obj/", obj, ".tmp", NULL); + + size_t lnkp_sz = strlen(TMP_DIR) + strlen(src) + 2; + char lnk_path[lnkp_sz]; + concat(lnk_path, lnkp_sz, TMP_DIR, "/", src, NULL); + + mkdirs(lnk_path); + if (symlink(lnk_target, lnk_path) != 0) + err(1, "symlink error on %s", src); +} + static inline void print_status(const char *file, char kind, int islnk) { printf("[%c] %s\n", kind, file); } +static inline int linklen(const char *lnk) +{ + int len; + struct stat st; + + if (lstat(lnk, &st) != 0) + err(1, "lstat %s", lnk); + + len = st.st_size + 1; + if (MAX_PATH_LEN < len) + errx(1, "Link too long: %s", lnk); + + return len; +} + static inline void concat(char *dst, size_t n, const char *arg1, ...) { va_list ap; @@ -389,7 +424,7 @@ static inline int copy_file(const char *src, const char *dst) { int fdin, fdout; struct stat st; - char buf[BUFLEN], *outptr; + char buf[BUF_LEN], *outptr; ssize_t nread, nwrite, res; if ((fdin = open(src, O_RDONLY)) < 0) @@ -431,6 +466,28 @@ static inline int copy_file(const char *src, const char *dst) return (nread < 0) ? -1 : 0; } +static inline void copy_link(const char *src) +{ + int len; + ssize_t n; + + len = linklen(src); + char target[len]; + n = readlink(src, target, len); + if (n == -1) + err(1, "readlink %s", src); + + target[n] = '\0'; + + size_t dst_sz = strlen(TMP_DIR) + strlen(src) + 2; + char dst[dst_sz]; + concat(dst, dst_sz, TMP_DIR, src, NULL); + mkdirs(dst); + + if (symlink(target, dst) != 0) + err(1, "Link copy error %s", src); +} + static inline void mkdirs(const char *path) { char *p; |
