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 -------------------------------------------------*/