Hash :
19d9beb7
Author :
Date :
2015-07-24T19:22:41
filebuf: remove lockfile upon rename errors When we have an error renaming the lockfile, we need to make sure that we remove it upon cleanup. For this, we need to keep track of whether we opened the file and whether the rename succeeded. If we did create the lockfile but the rename did not succeed, we remove the lockfile. This won't protect against all errors, but the most common ones (target file is open) does get handled.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef INCLUDE_filebuf_h__
#define INCLUDE_filebuf_h__
#include "fileops.h"
#include "hash.h"
#include <zlib.h>
#ifdef GIT_THREADS
# define GIT_FILEBUF_THREADS
#endif
#define GIT_FILEBUF_HASH_CONTENTS (1 << 0)
#define GIT_FILEBUF_APPEND (1 << 2)
#define GIT_FILEBUF_FORCE (1 << 3)
#define GIT_FILEBUF_TEMPORARY (1 << 4)
#define GIT_FILEBUF_DO_NOT_BUFFER (1 << 5)
#define GIT_FILEBUF_DEFLATE_SHIFT (6)
#define GIT_FILELOCK_EXTENSION ".lock\0"
#define GIT_FILELOCK_EXTLENGTH 6
typedef struct git_filebuf git_filebuf;
struct git_filebuf {
char *path_original;
char *path_lock;
int (*write)(git_filebuf *file, void *source, size_t len);
bool compute_digest;
git_hash_ctx digest;
unsigned char *buffer;
unsigned char *z_buf;
z_stream zs;
int flush_mode;
size_t buf_size, buf_pos;
git_file fd;
bool fd_is_open;
bool created_lock;
bool did_rename;
bool do_not_buffer;
int last_error;
};
#define GIT_FILEBUF_INIT {0}
/*
* The git_filebuf object lifecycle is:
* - Allocate git_filebuf, preferably using GIT_FILEBUF_INIT.
*
* - Call git_filebuf_open() to initialize the filebuf for use.
*
* - Make as many calls to git_filebuf_write(), git_filebuf_printf(),
* git_filebuf_reserve() as you like. The error codes for these
* functions don't need to be checked. They are stored internally
* by the file buffer.
*
* - While you are writing, you may call git_filebuf_hash() to get
* the hash of all you have written so far. This function will
* fail if any of the previous writes to the buffer failed.
*
* - To close the git_filebuf, you may call git_filebuf_commit() or
* git_filebuf_commit_at() to save the file, or
* git_filebuf_cleanup() to abandon the file. All of these will
* free the git_filebuf object. Likewise, all of these will fail
* if any of the previous writes to the buffer failed, and set
* an error code accordingly.
*/
int git_filebuf_write(git_filebuf *lock, const void *buff, size_t len);
int git_filebuf_reserve(git_filebuf *file, void **buff, size_t len);
int git_filebuf_printf(git_filebuf *file, const char *format, ...) GIT_FORMAT_PRINTF(2, 3);
int git_filebuf_open(git_filebuf *lock, const char *path, int flags, mode_t mode);
int git_filebuf_commit(git_filebuf *lock);
int git_filebuf_commit_at(git_filebuf *lock, const char *path);
void git_filebuf_cleanup(git_filebuf *lock);
int git_filebuf_hash(git_oid *oid, git_filebuf *file);
int git_filebuf_flush(git_filebuf *file);
int git_filebuf_stats(time_t *mtime, size_t *size, git_filebuf *file);
#endif