/* Called with the mutex already locked. */ krb5_error_code krb5_rc_dfl_close_no_free(krb5_context context, krb5_rcache id) { struct dfl_data *t = (struct dfl_data *)id->data; struct authlist *q; FREE(t->h); if (t->name) FREE(t->name); while ((q = t->a)) { t->a = q->na; FREE(q->rep.client); FREE(q->rep.server); FREE(q); } #ifndef NOIOSTUFF (void) krb5_rc_io_close(context, &t->d); #endif FREE(t); return 0; }
static krb5_error_code krb5_rc_dfl_recover_locked(krb5_context context, krb5_rcache id) { #ifdef NOIOSTUFF return KRB5_RC_NOIO; #else struct dfl_data *t = (struct dfl_data *)id->data; krb5_donot_replay *rep = 0; krb5_error_code retval; long max_size; int expired_entries = 0; krb5_int32 now; if ((retval = krb5_rc_io_open(context, &t->d, t->name))) { return retval; } t->recovering = 1; max_size = krb5_rc_io_size(context, &t->d); rep = NULL; if (krb5_rc_io_read(context, &t->d, (krb5_pointer) &t->lifespan, sizeof(t->lifespan))) { retval = KRB5_RC_IO; goto io_fail; } if (!(rep = (krb5_donot_replay *) malloc(sizeof(krb5_donot_replay)))) { retval = KRB5_RC_MALLOC; goto io_fail; } rep->client = rep->server = rep->msghash = NULL; if (krb5_timeofday(context, &now)) now = 0; /* now read in each auth_replay and insert into table */ for (;;) { if (krb5_rc_io_mark(context, &t->d)) { retval = KRB5_RC_IO; goto io_fail; } retval = krb5_rc_io_fetch(context, t, rep, (int) max_size); if (retval == KRB5_RC_IO_EOF) break; else if (retval != 0) goto io_fail; if (alive(now, rep, t->lifespan) != CMP_EXPIRED) { if (rc_store(context, id, rep, now, TRUE) == CMP_MALLOC) { retval = KRB5_RC_MALLOC; goto io_fail; } } else { expired_entries++; } /* * free fields allocated by rc_io_fetch */ free(rep->server); free(rep->client); if (rep->msghash) free(rep->msghash); rep->client = rep->server = rep->msghash = NULL; } retval = 0; krb5_rc_io_unmark(context, &t->d); /* * An automatic expunge here could remove the need for * mark/unmark but that would be inefficient. */ io_fail: krb5_rc_free_entry(context, &rep); if (retval) krb5_rc_io_close(context, &t->d); else if (expired_entries > EXCESSREPS) retval = krb5_rc_dfl_expunge_locked(context, id); t->recovering = 0; return retval; #endif }
krb5_error_code krb5_rc_io_move(krb5_context context, krb5_rc_iostuff *new1, krb5_rc_iostuff *old) { #if defined(_WIN32) || defined(__CYGWIN__) char *new_fn = NULL; char *old_fn = NULL; off_t offset = 0; krb5_error_code retval = 0; /* * Initial work around provided by Tom Sanfilippo to work around * poor Windows emulation of POSIX functions. Rename and dup has * different semantics! * * Additional fixes and explanation provided by [email protected]: * * First, we save the offset of "old". Then, we close and remove * the "new" file so we can do the rename. We also close "old" to * make sure the rename succeeds (though that might not be * necessary on some systems). * * Next, we do the rename. If all goes well, we seek the "new" * file to the position "old" was at. * * --- WARNING!!! --- * * Since "old" is now gone, we mourn its disappearance, but we * cannot emulate that Unix behavior... THIS BEHAVIOR IS * DIFFERENT FROM UNIX. However, it is ok because this function * gets called such that "old" gets closed right afterwards. */ offset = lseek(old->fd, 0, SEEK_CUR); new_fn = new1->fn; new1->fn = NULL; close(new1->fd); new1->fd = -1; unlink(new_fn); old_fn = old->fn; old->fn = NULL; close(old->fd); old->fd = -1; if (rename(old_fn, new_fn) == -1) { /* MUST be atomic! */ retval = KRB5_RC_IO_UNKNOWN; goto cleanup; } retval = krb5_rc_io_open_internal(context, new1, 0, new_fn); if (retval) goto cleanup; if (lseek(new1->fd, offset, SEEK_SET) == -1) { retval = KRB5_RC_IO_UNKNOWN; goto cleanup; } cleanup: free(new_fn); free(old_fn); return retval; #else char *fn = NULL; if (rename(old->fn, new1->fn) == -1) /* MUST be atomic! */ return KRB5_RC_IO_UNKNOWN; fn = new1->fn; new1->fn = NULL; /* avoid clobbering */ (void) krb5_rc_io_close(context, new1); new1->fn = fn; new1->fd = dup(old->fd); set_cloexec_fd(new1->fd); return 0; #endif }