5 * System-dependent key filing operations
7 * (c) 1999 Straylight/Edgeware
10 /*----- Licensing notice --------------------------------------------------*
12 * This file is part of Catacomb.
14 * Catacomb is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU Library General Public License as
16 * published by the Free Software Foundation; either version 2 of the
17 * License, or (at your option) any later version.
19 * Catacomb is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Library General Public License for more details.
24 * You should have received a copy of the GNU Library General Public
25 * License along with Catacomb; if not, write to the Free
26 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
30 /*----- Header files ------------------------------------------------------*/
37 #include <sys/types.h>
43 #include <mLib/dstr.h>
44 #include <mLib/lock.h>
48 /*----- Main code ---------------------------------------------------------*/
52 * Arguments: @int source@ = source file descriptor
53 * @int dest@ = destination file descriptor
55 * Returns: Zero if OK, nonzero otherwise.
57 * Use: Copies data from one file descriptor to another.
60 static int fdcopy(int source, int dest)
65 if (lseek(source, 0, SEEK_SET) < 0||
66 lseek(dest, 0, SEEK_SET) < 0 ||
67 ftruncate(dest, 0) < 0)
70 int n = read(source, buf, sizeof(buf));
77 int nn = write(dest, p, n);
87 /* --- @key_save@ --- *
89 * Arguments: @key_file *f@ = pointer to key file block
91 * Returns: A @KWRITE_@ code indicating how well it worked.
93 * Use: Writes a key file's data back to the actual file. This code
94 * is extremely careful about error handling. It should usually
95 * be able to back out somewhere sensible, but it can tell when
96 * it's got itself into a real pickle and starts leaving well
99 * Callers, please make sure that you ring alarm bells when this
100 * function returns @KWRITE_BROKEN@.
103 int key_save(key_file *f)
105 dstr n_older = DSTR_INIT, n_old = DSTR_INIT, n_new = DSTR_INIT;
106 int rc = KWRITE_FAIL;
108 if (!(f->f & KF_MODIFIED))
111 return (KWRITE_FAIL);
113 /* --- Write a new key file out --- *
115 * Check for an error after each key line. This ought to be enough.
116 * Checking after each individual byte write and @fprintf@ isn't much fun.
119 dstr_putf(&n_new, "%s.new", f->name);
126 if ((fp = fopen(n_new.buf, "w")) == 0)
129 for (key_mkiter(&i, f); (k = key_next(&i)) != 0; ) {
130 if (key_extract(f, k, fp, 0)) {
140 /* --- Set up the other filenames --- */
142 dstr_putf(&n_older, "%s.older", f->name);
143 dstr_putf(&n_old, "%s.old", f->name);
145 /* --- Move the current backup on one --- *
147 * If the `older' file exists, then we're in need of attention.
152 if (stat(n_older.buf, &st) == 0 || errno != ENOENT) {
157 if (rename(n_old.buf, n_older.buf) && errno != ENOENT)
161 /* --- Copy the current file to the backup --- */
165 if ((fd = open(n_old.buf, O_WRONLY | O_CREAT | O_EXCL, 0600)) < 0)
167 if (fdcopy(fileno(f->fp), fd)) {
175 /* --- Copy the newly created file to the current one --- *
177 * This is the dangerous bit.
182 if ((fd = open(n_new.buf, O_RDONLY)) < 0)
184 if (fdcopy(fd, fileno(f->fp))) {
189 if (fsync(fileno(f->fp)))
193 /* --- Clean up --- *
195 * Remove the `new' file and the `older' backup. Then we're done.
202 /* --- Failure while writing the new key file --- *
204 * I need to copy the backup back. If that fails then I'm really stuffed.
205 * If not, then I might as well try to get the backups sorted back out
214 if ((fd = open(n_old.buf, O_RDONLY)) < 0)
216 else if (fdcopy(fd, fileno(f->fp))) {
221 if (fsync(fileno(f->fp)))
226 if (rc == KWRITE_BROKEN)
229 /* Now drop through */
231 /* --- Failure while writing the new backup --- *
233 * The new backup isn't any use. Try to recover the old one.
240 if (rename(n_older.buf, n_old.buf) && errno != ENOENT)
244 /* Now drop through */
246 /* --- Failure while demoting the current backup --- *
248 * Leave the completed output file there for the operator in case he wants
253 dstr_destroy(&n_new);
254 dstr_destroy(&n_old);
255 dstr_destroy(&n_older);
258 /* --- Failure during write of new data --- *
260 * Clean up the new file and return. These errors can never cause
267 dstr_destroy(&n_new);
271 /* --- @key_lockfile@ --- *
273 * Arguments: @key_file *f@ = pointer to file structure to initialize
274 * @const char *file@ = pointer to the file name
275 * @unsigned how@ = opening options (@KOPEN_*@).
277 * Returns: Zero if it worked, nonzero otherwise.
279 * Use: Opens a keyfile and stores the information needed for
280 * continued access in the structure.
282 * If the file is opened with @KOPEN_WRITE@, it's created if
283 * necessary with read and write permissions for owner only, and
284 * locked for update while it's open.
286 * This is a system-dependent routine, and only really intended
287 * for the private use of @key_open@.
290 int key_lockfile(key_file *f, const char *file, unsigned how)
296 /* --- Handle the magic no-file option --- */
298 if (how & KOPEN_NOFILE) {
303 /* --- Lots of things depend on whether we're writing --- */
305 switch (how & KOPEN_MASK) {
312 of = O_RDWR | O_CREAT;
321 /* --- Open and lock the file --- */
323 if ((fd = open(file, of, 0600)) < 0)
325 if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0 ||
326 lock_file(fd, lf) < 0 ||
327 (f->fp = fdopen(fd, ff)) == 0) {
335 /*----- That's all, folks -------------------------------------------------*/