3 * $Id: key-file.c,v 1.1 1999/12/22 15:47:48 mdw Exp $
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 /*----- Revision history --------------------------------------------------*
32 * $Log: key-file.c,v $
33 * Revision 1.1 1999/12/22 15:47:48 mdw
34 * Major key-management revision.
38 /*----- Header files ------------------------------------------------------*/
45 #include <sys/types.h>
51 #include <mLib/dstr.h>
52 #include <mLib/lock.h>
56 /*----- Main code ---------------------------------------------------------*/
60 * Arguments: @int source@ = source file descriptor
61 * @int dest@ = destination file descriptor
63 * Returns: Zero if OK, nonzero otherwise.
65 * Use: Copies data from one file descriptor to another.
68 static int fdcopy(int source
, int dest
)
72 if (lseek(source
, 0, SEEK_SET
) < 0||
73 lseek(dest
, 0, SEEK_SET
) < 0 ||
74 ftruncate(dest
, 0) < 0)
77 int n
= read(source
, buf
, sizeof(buf
));
82 else if (write(dest
, buf
, n
) < 0)
88 /* --- @key_save@ --- *
90 * Arguments: @key_file *f@ = pointer to key file block
92 * Returns: A @KWRITE_@ code indicating how well it worked.
94 * Use: Writes a key file's data back to the actual file. This code
95 * is extremely careful about error handling. It should usually
96 * be able to back out somewhere sensible, but it can tell when
97 * it's got itself into a real pickle and starts leaving well
100 * Callers, please make sure that you ring alarm bells when this
101 * function returns @KWRITE_BROKEN@.
104 int key_save(key_file
*f
)
106 dstr n_older
= DSTR_INIT
, n_old
= DSTR_INIT
, n_new
= DSTR_INIT
;
107 int rc
= KWRITE_FAIL
;
109 if (!(f
->f
& KF_MODIFIED
))
112 /* --- Write a new key file out --- *
114 * Check for an error after each key line. This ought to be enough.
115 * Checking after each individual byte write and @fprintf@ isn't much fun.
118 dstr_putf(&n_new
, "%s.new", f
->name
);
125 if ((fp
= fopen(n_new
.buf
, "w")) == 0)
128 for (key_mkiter(&i
, f
); (k
= key_next(&i
)) != 0; ) {
129 if (key_extract(f
, k
, fp
, 0)) {
139 /* --- Set up the other filenames --- */
141 dstr_putf(&n_older
, "%s.older", f
->name
);
142 dstr_putf(&n_old
, "%s.old", f
->name
);
144 /* --- Move the current backup on one --- *
146 * If the `older' file exists, then we're in need of attention.
151 if (stat(n_older
.buf
, &st
) == 0 || errno
!= ENOENT
) {
156 if (rename(n_old
.buf
, n_older
.buf
) && errno
!= ENOENT
)
160 /* --- Copy the current file to the backup --- */
164 if ((fd
= open(n_old
.buf
, O_WRONLY
| O_CREAT
| O_EXCL
, 0600)) < 0)
166 if (fdcopy(fileno(f
->fp
), fd
)) {
174 /* --- Copy the newly created file to the current one --- *
176 * This is the dangerous bit.
181 if ((fd
= open(n_new
.buf
, O_RDONLY
)) < 0)
183 if (fdcopy(fd
, fileno(f
->fp
))) {
188 if (fsync(fileno(f
->fp
)))
192 /* --- Clean up --- *
194 * Remove the `new' file and the `older' backup. Then we're done.
201 /* --- Failure while writing the new key file --- *
203 * I need to copy the backup back. If that fails then I'm really stuffed.
204 * If not, then I might as well try to get the backups sorted back out
213 if ((fd
= open(n_old
.buf
, O_RDONLY
)) < 0)
215 else if (fdcopy(fd
, fileno(f
->fp
))) {
220 if (fsync(fileno(f
->fp
)))
225 if (rc
== KWRITE_BROKEN
)
228 /* Now drop through */
230 /* --- Failure while writing the new backup --- *
232 * The new backup isn't any use. Try to recover the old one.
239 if (rename(n_older
.buf
, n_old
.buf
) && errno
!= ENOENT
)
243 /* Now drop through */
245 /* --- Failure while demoting the current backup --- *
247 * Leave the completed output file there for the operator in case he wants
252 dstr_destroy(&n_new
);
253 dstr_destroy(&n_old
);
254 dstr_destroy(&n_older
);
257 /* --- Failure during write of new data --- *
259 * Clean up the new file and return. These errors can never cause
266 dstr_destroy(&n_new
);
270 /* --- @key_lockfile@ --- *
272 * Arguments: @key_file *f@ = pointer to file structure to initialize
273 * @const char *file@ = pointer to the file name
274 * @int how@ = opening options (@KOPEN_*@).
276 * Returns: Zero if it worked, nonzero otherwise.
278 * Use: Opens a keyfile and stores the information needed for
279 * continued access in the structure.
281 * If the file is opened with @KOPEN_WRITE@, it's created if
282 * necessary with read and write permissions for owner only, and
283 * locked for update while it's open.
285 * This is a system-dependent routine, and only really intended
286 * for the private use of @key_open@.
289 int key_lockfile(key_file
*f
, const char *file
, int how
)
295 /* --- Lots of things depend on whether we're writing --- */
304 of
= O_RDWR
| O_CREAT
;
313 /* --- Open and lock the file --- */
315 if ((fd
= open(file
, of
, 0600)) < 0)
317 if (fcntl(fd
, F_SETFD
, FD_CLOEXEC
) < 0 ||
318 lock_file(fd
, lf
) < 0 ||
319 (f
->fp
= fdopen(fd
, ff
)) == 0) {
327 /*----- That's all, folks -------------------------------------------------*/