e7f4fdd8034dcef4cd20633b80d8f9f3f8a075dd
3 * System-dependent key filing operations
5 * (c) 1999 Straylight/Edgeware
8 /*----- Licensing notice --------------------------------------------------*
10 * This file is part of Catacomb.
12 * Catacomb is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU Library General Public License as
14 * published by the Free Software Foundation; either version 2 of the
15 * License, or (at your option) any later version.
17 * Catacomb is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Library General Public License for more details.
22 * You should have received a copy of the GNU Library General Public
23 * License along with Catacomb; if not, write to the Free
24 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
28 /*----- Header files ------------------------------------------------------*/
35 #include <sys/types.h>
41 #include <mLib/dstr.h>
42 #include <mLib/lock.h>
46 /*----- Main code ---------------------------------------------------------*/
50 * Arguments: @int source@ = source file descriptor
51 * @int dest@ = destination file descriptor
53 * Returns: Zero if OK, nonzero otherwise.
55 * Use: Copies data from one file descriptor to another.
58 static int fdcopy(int source
, int dest
)
63 if (lseek(source
, 0, SEEK_SET
) < 0||
64 lseek(dest
, 0, SEEK_SET
) < 0 ||
65 ftruncate(dest
, 0) < 0)
68 int n
= read(source
, buf
, sizeof(buf
));
75 int nn
= write(dest
, p
, n
);
85 /* --- @key_save@ --- *
87 * Arguments: @key_file *f@ = pointer to key file block
89 * Returns: A @KWRITE_@ code indicating how well it worked.
91 * Use: Writes a key file's data back to the actual file. This code
92 * is extremely careful about error handling. It should usually
93 * be able to back out somewhere sensible, but it can tell when
94 * it's got itself into a real pickle and starts leaving well
97 * Callers, please make sure that you ring alarm bells when this
98 * function returns @KWRITE_BROKEN@.
101 int key_save(key_file
*f
)
103 dstr n_older
= DSTR_INIT
, n_old
= DSTR_INIT
, n_new
= DSTR_INIT
;
104 int rc
= KWRITE_FAIL
;
106 if (!(f
->f
& KF_MODIFIED
))
109 return (KWRITE_FAIL
);
111 /* --- Write a new key file out --- *
113 * Check for an error after each key line. This ought to be enough.
114 * Checking after each individual byte write and @fprintf@ isn't much fun.
117 dstr_putf(&n_new
, "%s.new", f
->name
);
124 if ((fp
= fopen(n_new
.buf
, "w")) == 0)
127 for (key_mkiter(&i
, f
); (k
= key_next(&i
)) != 0; ) {
128 if (key_extract(f
, k
, fp
, 0)) {
138 /* --- Set up the other filenames --- */
140 dstr_putf(&n_older
, "%s.older", f
->name
);
141 dstr_putf(&n_old
, "%s.old", f
->name
);
143 /* --- Move the current backup on one --- *
145 * If the `older' file exists, then we're in need of attention.
150 if (stat(n_older
.buf
, &st
) == 0 || errno
!= ENOENT
) {
155 if (rename(n_old
.buf
, n_older
.buf
) && errno
!= ENOENT
)
159 /* --- Copy the current file to the backup --- */
163 if ((fd
= open(n_old
.buf
, O_WRONLY
| O_CREAT
| O_EXCL
, 0600)) < 0)
165 if (fdcopy(fileno(f
->fp
), fd
)) {
173 /* --- Copy the newly created file to the current one --- *
175 * This is the dangerous bit.
180 if ((fd
= open(n_new
.buf
, O_RDONLY
)) < 0)
182 if (fdcopy(fd
, fileno(f
->fp
))) {
187 if (fsync(fileno(f
->fp
)))
191 /* --- Clean up --- *
193 * Remove the `new' file and the `older' backup. Then we're done.
198 dstr_destroy(&n_new
);
199 dstr_destroy(&n_old
);
200 dstr_destroy(&n_older
);
203 /* --- Failure while writing the new key file --- *
205 * I need to copy the backup back. If that fails then I'm really stuffed.
206 * If not, then I might as well try to get the backups sorted back out
215 if ((fd
= open(n_old
.buf
, O_RDONLY
)) < 0)
217 else if (fdcopy(fd
, fileno(f
->fp
))) {
222 if (fsync(fileno(f
->fp
)))
227 if (rc
== KWRITE_BROKEN
)
230 /* Now drop through */
232 /* --- Failure while writing the new backup --- *
234 * The new backup isn't any use. Try to recover the old one.
241 if (rename(n_older
.buf
, n_old
.buf
) && errno
!= ENOENT
)
245 /* Now drop through */
247 /* --- Failure while demoting the current backup --- *
249 * Leave the completed output file there for the operator in case he wants
254 dstr_destroy(&n_new
);
255 dstr_destroy(&n_old
);
256 dstr_destroy(&n_older
);
259 /* --- Failure during write of new data --- *
261 * Clean up the new file and return. These errors can never cause
268 dstr_destroy(&n_new
);
272 /* --- @key_lockfile@ --- *
274 * Arguments: @key_file *f@ = pointer to file structure to initialize
275 * @const char *file@ = pointer to the file name
276 * @unsigned how@ = opening options (@KOPEN_*@).
278 * Returns: Zero if it worked, nonzero otherwise.
280 * Use: Opens a keyfile and stores the information needed for
281 * continued access in the structure.
283 * If the file is opened with @KOPEN_WRITE@, it's created if
284 * necessary with read and write permissions for owner only, and
285 * locked for update while it's open.
287 * This is a system-dependent routine, and only really intended
288 * for the private use of @key_open@.
291 int key_lockfile(key_file
*f
, const char *file
, unsigned how
)
297 /* --- Handle the magic no-file option --- */
299 if (how
& KOPEN_NOFILE
) {
304 /* --- Lots of things depend on whether we're writing --- */
306 switch (how
& KOPEN_MASK
) {
313 of
= O_RDWR
| O_CREAT
;
322 /* --- Open and lock the file --- */
324 if ((fd
= open(file
, of
, 0600)) < 0)
326 if (fcntl(fd
, F_SETFD
, FD_CLOEXEC
) < 0 ||
327 lock_file(fd
, lf
) < 0 ||
328 (f
->fp
= fdopen(fd
, ff
)) == 0) {
336 /*----- That's all, folks -------------------------------------------------*/