lockfile: move documentation to lockfile.h and lockfile.c
Rearrange/rewrite it somewhat to fit its new environment. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Michael Haggerty committed
Aug 10, 2015 at 11:47 UTC
2db69de81deea4682579d0b9e6da40b4e9558c05
3 files changed
+283
-280
Documentation/technical/api-lockfile.txt
deleted
-220
@@ -1,220 +0,0 @@
1
-lockfile API
2
-============
3
-
4
-The lockfile API serves two purposes:
5
-
6
-* Mutual exclusion and atomic file updates. When we want to change a
7
- file, we create a lockfile `<filename>.lock`, write the new file
8
- contents into it, and then rename the lockfile to its final
9
- destination `<filename>`. We create the `<filename>.lock` file with
10
- `O_CREAT|O_EXCL` so that we can notice and fail if somebody else has
11
- already locked the file, then atomically rename the lockfile to its
12
- final destination to commit the changes and unlock the file.
13
-
14
-* Automatic cruft removal. If the program exits after we lock a file
15
- but before the changes have been committed, we want to make sure
16
- that we remove the lockfile. This is done by remembering the
17
- lockfiles we have created in a linked list and setting up an
18
- `atexit(3)` handler and a signal handler that clean up the
19
- lockfiles. This mechanism ensures that outstanding lockfiles are
20
- cleaned up if the program exits (including when `die()` is called)
21
- or if the program dies on a signal.
22
-
23
-Please note that lockfiles only block other writers. Readers do not
24
-block, but they are guaranteed to see either the old contents of the
25
-file or the new contents of the file (assuming that the filesystem
26
-implements `rename(2)` atomically).
27
-
28
-
29
-Calling sequence
30
-----------------
31
-
32
-The caller:
33
-
34
-* Allocates a `struct lock_file` either as a static variable or on the
35
- heap, initialized to zeros. Once you use the structure to call the
36
- `hold_lock_file_*` family of functions, it belongs to the lockfile
37
- subsystem and its storage must remain valid throughout the life of
38
- the program (i.e. you cannot use an on-stack variable to hold this
39
- structure).
40
-
41
-* Attempts to create a lockfile by passing that variable and the path
42
- of the final destination (e.g. `$GIT_DIR/index`) to
43
- `hold_lock_file_for_update` or `hold_lock_file_for_append`.
44
-
45
-* Writes new content for the destination file by either:
46
-
47
- * writing to the file descriptor returned by the `hold_lock_file_*`
48
- functions (also available via `lock->fd`).
49
-
50
- * calling `fdopen_lock_file` to get a `FILE` pointer for the open
51
- file and writing to the file using stdio.
52
-
53
-When finished writing, the caller can:
54
-
55
-* Close the file descriptor and rename the lockfile to its final
56
- destination by calling `commit_lock_file` or `commit_lock_file_to`.
57
-
58
-* Close the file descriptor and remove the lockfile by calling
59
- `rollback_lock_file`.
60
-
61
-* Close the file descriptor without removing or renaming the lockfile
62
- by calling `close_lock_file`, and later call `commit_lock_file`,
63
- `commit_lock_file_to`, `rollback_lock_file`, or `reopen_lock_file`.
64
-
65
-Even after the lockfile is committed or rolled back, the `lock_file`
66
-object must not be freed or altered by the caller. However, it may be
67
-reused; just pass it to another call of `hold_lock_file_for_update` or
68
-`hold_lock_file_for_append`.
69
-
70
-If the program exits before you have called one of `commit_lock_file`,
71
-`commit_lock_file_to`, `rollback_lock_file`, or `close_lock_file`, an
72
-`atexit(3)` handler will close and remove the lockfile, rolling back
73
-any uncommitted changes.
74
-
75
-If you need to close the file descriptor you obtained from a
76
-`hold_lock_file_*` function yourself, do so by calling
77
-`close_lock_file`. You should never call `close(2)` or `fclose(3)`
78
-yourself! Otherwise the `struct lock_file` structure would still think
79
-that the file descriptor needs to be closed, and a commit or rollback
80
-would result in duplicate calls to `close(2)`. Worse yet, if you close
81
-and then later open another file descriptor for a completely different
82
-purpose, then a commit or rollback might close that unrelated file
83
-descriptor.
84
-
85
-
86
-Error handling
87
---------------
88
-
89
-The `hold_lock_file_*` functions return a file descriptor on success
90
-or -1 on failure (unless `LOCK_DIE_ON_ERROR` is used; see below). On
91
-errors, `errno` describes the reason for failure. Errors can be
92
-reported by passing `errno` to one of the following helper functions:
93
-
94
-unable_to_lock_message::
95
-
96
- Append an appropriate error message to a `strbuf`.
97
-
98
-unable_to_lock_error::
99
-
100
- Emit an appropriate error message using `error()`.
101
-
102
-unable_to_lock_die::
103
-
104
- Emit an appropriate error message and `die()`.
105
-
106
-Similarly, `commit_lock_file`, `commit_lock_file_to`, and
107
-`close_lock_file` return 0 on success. On failure they set `errno`
108
-appropriately, do their best to roll back the lockfile, and return -1.
109
-
110
-
111
-Flags
112
------
113
-
114
-The following flags can be passed to `hold_lock_file_for_update` or
115
-`hold_lock_file_for_append`:
116
-
117
-LOCK_NO_DEREF::
118
-
119
- Usually symbolic links in the destination path are resolved
120
- and the lockfile is created by adding ".lock" to the resolved
121
- path. If `LOCK_NO_DEREF` is set, then the lockfile is created
122
- by adding ".lock" to the path argument itself. This option is
123
- used, for example, when locking a symbolic reference, which
124
- for backwards-compatibility reasons can be a symbolic link
125
- containing the name of the referred-to-reference.
126
-
127
-LOCK_DIE_ON_ERROR::
128
-
129
- If a lock is already taken for the file, `die()` with an error
130
- message. If this option is not specified, trying to lock a
131
- file that is already locked returns -1 to the caller.
132
-
133
-
134
-The functions
135
--------------
136
-
137
-hold_lock_file_for_update::
138
-
139
- Take a pointer to `struct lock_file`, the path of the file to
140
- be locked (e.g. `$GIT_DIR/index`) and a flags argument (see
141
- above). Attempt to create a lockfile for the destination and
142
- return the file descriptor for writing to the file.
143
-
144
-hold_lock_file_for_append::
145
-
146
- Like `hold_lock_file_for_update`, but before returning copy
147
- the existing contents of the file (if any) to the lockfile and
148
- position its write pointer at the end of the file.
149
-
150
-fdopen_lock_file::
151
-
152
- Associate a stdio stream with the lockfile. Return NULL
153
- (*without* rolling back the lockfile) on error. The stream is
154
- closed automatically when `close_lock_file` is called or when
155
- the file is committed or rolled back.
156
-
157
-get_locked_file_path::
158
-
159
- Return the path of the file that is locked by the specified
160
- lock_file object. The caller must free the memory.
161
-
162
-commit_lock_file::
163
-
164
- Take a pointer to the `struct lock_file` initialized with an
165
- earlier call to `hold_lock_file_for_update` or
166
- `hold_lock_file_for_append`, close the file descriptor, and
167
- rename the lockfile to its final destination. Return 0 upon
168
- success. On failure, roll back the lock file and return -1,
169
- with `errno` set to the value from the failing call to
170
- `close(2)` or `rename(2)`. It is a bug to call
171
- `commit_lock_file` for a `lock_file` object that is not
172
- currently locked.
173
-
174
-commit_lock_file_to::
175
-
176
- Like `commit_lock_file()`, except that it takes an explicit
177
- `path` argument to which the lockfile should be renamed. The
178
- `path` must be on the same filesystem as the lock file.
179
-
180
-rollback_lock_file::
181
-
182
- Take a pointer to the `struct lock_file` initialized with an
183
- earlier call to `hold_lock_file_for_update` or
184
- `hold_lock_file_for_append`, close the file descriptor and
185
- remove the lockfile. It is a NOOP to call
186
- `rollback_lock_file()` for a `lock_file` object that has
187
- already been committed or rolled back.
188
-
189
-close_lock_file::
190
-
191
- Take a pointer to the `struct lock_file` initialized with an
192
- earlier call to `hold_lock_file_for_update` or
193
- `hold_lock_file_for_append`. Close the file descriptor (and
194
- the file pointer if it has been opened using
195
- `fdopen_lock_file`). Return 0 upon success. On failure to
196
- `close(2)`, return a negative value and roll back the lock
197
- file. Usually `commit_lock_file`, `commit_lock_file_to`, or
198
- `rollback_lock_file` should eventually be called if
199
- `close_lock_file` succeeds.
200
-
201
-reopen_lock_file::
202
-
203
- Re-open a lockfile that has been closed (using
204
- `close_lock_file`) but not yet committed or rolled back. This
205
- can be used to implement a sequence of operations like the
206
- following:
207
-
208
- * Lock file.
209
-
210
- * Write new contents to lockfile, then `close_lock_file` to
211
- cause the contents to be written to disk.
212
-
213
- * Pass the name of the lockfile to another program to allow it
214
- (and nobody else) to inspect the contents you wrote, while
215
- still holding the lock yourself.
216
-
217
- * `reopen_lock_file` to reopen the lockfile. Make further
218
- updates to the contents.
219
-
220
- * `commit_lock_file` to make the final version permanent.
lockfile.c
+53
@@ -1,6 +1,59 @@
1
/*
2
* Copyright (c) 2005, Junio C Hamano
3
*/
4
+
5
+/*
6
+ * State diagram and cleanup
7
+ * -------------------------
8
+ *
9
+ * This module keeps track of all locked files in `lock_file_list` for
10
+ * use at cleanup. This list and the `lock_file` objects that comprise
11
+ * it must be kept in self-consistent states at all time, because the
12
+ * program can be interrupted any time by a signal, in which case the
13
+ * signal handler will walk through the list attempting to clean up
14
+ * any open lock files.
15
+ *
16
+ * The possible states of a `lock_file` object are as follows:
17
+ *
18
+ * - Uninitialized. In this state the object's `on_list` field must be
19
+ * zero but the rest of its contents need not be initialized. As
20
+ * soon as the object is used in any way, it is irrevocably
21
+ * registered in `lock_file_list`, and `on_list` is set.
22
+ *
23
+ * - Locked, lockfile open (after `hold_lock_file_for_update()`,
24
+ * `hold_lock_file_for_append()`, or `reopen_lock_file()`). In this
25
+ * state:
26
+ *
27
+ * - the lockfile exists
28
+ * - `active` is set
29
+ * - `filename` holds the filename of the lockfile
30
+ * - `fd` holds a file descriptor open for writing to the lockfile
31
+ * - `fp` holds a pointer to an open `FILE` object if and only if
32
+ * `fdopen_lock_file()` has been called on the object
33
+ * - `owner` holds the PID of the process that locked the file
34
+ *
35
+ * - Locked, lockfile closed (after successful `close_lock_file()`).
36
+ * Same as the previous state, except that the lockfile is closed
37
+ * and `fd` is -1.
38
+ *
39
+ * - Unlocked (after `commit_lock_file()`, `commit_lock_file_to()`,
40
+ * `rollback_lock_file()`, a failed attempt to lock, or a failed
41
+ * `close_lock_file()`). In this state:
42
+ *
43
+ * - `active` is unset
44
+ * - `filename` is empty (usually, though there are transitory
45
+ * states in which this condition doesn't hold). Client code should
46
+ * *not* rely on the filename being empty in this state.
47
+ * - `fd` is -1
48
+ * - the object is left registered in the `lock_file_list`, and
49
+ * `on_list` is set.
50
+ *
51
+ * A lockfile is owned by the process that created it. The `lock_file`
52
+ * has an `owner` field that records the owner's PID. This field is
53
+ * used to prevent a forked process from closing a lockfile created by
54
+ * its parent.
55
+ */
56
+
57
#include "cache.h"
58
#include "lockfile.h"
59
#include "sigchain.h"
lockfile.h
+230
-60
@@ -4,54 +4,103 @@
4
/*
5
* File write-locks as used by Git.
6
*
7
- * For an overview of how to use the lockfile API, please see
8
- *
9
- * Documentation/technical/api-lockfile.txt
10
- *
11
- * This module keeps track of all locked files in lock_file_list for
12
- * use at cleanup. This list and the lock_file objects that comprise
13
- * it must be kept in self-consistent states at all time, because the
14
- * program can be interrupted any time by a signal, in which case the
15
- * signal handler will walk through the list attempting to clean up
16
- * any open lock files.
17
- *
18
- * A lockfile is owned by the process that created it. The lock_file
19
- * object has an "owner" field that records its owner. This field is
20
- * used to prevent a forked process from closing a lockfile created by
21
- * its parent.
22
- *
23
- * The possible states of a lock_file object are as follows:
24
- *
25
- * - Uninitialized. In this state the object's on_list field must be
26
- * zero but the rest of its contents need not be initialized. As
27
- * soon as the object is used in any way, it is irrevocably
28
- * registered in the lock_file_list, and on_list is set.
29
- *
30
- * - Locked, lockfile open (after hold_lock_file_for_update(),
31
- * hold_lock_file_for_append(), or reopen_lock_file()). In this
32
- * state:
33
- * - the lockfile exists
34
- * - active is set
35
- * - filename holds the filename of the lockfile
36
- * - fd holds a file descriptor open for writing to the lockfile
37
- * - fp holds a pointer to an open FILE object if and only if
38
- * fdopen_lock_file() has been called on the object
39
- * - owner holds the PID of the process that locked the file
40
- *
41
- * - Locked, lockfile closed (after successful close_lock_file()).
42
- * Same as the previous state, except that the lockfile is closed
43
- * and fd is -1.
44
- *
45
- * - Unlocked (after commit_lock_file(), commit_lock_file_to(),
46
- * rollback_lock_file(), a failed attempt to lock, or a failed
47
- * close_lock_file()). In this state:
48
- * - active is unset
49
- * - filename is empty (usually, though there are transitory
50
- * states in which this condition doesn't hold). Client code should
51
- * *not* rely on the filename being empty in this state.
52
- * - fd is -1
53
- * - the object is left registered in the lock_file_list, and
54
- * on_list is set.
7
+ * The lockfile API serves two purposes:
8
+ *
9
+ * * Mutual exclusion and atomic file updates. When we want to change
10
+ * a file, we create a lockfile `<filename>.lock`, write the new
11
+ * file contents into it, and then rename the lockfile to its final
12
+ * destination `<filename>`. We create the `<filename>.lock` file
13
+ * with `O_CREAT|O_EXCL` so that we can notice and fail if somebody
14
+ * else has already locked the file, then atomically rename the
15
+ * lockfile to its final destination to commit the changes and
16
+ * unlock the file.
17
+ *
18
+ * * Automatic cruft removal. If the program exits after we lock a
19
+ * file but before the changes have been committed, we want to make
20
+ * sure that we remove the lockfile. This is done by remembering the
21
+ * lockfiles we have created in a linked list and setting up an
22
+ * `atexit(3)` handler and a signal handler that clean up the
23
+ * lockfiles. This mechanism ensures that outstanding lockfiles are
24
+ * cleaned up if the program exits (including when `die()` is
25
+ * called) or if the program is terminated by a signal.
26
+ *
27
+ * Please note that lockfiles only block other writers. Readers do not
28
+ * block, but they are guaranteed to see either the old contents of
29
+ * the file or the new contents of the file (assuming that the
30
+ * filesystem implements `rename(2)` atomically).
31
+ *
32
+ *
33
+ * Calling sequence
34
+ * ----------------
35
+ *
36
+ * The caller:
37
+ *
38
+ * * Allocates a `struct lock_file` either as a static variable or on
39
+ * the heap, initialized to zeros. Once you use the structure to
40
+ * call the `hold_lock_file_for_*()` family of functions, it belongs
41
+ * to the lockfile subsystem and its storage must remain valid
42
+ * throughout the life of the program (i.e. you cannot use an
43
+ * on-stack variable to hold this structure).
44
+ *
45
+ * * Attempts to create a lockfile by calling
46
+ * `hold_lock_file_for_update()` or `hold_lock_file_for_append()`.
47
+ *
48
+ * * Writes new content for the destination file by either:
49
+ *
50
+ * * writing to the file descriptor returned by the
51
+ * `hold_lock_file_for_*()` functions (also available via
52
+ * `lock->fd`).
53
+ *
54
+ * * calling `fdopen_lock_file()` to get a `FILE` pointer for the
55
+ * open file and writing to the file using stdio.
56
+ *
57
+ * When finished writing, the caller can:
58
+ *
59
+ * * Close the file descriptor and rename the lockfile to its final
60
+ * destination by calling `commit_lock_file()` or
61
+ * `commit_lock_file_to()`.
62
+ *
63
+ * * Close the file descriptor and remove the lockfile by calling
64
+ * `rollback_lock_file()`.
65
+ *
66
+ * * Close the file descriptor without removing or renaming the
67
+ * lockfile by calling `close_lock_file()`, and later call
68
+ * `commit_lock_file()`, `commit_lock_file_to()`,
69
+ * `rollback_lock_file()`, or `reopen_lock_file()`.
70
+ *
71
+ * Even after the lockfile is committed or rolled back, the
72
+ * `lock_file` object must not be freed or altered by the caller.
73
+ * However, it may be reused; just pass it to another call of
74
+ * `hold_lock_file_for_update()` or `hold_lock_file_for_append()`.
75
+ *
76
+ * If the program exits before `commit_lock_file()`,
77
+ * `commit_lock_file_to()`, or `rollback_lock_file()` is called, an
78
+ * `atexit(3)` handler will close and remove the lockfile, thereby
79
+ * rolling back any uncommitted changes.
80
+ *
81
+ * If you need to close the file descriptor you obtained from a
82
+ * `hold_lock_file_for_*()` function yourself, do so by calling
83
+ * `close_lock_file()`. You should never call `close(2)` or
84
+ * `fclose(3)` yourself, otherwise the `struct lock_file` structure
85
+ * would still think that the file descriptor needs to be closed, and
86
+ * a commit or rollback would result in duplicate calls to `close(2)`.
87
+ * Worse yet, if you close and then later open another file descriptor
88
+ * for a completely different purpose, then a commit or rollback might
89
+ * close that unrelated file descriptor.
90
+ *
91
+ * Error handling
92
+ * --------------
93
+ *
94
+ * The `hold_lock_file_for_*()` functions return a file descriptor on
95
+ * success or -1 on failure (unless `LOCK_DIE_ON_ERROR` is used; see
96
+ * "flags" below). On errors, `errno` describes the reason for
97
+ * failure. Errors can be reported by passing `errno` to
98
+ * `unable_to_lock_message()` or `unable_to_lock_die()`.
99
+ *
100
+ * Similarly, `commit_lock_file`, `commit_lock_file_to`, and
101
+ * `close_lock_file` return 0 on success. On failure they set `errno`
102
+ * appropriately, do their best to roll back the lockfile, and return
103
+ * -1.
104
*/
105
106
struct lock_file {
@@ -68,16 +117,51 @@ struct lock_file {
117
#define LOCK_SUFFIX ".lock"
118
#define LOCK_SUFFIX_LEN 5
119
120
+
121
+/*
122
+ * Flags
123
+ * -----
124
+ *
125
+ * The following flags can be passed to `hold_lock_file_for_update()`
126
+ * or `hold_lock_file_for_append()`.
127
+ */
128
+
129
+/*
130
+ * If a lock is already taken for the file, `die()` with an error
131
+ * message. If this flag is not specified, trying to lock a file that
132
+ * is already locked returns -1 to the caller.
133
+ */
134
#define LOCK_DIE_ON_ERROR 1
135
+
136
+/*
137
+ * Usually symbolic links in the destination path are resolved. This
138
+ * means that (1) the lockfile is created by adding ".lock" to the
139
+ * resolved path, and (2) upon commit, the resolved path is
140
+ * overwritten. However, if `LOCK_NO_DEREF` is set, then the lockfile
141
+ * is created by adding ".lock" to the path argument itself. This
142
+ * option is used, for example, when detaching a symbolic reference,
143
+ * which for backwards-compatibility reasons, can be a symbolic link
144
+ * containing the name of the referred-to-reference.
145
+ */
146
#define LOCK_NO_DEREF 2
147
74
-extern void unable_to_lock_message(const char *path, int err,
75
- struct strbuf *buf);
76
-extern NORETURN void unable_to_lock_die(const char *path, int err);
148
+/*
149
+ * Attempt to create a lockfile for the file at `path` and return a
150
+ * file descriptor for writing to it, or -1 on error. If the file is
151
+ * currently locked, retry with quadratic backoff for at least
152
+ * timeout_ms milliseconds. If timeout_ms is 0, try exactly once; if
153
+ * timeout_ms is -1, retry indefinitely. The flags argument and error
154
+ * handling are described above.
155
+ */
156
extern int hold_lock_file_for_update_timeout(
157
struct lock_file *lk, const char *path,
158
int flags, long timeout_ms);
159
160
+/*
161
+ * Attempt to create a lockfile for the file at `path` and return a
162
+ * file descriptor for writing to it, or -1 on error. The flags
163
+ * argument and error handling are described above.
164
+ */
165
static inline int hold_lock_file_for_update(
166
struct lock_file *lk, const char *path,
167
int flags)
@@ -85,15 +169,101 @@ static inline int hold_lock_file_for_update(
169
return hold_lock_file_for_update_timeout(lk, path, flags, 0);
170
}
171
88
-extern int hold_lock_file_for_append(struct lock_file *lk, const char *path,
89
- int flags);
172
+/*
173
+ * Like `hold_lock_file_for_update()`, but before returning copy the
174
+ * existing contents of the file (if any) to the lockfile and position
175
+ * its write pointer at the end of the file. The flags argument and
176
+ * error handling are described above.
177
+ */
178
+extern int hold_lock_file_for_append(struct lock_file *lk,
179
+ const char *path, int flags);
180
+
181
+/*
182
+ * Append an appropriate error message to `buf` following the failure
183
+ * of `hold_lock_file_for_update()` or `hold_lock_file_for_append()`
184
+ * to lock `path`. `err` should be the `errno` set by the failing
185
+ * call.
186
+ */
187
+extern void unable_to_lock_message(const char *path, int err,
188
+ struct strbuf *buf);
189
91
-extern FILE *fdopen_lock_file(struct lock_file *, const char *mode);
92
-extern char *get_locked_file_path(struct lock_file *);
93
-extern int commit_lock_file_to(struct lock_file *, const char *path);
94
-extern int commit_lock_file(struct lock_file *);
95
-extern int reopen_lock_file(struct lock_file *);
96
-extern int close_lock_file(struct lock_file *);
97
-extern void rollback_lock_file(struct lock_file *);
190
+/*
191
+ * Emit an appropriate error message and `die()` following the failure
192
+ * of `hold_lock_file_for_update()` or `hold_lock_file_for_append()`
193
+ * to lock `path`. `err` should be the `errno` set by the failing
194
+ * call.
195
+ */
196
+extern NORETURN void unable_to_lock_die(const char *path, int err);
197
+
198
+/*
199
+ * Associate a stdio stream with the lockfile (which must still be
200
+ * open). Return `NULL` (*without* rolling back the lockfile) on
201
+ * error. The stream is closed automatically when `close_lock_file()`
202
+ * is called or when the file is committed or rolled back.
203
+ */
204
+extern FILE *fdopen_lock_file(struct lock_file *lk, const char *mode);
205
+
206
+/*
207
+ * Return the path of the file that is locked by the specified
208
+ * lock_file object. The caller must free the memory.
209
+ */
210
+extern char *get_locked_file_path(struct lock_file *lk);
211
+
212
+/*
213
+ * If the lockfile is still open, close it (and the file pointer if it
214
+ * has been opened using `fdopen_lock_file()`) without renaming the
215
+ * lockfile over the file being locked. Return 0 upon success. On
216
+ * failure to `close(2)`, return a negative value and roll back the
217
+ * lock file. Usually `commit_lock_file()`, `commit_lock_file_to()`,
218
+ * or `rollback_lock_file()` should eventually be called if
219
+ * `close_lock_file()` succeeds.
220
+ */
221
+extern int close_lock_file(struct lock_file *lk);
222
+
223
+/*
224
+ * Re-open a lockfile that has been closed using `close_lock_file()`
225
+ * but not yet committed or rolled back. This can be used to implement
226
+ * a sequence of operations like the following:
227
+ *
228
+ * * Lock file.
229
+ *
230
+ * * Write new contents to lockfile, then `close_lock_file()` to
231
+ * cause the contents to be written to disk.
232
+ *
233
+ * * Pass the name of the lockfile to another program to allow it (and
234
+ * nobody else) to inspect the contents you wrote, while still
235
+ * holding the lock yourself.
236
+ *
237
+ * * `reopen_lock_file()` to reopen the lockfile. Make further updates
238
+ * to the contents.
239
+ *
240
+ * * `commit_lock_file()` to make the final version permanent.
241
+ */
242
+extern int reopen_lock_file(struct lock_file *lk);
243
+
244
+/*
245
+ * Commit the change represented by `lk`: close the file descriptor
246
+ * and/or file pointer if they are still open and rename the lockfile
247
+ * to its final destination. Return 0 upon success. On failure, roll
248
+ * back the lock file and return -1, with `errno` set to the value
249
+ * from the failing call to `close(2)` or `rename(2)`. It is a bug to
250
+ * call `commit_lock_file()` for a `lock_file` object that is not
251
+ * currently locked.
252
+ */
253
+extern int commit_lock_file(struct lock_file *lk);
254
+
255
+/*
256
+ * Like `commit_lock_file()`, but rename the lockfile to the provided
257
+ * `path`. `path` must be on the same filesystem as the lock file.
258
+ */
259
+extern int commit_lock_file_to(struct lock_file *lk, const char *path);
260
+
261
+/*
262
+ * Roll back `lk`: close the file descriptor and/or file pointer and
263
+ * remove the lockfile. It is a NOOP to call `rollback_lock_file()`
264
+ * for a `lock_file` object that has already been committed or rolled
265
+ * back.
266
+ */
267
+extern void rollback_lock_file(struct lock_file *lk);
268
269
#endif /* LOCKFILE_H */