void KRB5_CALLCONV profile_release(profile_t profile) { prf_file_t p, next; if (!profile || profile->magic != PROF_MAGIC_PROFILE) return; for (p = profile->first_file; p; p = next) { next = p->next; profile_close_file(p); } profile->magic = 0; free(profile); }
void KRB5_CALLCONV profile_release(profile_t profile) { prf_file_t p, next; if (!profile || profile->magic != PROF_MAGIC_PROFILE) return; if (profile->vt) { /* Flush the profile and then delegate to profile_abandon. */ if (profile->vt->flush) profile->vt->flush(profile->cbdata); profile_abandon(profile); return; } else { for (p = profile->first_file; p; p = next) { next = p->next; profile_close_file(p); } } profile->magic = 0; free(profile); }
errcode_t profile_open_file(const_profile_filespec_t filespec, prf_file_t *ret_prof) { prf_file_t prf; errcode_t retval; char *home_env = 0; prf_data_t data; char *expanded_filename; retval = CALL_INIT_FUNCTION(profile_library_initializer); if (retval) return retval; scan_shared_trees_unlocked(); prf = malloc(sizeof(struct _prf_file_t)); if (!prf) return ENOMEM; memset(prf, 0, sizeof(struct _prf_file_t)); prf->magic = PROF_MAGIC_FILE; if (filespec[0] == '~' && filespec[1] == '/') { home_env = getenv("HOME"); #ifdef HAVE_PWD_H if (home_env == NULL) { uid_t uid; struct passwd *pw, pwx; char pwbuf[BUFSIZ]; uid = getuid(); if (!k5_getpwuid_r(uid, &pwx, pwbuf, sizeof(pwbuf), &pw) && pw != NULL && pw->pw_dir[0] != 0) home_env = pw->pw_dir; } #endif } if (home_env) { if (asprintf(&expanded_filename, "%s%s", home_env, filespec + 1) < 0) expanded_filename = 0; } else expanded_filename = strdup(filespec); if (expanded_filename == 0) { free(prf); return ENOMEM; } retval = k5_mutex_lock(&g_shared_trees_mutex); if (retval) { free(expanded_filename); free(prf); scan_shared_trees_unlocked(); return retval; } scan_shared_trees_locked(); for (data = g_shared_trees; data; data = data->next) { if (!strcmp(data->filespec, expanded_filename) /* Check that current uid has read access. */ && r_access(data->filespec)) break; } if (data) { data->refcount++; (void) k5_mutex_unlock(&g_shared_trees_mutex); retval = profile_update_file_data(data); free(expanded_filename); prf->data = data; *ret_prof = prf; scan_shared_trees_unlocked(); return retval; } (void) k5_mutex_unlock(&g_shared_trees_mutex); data = profile_make_prf_data(expanded_filename); if (data == NULL) { free(prf); free(expanded_filename); return ENOMEM; } free(expanded_filename); prf->data = data; retval = k5_mutex_init(&data->lock); if (retval) { free(data); free(prf); return retval; } retval = profile_update_file(prf); if (retval) { profile_close_file(prf); return retval; } retval = k5_mutex_lock(&g_shared_trees_mutex); if (retval) { profile_close_file(prf); scan_shared_trees_unlocked(); return retval; } scan_shared_trees_locked(); data->flags |= PROFILE_FILE_SHARED; data->next = g_shared_trees; g_shared_trees = data; scan_shared_trees_locked(); (void) k5_mutex_unlock(&g_shared_trees_mutex); *ret_prof = prf; return 0; }