X-Git-Url: https://git.cameronkatri.com/cgit.git/blobdiff_plain/6102bcfce46fd357566941d565b95f78510af79b..2a7dd4bf67edeff2c6c4f6d6d39d2d7f954d978a:/cache.c?ds=sidebyside diff --git a/cache.c b/cache.c index add647e..fa83ddc 100644 --- a/cache.c +++ b/cache.c @@ -1,6 +1,6 @@ /* cache.c: cache management * - * Copyright (C) 2006 Lars Hjemli + * Copyright (C) 2006-2014 cgit Development Team * * Licensed under GNU General Public License v2 * (see COPYING for full license text) @@ -15,6 +15,7 @@ #include "cgit.h" #include "cache.h" +#include "html.h" #define CACHE_BUFSIZE (1024 * 4) @@ -51,7 +52,7 @@ static int open_slot(struct cache_slot *slot) if (fstat(slot->cache_fd, &slot->cache_st)) return errno; - slot->bufsize = read(slot->cache_fd, slot->buf, sizeof(slot->buf)); + slot->bufsize = xread(slot->cache_fd, slot->buf, sizeof(slot->buf)); if (slot->bufsize < 0) return errno; @@ -66,27 +67,34 @@ static int open_slot(struct cache_slot *slot) } /* Close the active cache slot */ -static void close_slot(struct cache_slot *slot) +static int close_slot(struct cache_slot *slot) { + int err = 0; if (slot->cache_fd > 0) { - close(slot->cache_fd); - slot->cache_fd = -1; + if (close(slot->cache_fd)) + err = errno; + else + slot->cache_fd = -1; } + return err; } /* Print the content of the active cache slot (but skip the key). */ static int print_slot(struct cache_slot *slot) { - ssize_t i, j = 0; + ssize_t i, j; i = lseek(slot->cache_fd, slot->keylen + 1, SEEK_SET); if (i != slot->keylen + 1) return errno; - while((i=read(slot->cache_fd, slot->buf, sizeof(slot->buf))) > 0) - j = write(STDOUT_FILENO, slot->buf, i); + do { + i = j = xread(slot->cache_fd, slot->buf, sizeof(slot->buf)); + if (i > 0) + j = xwrite(STDOUT_FILENO, slot->buf, i); + } while (i > 0 && j == i); - if (j < 0) + if (i < 0 || j != i) return errno; else return 0; @@ -98,7 +106,7 @@ static int is_expired(struct cache_slot *slot) if (slot->ttl < 0) return 0; else - return slot->cache_st.st_mtime + slot->ttl*60 < time(NULL); + return slot->cache_st.st_mtime + slot->ttl * 60 < time(NULL); } /* Check if the slot has been modified since we opened it. @@ -116,12 +124,16 @@ static int is_modified(struct cache_slot *slot) } /* Close an open lockfile */ -static void close_lock(struct cache_slot *slot) +static int close_lock(struct cache_slot *slot) { + int err = 0; if (slot->lock_fd > 0) { - close(slot->lock_fd); - slot->lock_fd = -1; + if (close(slot->lock_fd)) + err = errno; + else + slot->lock_fd = -1; } + return err; } /* Create a lockfile used to store the generated content for a cache @@ -130,11 +142,12 @@ static void close_lock(struct cache_slot *slot) */ static int lock_slot(struct cache_slot *slot) { - slot->lock_fd = open(slot->lock_name, O_RDWR|O_CREAT|O_EXCL, - S_IRUSR|S_IWUSR); + slot->lock_fd = open(slot->lock_name, O_RDWR | O_CREAT | O_EXCL, + S_IRUSR | S_IWUSR); if (slot->lock_fd == -1) return errno; - write(slot->lock_fd, slot->key, slot->keylen + 1); + if (xwrite(slot->lock_fd, slot->key, slot->keylen + 1) < 0) + return errno; return 0; } @@ -150,7 +163,11 @@ static int unlock_slot(struct cache_slot *slot, int replace_old_slot) err = rename(slot->lock_name, slot->cache_name); else err = unlink(slot->lock_name); - return err; + + if (err) + return errno; + + return 0; } /* Generate the content for the current cache slot by redirecting @@ -177,7 +194,9 @@ static int fill_slot(struct cache_slot *slot) return errno; /* Close the temporary filedescriptor */ - close(tmp); + if (close(tmp)) + return errno; + return 0; } @@ -196,7 +215,7 @@ unsigned long hash_str(const char *str) if (!s) return h; - while(*s) { + while (*s) { h *= FNV_PRIME; h ^= *s++; } @@ -237,9 +256,14 @@ static int process_slot(struct cache_slot *slot) } } } - print_slot(slot); + if ((err = print_slot(slot)) != 0) { + cache_log("[cgit] error printing cache %s: %s (%d)\n", + slot->cache_name, + strerror(err), + err); + } close_slot(slot); - return 0; + return err; } /* If the cache slot does not exist (or its key doesn't match the @@ -274,7 +298,12 @@ static int process_slot(struct cache_slot *slot) // the lock file. slot->cache_fd = slot->lock_fd; unlock_slot(slot, 1); - err = print_slot(slot); + if ((err = print_slot(slot)) != 0) { + cache_log("[cgit] error printing cache %s: %s (%d)\n", + slot->cache_name, + strerror(err), + err); + } close_slot(slot); return err; } @@ -284,10 +313,11 @@ int cache_process(int size, const char *path, const char *key, int ttl, cache_fill_fn fn, void *cbdata) { unsigned long hash; - int len, i; - char filename[1024]; - char lockname[1024 + 5]; /* 5 = ".lock" */ + int i; + struct strbuf filename = STRBUF_INIT; + struct strbuf lockname = STRBUF_INIT; struct cache_slot slot; + int result; /* If the cache is disabled, just generate the content */ if (size <= 0) { @@ -301,41 +331,35 @@ int cache_process(int size, const char *path, const char *key, int ttl, fn(cbdata); return 0; } - len = strlen(path); - if (len > sizeof(filename) - 10) { /* 10 = "/01234567\0" */ - cache_log("[cgit] Cache path too long, caching is disabled: %s\n", - path); - fn(cbdata); - return 0; - } if (!key) key = ""; hash = hash_str(key) % size; - strcpy(filename, path); - if (filename[len - 1] != '/') - filename[len++] = '/'; - for(i = 0; i < 8; i++) { - sprintf(filename + len++, "%x", - (unsigned char)(hash & 0xf)); + strbuf_addstr(&filename, path); + strbuf_ensure_end(&filename, '/'); + for (i = 0; i < 8; i++) { + strbuf_addf(&filename, "%x", (unsigned char)(hash & 0xf)); hash >>= 4; } - filename[len] = '\0'; - strcpy(lockname, filename); - strcpy(lockname + len, ".lock"); + strbuf_addbuf(&lockname, &filename); + strbuf_addstr(&lockname, ".lock"); slot.fn = fn; slot.cbdata = cbdata; slot.ttl = ttl; - slot.cache_name = filename; - slot.lock_name = lockname; + slot.cache_name = filename.buf; + slot.lock_name = lockname.buf; slot.key = key; slot.keylen = strlen(key); - return process_slot(&slot); + result = process_slot(&slot); + + strbuf_release(&filename); + strbuf_release(&lockname); + return result; } /* Return a strftime formatted date/time * NB: the result from this function is to shared memory */ -char *sprintftime(const char *format, time_t time) +static char *sprintftime(const char *format, time_t time) { static char buf[64]; struct tm *tm; @@ -352,19 +376,14 @@ int cache_ls(const char *path) DIR *dir; struct dirent *ent; int err = 0; - struct cache_slot slot; - char fullname[1024]; - char *name; + struct cache_slot slot = { 0 }; + struct strbuf fullname = STRBUF_INIT; + size_t prefixlen; if (!path) { cache_log("[cgit] cache path not specified\n"); return -1; } - if (strlen(path) > 1024 - 10) { - cache_log("[cgit] cache path too long: %s\n", - path); - return -1; - } dir = opendir(path); if (!dir) { err = errno; @@ -372,31 +391,30 @@ int cache_ls(const char *path) path, strerror(err), err); return err; } - strcpy(fullname, path); - name = fullname + strlen(path); - if (*(name - 1) != '/') { - *name++ = '/'; - *name = '\0'; - } - slot.cache_name = fullname; - while((ent = readdir(dir)) != NULL) { + strbuf_addstr(&fullname, path); + strbuf_ensure_end(&fullname, '/'); + prefixlen = fullname.len; + while ((ent = readdir(dir)) != NULL) { if (strlen(ent->d_name) != 8) continue; - strcpy(name, ent->d_name); + strbuf_setlen(&fullname, prefixlen); + strbuf_addstr(&fullname, ent->d_name); + slot.cache_name = fullname.buf; if ((err = open_slot(&slot)) != 0) { cache_log("[cgit] unable to open path %s: %s (%d)\n", - fullname, strerror(err), err); + fullname.buf, strerror(err), err); continue; } - printf("%s %s %10lld %s\n", - name, - sprintftime("%Y-%m-%d %H:%M:%S", - slot.cache_st.st_mtime), - slot.cache_st.st_size, - slot.buf); + htmlf("%s %s %10"PRIuMAX" %s\n", + fullname.buf, + sprintftime("%Y-%m-%d %H:%M:%S", + slot.cache_st.st_mtime), + (uintmax_t)slot.cache_st.st_size, + slot.buf); close_slot(&slot); } closedir(dir); + strbuf_release(&fullname); return 0; }