/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* prof_file.c ---- routines that manipulate an individual profile file.
*/
#include <autoconf.h>
#include "prof_int.h"
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <string.h>
#include <stddef.h>
#include <errno.h>
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
#if defined(_WIN32)
#include <io.h>
#define HAVE_STAT
#endif
#include "k5-platform.h"
struct global_shared_profile_data {
/* This is the head of the global list of shared trees */
/* Lock for above list. */
};
0,
};
int profile_library_initializer(void)
{
#ifdef SHOW_INITFINI_FUNCS
printf("profile_library_initializer\n");
#endif
#endif
return k5_mutex_finish_init(&g_shared_trees_mutex);
}
void profile_library_finalizer(void)
{
#ifdef SHOW_INITFINI_FUNCS
printf("profile_library_finalizer: skipping\n");
#endif
return;
}
#ifdef SHOW_INITFINI_FUNCS
printf("profile_library_finalizer\n");
#endif
#endif
}
static void profile_free_file_data(prf_data_t);
#if 0
#define scan_shared_trees_locked() \
{ \
prf_data_t d; \
for (d = g_shared_trees; d; d = d->next) { \
} \
}
#define scan_shared_trees_unlocked() \
{ \
int r; \
r = k5_mutex_lock(&g_shared_trees_mutex); \
assert (r == 0); \
}
#else
#define scan_shared_trees_locked() { ; }
#define scan_shared_trees_unlocked() { ; }
#endif
{
#ifdef HAVE_ACCESS
return 1;
else
return 0;
#else
/*
* We're on a substandard OS that doesn't support access. So
* we kludge a test using stdio routines, and hope fopen
* checks the r/w permissions.
*/
FILE *f;
/* Solaris Kerberos */
if (f) {
fclose(f);
return 1;
}
return 0;
#endif
}
{
#ifdef HAVE_ACCESS
return 1;
else
return 0;
#else
/*
* We're on a substandard OS that doesn't support access. So
* we kludge a test using stdio routines, and hope fopen
* checks the r/w permissions.
*/
FILE *f;
/* Solaris Kerberos */
if (f) {
fclose(f);
return 1;
}
return 0;
#endif
}
{
prf_data_t d;
char *fcopy;
if (len < sizeof(struct _prf_data_t))
len = sizeof(struct _prf_data_t);
if (d == NULL)
return NULL;
d->refcount = 1;
d->magic = PROF_MAGIC_FILE_DATA;
return d;
}
{
char *home_env = 0;
unsigned int len;
char *expanded_filename;
if (retval)
return retval;
if (!prf)
return ENOMEM;
#ifdef HAVE_PWD_H
}
#endif
if (home_env)
}
if (expanded_filename == 0)
return errno;
if (home_env) {
} else
if (retval) {
return retval;
}
/* Check that current uid has read access. */
break;
}
if (data) {
(void) k5_mutex_unlock(&g_shared_trees_mutex);
return retval;
}
(void) k5_mutex_unlock(&g_shared_trees_mutex);
return ENOMEM;
}
if (retval) {
return retval;
}
if (retval) {
return retval;
}
if (retval) {
return retval;
}
(void) k5_mutex_unlock(&g_shared_trees_mutex);
return 0;
}
{
#ifdef HAVE_STAT
unsigned long frac;
#endif
FILE *f;
if (retval)
return retval;
#ifdef HAVE_STAT
return 0;
}
return retval;
}
#if defined HAVE_STRUCT_STAT_ST_MTIMENSEC
#elif defined HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
#else
frac = 0;
#endif
return 0;
}
}
}
#else
/*
* If we don't have the stat() call, assume that our in-core
* memory image is correct. That is, we won't reread the
* profile file if it changes.
*/
return 0;
}
#endif
errno = 0;
/* Solaris Kerberos */
if (f == NULL) {
if (retval == 0)
return retval;
}
data->upd_serial++;
fclose(f);
if (retval) {
return retval;
}
#ifdef HAVE_STAT
#endif
return 0;
}
static int
{
#ifdef _WIN32
return -1;
#else
#endif
}
int can_create)
{
FILE *f;
if (!new_file)
goto errout;
if (!old_file)
goto errout;
errno = 0;
/* Solaris Kerberos */
if (!f) {
if (retval == 0)
goto errout;
}
if (fclose(f) != 0) {
goto errout;
}
/* Okay, got the hard link. Yay. Now we've got our
backup version, so just put the new version in
place. */
/* Weird, the rename didn't work. But the old version
should still be in place, so no special cleanup is
needed. */
goto errout;
}
goto errout;
}
} else {
/* Couldn't make the hard link, so there's going to be a
small window where data->filespec does not refer to
either version. */
#ifndef _WIN32
sync();
#endif
goto errout;
}
goto errout;
}
}
retval = 0;
if (new_file)
if (old_file)
return retval;
}
{
if (retval)
return retval;
return retval;
}
{
return PROF_MAGIC_FILE_DATA;
if (retval)
return retval;
return 0;
}
return retval;
}
{
return PROF_MAGIC_FILE_DATA;
if (retval)
return retval;
return retval;
}
{
int err;
if (err)
return;
(void) k5_mutex_unlock(&g_shared_trees_mutex);
}
{
}
int profile_lock_global()
{
return k5_mutex_lock(&g_shared_trees_mutex);
}
int profile_unlock_global()
{
return k5_mutex_unlock(&g_shared_trees_mutex);
}
{
}
/* Call with mutex locked! */
{
/* Remove from linked list. */
if (g_shared_trees == data)
else {
while (next) {
break;
}
}
}
}
}
{
if (retval)
return retval;
return 0;
}