resolve_ref: use strbufs for internal buffers
[gitweb.git] / sha1_file.c
index ea78ba7cf062c92fe78e67ff4c0f5a0607e6aebd..2be1afdde0b1bde19583ad8fa183fb7f2546cc13 100644 (file)
@@ -377,15 +377,12 @@ void read_info_alternates(const char * relative_base, int depth)
        char *map;
        size_t mapsz;
        struct stat st;
-       const char alt_file_name[] = "info/alternates";
-       /* Given that relative_base is no longer than PATH_MAX,
-          ensure that "path" has enough space to append "/", the
-          file name, "info/alternates", and a trailing NUL.  */
-       char path[PATH_MAX + 1 + sizeof alt_file_name];
+       char *path;
        int fd;
 
-       sprintf(path, "%s/%s", relative_base, alt_file_name);
+       path = xstrfmt("%s/info/alternates", relative_base);
        fd = git_open_noatime(path);
+       free(path);
        if (fd < 0)
                return;
        if (fstat(fd, &st) || (st.st_size == 0)) {
@@ -674,13 +671,15 @@ static int check_packed_git_idx(const char *path, struct packed_git *p)
 int open_pack_index(struct packed_git *p)
 {
        char *idx_name;
+       size_t len;
        int ret;
 
        if (p->index_data)
                return 0;
 
-       idx_name = xstrdup(p->pack_name);
-       strcpy(idx_name + strlen(idx_name) - strlen(".pack"), ".idx");
+       if (!strip_suffix(p->pack_name, ".pack", &len))
+               die("BUG: pack_name does not end in .pack");
+       idx_name = xstrfmt("%.*s.idx", (int)len, p->pack_name);
        ret = check_packed_git_idx(idx_name, p);
        free(idx_name);
        return ret;
@@ -1149,11 +1148,12 @@ static void try_to_free_pack_memory(size_t size)
        release_pack_memory(size);
 }
 
-struct packed_git *add_packed_git(const char *path, int path_len, int local)
+struct packed_git *add_packed_git(const char *path, size_t path_len, int local)
 {
        static int have_set_try_to_free_routine;
        struct stat st;
-       struct packed_git *p = alloc_packed_git(path_len + 2);
+       size_t alloc;
+       struct packed_git *p;
 
        if (!have_set_try_to_free_routine) {
                have_set_try_to_free_routine = 1;
@@ -1164,18 +1164,22 @@ struct packed_git *add_packed_git(const char *path, int path_len, int local)
         * Make sure a corresponding .pack file exists and that
         * the index looks sane.
         */
-       path_len -= strlen(".idx");
-       if (path_len < 1) {
-               free(p);
+       if (!strip_suffix_mem(path, &path_len, ".idx"))
                return NULL;
-       }
+
+       /*
+        * ".pack" is long enough to hold any suffix we're adding (and
+        * the use xsnprintf double-checks that)
+        */
+       alloc = path_len + strlen(".pack") + 1;
+       p = alloc_packed_git(alloc);
        memcpy(p->pack_name, path, path_len);
 
-       strcpy(p->pack_name + path_len, ".keep");
+       xsnprintf(p->pack_name + path_len, alloc - path_len, ".keep");
        if (!access(p->pack_name, F_OK))
                p->pack_keep = 1;
 
-       strcpy(p->pack_name + path_len, ".pack");
+       xsnprintf(p->pack_name + path_len, alloc - path_len, ".pack");
        if (stat(p->pack_name, &st) || !S_ISREG(st.st_mode)) {
                free(p);
                return NULL;
@@ -1467,7 +1471,7 @@ int check_sha1_signature(const unsigned char *sha1, void *map,
                return -1;
 
        /* Generate the header */
-       hdrlen = sprintf(hdr, "%s %lu", typename(obj_type), size) + 1;
+       hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %lu", typename(obj_type), size) + 1;
 
        /* Sha1.. */
        git_SHA1_Init(&c);
@@ -1494,7 +1498,10 @@ int git_open_noatime(const char *name)
        static int sha1_file_open_flag = O_NOATIME;
 
        for (;;) {
-               int fd = open(name, O_RDONLY | sha1_file_open_flag);
+               int fd;
+
+               errno = 0;
+               fd = open(name, O_RDONLY | sha1_file_open_flag);
                if (fd >= 0)
                        return fd;
 
@@ -2930,7 +2937,7 @@ static void write_sha1_file_prepare(const void *buf, unsigned long len,
        git_SHA_CTX c;
 
        /* Generate the header */
-       *hdrlen = sprintf(hdr, "%s %lu", type, len)+1;
+       *hdrlen = xsnprintf(hdr, *hdrlen, "%s %lu", type, len)+1;
 
        /* Sha1.. */
        git_SHA1_Init(&c);
@@ -2993,7 +3000,7 @@ int hash_sha1_file(const void *buf, unsigned long len, const char *type,
                    unsigned char *sha1)
 {
        char hdr[32];
-       int hdrlen;
+       int hdrlen = sizeof(hdr);
        write_sha1_file_prepare(buf, len, type, sha1, hdr, &hdrlen);
        return 0;
 }
@@ -3139,7 +3146,7 @@ static int freshen_packed_object(const unsigned char *sha1)
 int write_sha1_file(const void *buf, unsigned long len, const char *type, unsigned char *sha1)
 {
        char hdr[32];
-       int hdrlen;
+       int hdrlen = sizeof(hdr);
 
        /* Normally if we have it in the pack then we do not bother writing
         * it out into .git/objects/??/?{38} file.
@@ -3157,7 +3164,8 @@ int hash_sha1_file_literally(const void *buf, unsigned long len, const char *typ
        int hdrlen, status = 0;
 
        /* type string, SP, %lu of the length plus NUL must fit this */
-       header = xmalloc(strlen(type) + 32);
+       hdrlen = strlen(type) + 32;
+       header = xmalloc(hdrlen);
        write_sha1_file_prepare(buf, len, type, sha1, header, &hdrlen);
 
        if (!(flags & HASH_WRITE_OBJECT))
@@ -3185,7 +3193,7 @@ int force_object_loose(const unsigned char *sha1, time_t mtime)
        buf = read_packed_sha1(sha1, &type, &len);
        if (!buf)
                return error("cannot read sha1_file for %s", sha1_to_hex(sha1));
-       hdrlen = sprintf(hdr, "%s %lu", typename(type), len) + 1;
+       hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %lu", typename(type), len) + 1;
        ret = write_loose_object(sha1, hdr, hdrlen, buf, len, mtime);
        free(buf);