l10n: git.pot: v2.12.0 round 1 (239 new, 15 removed)
[gitweb.git] / lockfile.h
index a483cc9ff3e3d9e9b693d4d45b9b5d1d737e1608..7b715f9e7754882061dde0220d13fdc7d0d6c252 100644 (file)
@@ -29,6 +29,8 @@
  * the file or the new contents of the file (assuming that the
  * filesystem implements `rename(2)` atomically).
  *
+ * Most of the heavy lifting is done by the tempfile module (see
+ * "tempfile.h").
  *
  * Calling sequence
  * ----------------
@@ -42,8 +44,7 @@
  *   throughout the life of the program (i.e. you cannot use an
  *   on-stack variable to hold this structure).
  *
- * * Attempts to create a lockfile by calling
- *   `hold_lock_file_for_update()` or `hold_lock_file_for_append()`.
+ * * Attempts to create a lockfile by calling `hold_lock_file_for_update()`.
  *
  * * Writes new content for the destination file by either:
  *
  *   * calling `fdopen_lock_file()` to get a `FILE` pointer for the
  *     open file and writing to the file using stdio.
  *
+ *   Note that the file descriptor returned by hold_lock_file_for_update()
+ *   is marked O_CLOEXEC, so the new contents must be written by the
+ *   current process, not a spawned one.
+ *
  * When finished writing, the caller can:
  *
  * * Close the file descriptor and rename the lockfile to its final
  * Even after the lockfile is committed or rolled back, the
  * `lock_file` object must not be freed or altered by the caller.
  * However, it may be reused; just pass it to another call of
- * `hold_lock_file_for_update()` or `hold_lock_file_for_append()`.
+ * `hold_lock_file_for_update()`.
  *
  * If the program exits before `commit_lock_file()`,
- * `commit_lock_file_to()`, or `rollback_lock_file()` is called, an
- * `atexit(3)` handler will close and remove the lockfile, thereby
- * rolling back any uncommitted changes.
+ * `commit_lock_file_to()`, or `rollback_lock_file()` is called, the
+ * tempfile module will close and remove the lockfile, thereby rolling
+ * back any uncommitted changes.
  *
  * If you need to close the file descriptor you obtained from a
  * `hold_lock_file_for_*()` function yourself, do so by calling
- * `close_lock_file()`. You should never call `close(2)` or
- * `fclose(3)` yourself, otherwise the `struct lock_file` structure
- * would still think that the file descriptor needs to be closed, and
- * a commit or rollback would result in duplicate calls to `close(2)`.
- * Worse yet, if you close and then later open another file descriptor
- * for a completely different purpose, then a commit or rollback might
- * close that unrelated file descriptor.
+ * `close_lock_file()`. See "tempfile.h" for more information.
+ *
+ *
+ * Under the covers, a lockfile is just a tempfile with a few helper
+ * functions. In particular, the state diagram and the cleanup
+ * machinery are all implemented in the tempfile module.
+ *
  *
  * Error handling
  * --------------
  * -1.
  */
 
+#include "tempfile.h"
+
 struct lock_file {
-       struct lock_file *volatile next;
-       volatile sig_atomic_t active;
-       volatile int fd;
-       FILE *volatile fp;
-       volatile pid_t owner;
-       char on_list;
-       struct strbuf filename;
+       struct tempfile tempfile;
 };
 
 /* String appended to a filename to derive the lockfile name: */
@@ -122,17 +123,22 @@ struct lock_file {
  * Flags
  * -----
  *
- * The following flags can be passed to `hold_lock_file_for_update()`
- * or `hold_lock_file_for_append()`.
+ * The following flags can be passed to `hold_lock_file_for_update()`.
  */
 
 /*
  * If a lock is already taken for the file, `die()` with an error
  * message. If this flag is not specified, trying to lock a file that
- * is already locked returns -1 to the caller.
+ * is already locked silently returns -1 to the caller, or ...
  */
 #define LOCK_DIE_ON_ERROR 1
 
+/*
+ * ... this flag can be passed instead to return -1 and give the usual
+ * error message upon an error.
+ */
+#define LOCK_REPORT_ON_ERROR 4
+
 /*
  * Usually symbolic links in the destination path are resolved. This
  * means that (1) the lockfile is created by adding ".lock" to the
@@ -169,28 +175,18 @@ static inline int hold_lock_file_for_update(
        return hold_lock_file_for_update_timeout(lk, path, flags, 0);
 }
 
-/*
- * Like `hold_lock_file_for_update()`, but before returning copy the
- * existing contents of the file (if any) to the lockfile and position
- * its write pointer at the end of the file. The flags argument and
- * error handling are described above.
- */
-extern int hold_lock_file_for_append(struct lock_file *lk,
-                                    const char *path, int flags);
-
 /*
  * Append an appropriate error message to `buf` following the failure
- * of `hold_lock_file_for_update()` or `hold_lock_file_for_append()`
- * to lock `path`. `err` should be the `errno` set by the failing
- * call.
+ * of `hold_lock_file_for_update()` to lock `path`. `err` should be the
+ * `errno` set by the failing call.
  */
 extern void unable_to_lock_message(const char *path, int err,
                                   struct strbuf *buf);
 
 /*
  * Emit an appropriate error message and `die()` following the failure
- * of `hold_lock_file_for_update()` or `hold_lock_file_for_append()`
- * to lock `path`. `err` should be the `errno` set by the failing
+ * of `hold_lock_file_for_update()` to lock `path`. `err` should be the
+ * `errno` set by the failing
  * call.
  */
 extern NORETURN void unable_to_lock_die(const char *path, int err);
@@ -201,7 +197,29 @@ extern NORETURN void unable_to_lock_die(const char *path, int err);
  * error. The stream is closed automatically when `close_lock_file()`
  * is called or when the file is committed or rolled back.
  */
-extern FILE *fdopen_lock_file(struct lock_file *lk, const char *mode);
+static inline FILE *fdopen_lock_file(struct lock_file *lk, const char *mode)
+{
+       return fdopen_tempfile(&lk->tempfile, mode);
+}
+
+/*
+ * Return the path of the lockfile. The return value is a pointer to a
+ * field within the lock_file object and should not be freed.
+ */
+static inline const char *get_lock_file_path(struct lock_file *lk)
+{
+       return get_tempfile_path(&lk->tempfile);
+}
+
+static inline int get_lock_file_fd(struct lock_file *lk)
+{
+       return get_tempfile_fd(&lk->tempfile);
+}
+
+static inline FILE *get_lock_file_fp(struct lock_file *lk)
+{
+       return get_tempfile_fp(&lk->tempfile);
+}
 
 /*
  * Return the path of the file that is locked by the specified
@@ -218,7 +236,10 @@ extern char *get_locked_file_path(struct lock_file *lk);
  * or `rollback_lock_file()` should eventually be called if
  * `close_lock_file()` succeeds.
  */
-extern int close_lock_file(struct lock_file *lk);
+static inline int close_lock_file(struct lock_file *lk)
+{
+       return close_tempfile(&lk->tempfile);
+}
 
 /*
  * Re-open a lockfile that has been closed using `close_lock_file()`
@@ -239,7 +260,10 @@ extern int close_lock_file(struct lock_file *lk);
  *
  * * `commit_lock_file()` to make the final version permanent.
  */
-extern int reopen_lock_file(struct lock_file *lk);
+static inline int reopen_lock_file(struct lock_file *lk)
+{
+       return reopen_tempfile(&lk->tempfile);
+}
 
 /*
  * Commit the change represented by `lk`: close the file descriptor
@@ -256,7 +280,10 @@ extern int commit_lock_file(struct lock_file *lk);
  * Like `commit_lock_file()`, but rename the lockfile to the provided
  * `path`. `path` must be on the same filesystem as the lock file.
  */
-extern int commit_lock_file_to(struct lock_file *lk, const char *path);
+static inline int commit_lock_file_to(struct lock_file *lk, const char *path)
+{
+       return rename_tempfile(&lk->tempfile, path);
+}
 
 /*
  * Roll back `lk`: close the file descriptor and/or file pointer and
@@ -264,6 +291,9 @@ extern int commit_lock_file_to(struct lock_file *lk, const char *path);
  * for a `lock_file` object that has already been committed or rolled
  * back.
  */
-extern void rollback_lock_file(struct lock_file *lk);
+static inline void rollback_lock_file(struct lock_file *lk)
+{
+       delete_tempfile(&lk->tempfile);
+}
 
 #endif /* LOCKFILE_H */