Diffstat (limited to 'cache.c')
| -rw-r--r-- | cache.c | 114 |
1 files changed, 45 insertions, 69 deletions
@@ -13,23 +13,22 @@ * */ -#include "cgit.h" -#include "cache.h" -#include "html.h" #ifdef HAVE_LINUX_SENDFILE #include <sys/sendfile.h> #endif +#include "cgit.h" +#include "cache.h" +#include "html.h" #define CACHE_BUFSIZE (1024 * 4) struct cache_slot { const char *key; - size_t keylen; + int keylen; int ttl; cache_fill_fn fn; int cache_fd; int lock_fd; - int stdout_fd; const char *cache_name; const char *lock_name; int match; @@ -45,7 +44,7 @@ struct cache_slot { static int open_slot(struct cache_slot *slot) { char *bufz; - ssize_t bufkeylen = -1; + int bufkeylen = -1; slot->cache_fd = open(slot->cache_name, O_RDONLY); if (slot->cache_fd == -1) @@ -62,9 +61,8 @@ static int open_slot(struct cache_slot *slot) if (bufz) bufkeylen = bufz - slot->buf; - if (slot->key) - slot->match = bufkeylen == slot->keylen && - !memcmp(slot->key, slot->buf, bufkeylen + 1); + slot->match = bufkeylen == slot->keylen && + !memcmp(slot->key, slot->buf, bufkeylen + 1); return 0; } @@ -85,45 +83,40 @@ static int close_slot(struct cache_slot *slot) /* Print the content of the active cache slot (but skip the key). */ static int print_slot(struct cache_slot *slot) { - off_t off; #ifdef HAVE_LINUX_SENDFILE - off_t size; -#endif - - off = slot->keylen + 1; + off_t start_off; + int ret; -#ifdef HAVE_LINUX_SENDFILE - size = slot->cache_st.st_size; + start_off = slot->keylen + 1; do { - ssize_t ret; - ret = sendfile(STDOUT_FILENO, slot->cache_fd, &off, size - off); + ret = sendfile(STDOUT_FILENO, slot->cache_fd, &start_off, + slot->cache_st.st_size - start_off); if (ret < 0) { if (errno == EAGAIN || errno == EINTR) continue; - /* Fall back to read/write on EINVAL or ENOSYS */ - if (errno == EINVAL || errno == ENOSYS) - break; return errno; } - if (off == size) - return 0; + return 0; } while (1); -#endif +#else + ssize_t i, j; - if (lseek(slot->cache_fd, off, SEEK_SET) != off) + i = lseek(slot->cache_fd, slot->keylen + 1, SEEK_SET); + if (i != slot->keylen + 1) return errno; do { - ssize_t ret; - ret = xread(slot->cache_fd, slot->buf, sizeof(slot->buf)); - if (ret < 0) - return errno; - if (ret == 0) - return 0; - if (write_in_full(STDOUT_FILENO, slot->buf, ret) < 0) - return errno; - } while (1); + 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 (i < 0 || j != i) + return errno; + else + return 0; +#endif } /* Check if the slot has expired */ @@ -168,25 +161,10 @@ static int close_lock(struct cache_slot *slot) */ static int lock_slot(struct cache_slot *slot) { - struct flock lock = { - .l_type = F_WRLCK, - .l_whence = SEEK_SET, - .l_start = 0, - .l_len = 0, - }; - - slot->lock_fd = open(slot->lock_name, O_RDWR | O_CREAT, + slot->lock_fd = open(slot->lock_name, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); if (slot->lock_fd == -1) return errno; - if (fcntl(slot->lock_fd, F_SETLK, &lock) < 0) { - int saved_errno = errno; - close(slot->lock_fd); - slot->lock_fd = -1; - return saved_errno; - } - if (ftruncate(slot->lock_fd, 0) < 0) - return errno; if (xwrite(slot->lock_fd, slot->key, slot->keylen + 1) < 0) return errno; return 0; @@ -205,13 +183,6 @@ static int unlock_slot(struct cache_slot *slot, int replace_old_slot) else err = unlink(slot->lock_name); - /* Restore stdout and close the temporary FD. */ - if (slot->stdout_fd >= 0) { - dup2(slot->stdout_fd, STDOUT_FILENO); - close(slot->stdout_fd); - slot->stdout_fd = -1; - } - if (err) return errno; @@ -223,9 +194,11 @@ static int unlock_slot(struct cache_slot *slot, int replace_old_slot) */ static int fill_slot(struct cache_slot *slot) { + int tmp; + /* Preserve stdout */ - slot->stdout_fd = dup(STDOUT_FILENO); - if (slot->stdout_fd == -1) + tmp = dup(STDOUT_FILENO); + if (tmp == -1) return errno; /* Redirect stdout to lockfile */ @@ -235,14 +208,18 @@ static int fill_slot(struct cache_slot *slot) /* Generate cache content */ slot->fn(); - /* Make sure any buffered data is flushed to the file */ - if (fflush(stdout)) - return errno; - /* update stat info */ if (fstat(slot->lock_fd, &slot->cache_st)) return errno; + /* Restore stdout */ + if (dup2(tmp, STDOUT_FILENO) == -1) + return errno; + + /* Close the temporary filedescriptor */ + if (close(tmp)) + return errno; + return 0; } @@ -315,7 +292,7 @@ static int process_slot(struct cache_slot *slot) /* If the cache slot does not exist (or its key doesn't match the * current key), lets try to create a new cache slot for this * request. If this fails (for whatever reason), lets just generate - * the content without caching it and fool the caller to believe + * the content without caching it and fool the caller to belive * everything worked out (but print a warning on stdout). */ @@ -390,7 +367,6 @@ int cache_process(int size, const char *path, const char *key, int ttl, strbuf_addstr(&lockname, ".lock"); slot.fn = fn; slot.ttl = ttl; - slot.stdout_fd = -1; slot.cache_name = filename.buf; slot.lock_name = lockname.buf; slot.key = key; @@ -408,12 +384,12 @@ int cache_process(int size, const char *path, const char *key, int ttl, static char *sprintftime(const char *format, time_t time) { static char buf[64]; - struct tm tm; + struct tm *tm; if (!time) return NULL; - gmtime_r(&time, &tm); - strftime(buf, sizeof(buf)-1, format, &tm); + tm = gmtime(&time); + strftime(buf, sizeof(buf)-1, format, tm); return buf; } @@ -422,7 +398,7 @@ int cache_ls(const char *path) DIR *dir; struct dirent *ent; int err = 0; - struct cache_slot slot = { NULL }; + struct cache_slot slot = { 0 }; struct strbuf fullname = STRBUF_INIT; size_t prefixlen; |