CGI-SpeedyCGI
view release on metacpan or search on metacpan
src/speedy_file.c view on Meta::CPAN
}
}
static void file_map(unsigned int len) {
if (maplen != len) {
file_unmap();
maplen = len;
if (len) {
speedy_file_maddr = (speedy_file_t*)mmap(
0, len, PROT_READ | PROT_WRITE, MAP_SHARED, file_fd, 0
);
if (speedy_file_maddr == (speedy_file_t*)MAP_FAILED)
speedy_util_die("mmap failed");
}
}
}
static void file_unlock(void) {
struct flock fl;
if (!file_locked)
return;
FILE_HEAD.lock_owner = 0;
fillin_fl(fl);
fl.l_type = F_UNLCK;
if (fcntl(file_fd, F_SETLK, &fl) == -1) speedy_util_die("unlock file");
file_locked = 0;
speedy_sig_blockall_undo();
}
/* Only call this if you're sure the fd is not suspect */
static void file_close2(void) {
#ifdef SPEEDY_BACKEND
if (fd_is_suspect)
DIE_QUIET("file_close2: assertion failed - fd_is_suspect");
#endif
file_unlock();
file_unmap();
if (file_fd != -1) {
(void) close(file_fd);
file_fd = -1;
}
}
#ifdef SPEEDY_BACKEND
SPEEDY_INLINE void speedy_file_fd_is_suspect(void) {
fd_is_suspect = 1;
}
static void fix_suspect_fd(void) {
if (fd_is_suspect) {
if (file_fd != -1) {
struct stat stbuf;
if (fstat(file_fd, &stbuf) == -1 ||
stbuf.st_dev != file_stat.st_dev ||
stbuf.st_ino != file_stat.st_ino)
{
file_unmap();
file_fd = -1;
}
}
fd_is_suspect = 0;
}
}
#endif
#define get_stat() \
if (fstat(file_fd, &file_stat) == -1) speedy_util_die("fstat")
static void remove_file(int is_corrupt) {
#ifdef SPEEDY_DEBUG
if (is_corrupt) {
/* Keep the file for debugging */
char newname[200];
struct timeval tv;
gettimeofday(&tv, NULL);
sprintf(newname, "%s.corrupt.%d.%06d.%d",
file_name, (int)tv.tv_sec, (int)tv.tv_usec, getpid());
if (rename(file_name, newname) == -1)
speedy_util_die("rename temp file");
FILE_HEAD.file_removed = 1;
DIE_QUIET("temp file corrupt");
}
#endif
if (unlink(file_name) == -1 && errno != ENOENT)
speedy_util_die("unlink temp file");
FILE_HEAD.file_removed = 1;
}
static void str_replace(char **ptr, char *newval) {
if (*ptr)
speedy_free(*ptr);
*ptr = newval;
}
static void file_lock(void) {
static struct timeval file_create_time;
struct flock fl;
int tries;
time_t now;
if (file_locked)
return;
#ifdef SPEEDY_BACKEND
fix_suspect_fd();
#endif
/* Re-open the temp file occasionally or if tmpbase changed */
if ((now = speedy_util_time()) - last_reopen > OPTVAL_RESTATTIMEOUT ||
!saved_tmpbase || strcmp(saved_tmpbase, OPTVAL_TMPBASE) != 0)
{
last_reopen = now;
file_close2();
}
for (tries = 5; tries; --tries) {
/* If file is not open, open it */
if (file_fd == -1) {
str_replace(&saved_tmpbase, speedy_util_strdup(OPTVAL_TMPBASE));
str_replace(&file_name, speedy_util_fname(FILE_REV, 'F'));
file_fd = speedy_util_pref_fd(
open(file_name, O_RDWR | O_CREAT, 0600), PREF_FD_FILE
);
if (file_fd == -1) speedy_util_die("open temp file");
fcntl(file_fd, F_SETFD, FD_CLOEXEC);
}
/* Lock the file */
fillin_fl(fl);
fl.l_type = F_WRLCK;
if (fcntl(file_fd, F_SETLKW, &fl) == -1) speedy_util_die("lock file");
/* Fstat the file, now that it's locked down */
get_stat();
/* Map into memory */
file_map(file_stat.st_size);
/* If file is too small (0 or below MIN_SLOTS_FREE), extend it */
if (file_stat.st_size < sizeof(file_head_t) ||
file_stat.st_size < sizeof(file_head_t) +
sizeof(slot_t) * (FILE_HEAD.slots_alloced + MIN_SLOTS_FREE))
{
if (ftruncate(file_fd, file_stat.st_size + FILE_ALLOC_CHUNK) == -1)
speedy_util_die("ftruncate");
get_stat();
file_map(file_stat.st_size);
}
/* Initialize file's create time if necessary */
if (!FILE_HEAD.create_time.tv_sec)
speedy_util_gettimeofday(&(FILE_HEAD.create_time));
/* Initialize our copy of the create-time if necessary */
if (!file_create_time.tv_sec || cur_state < FS_HAVESLOTS) {
file_create_time = FILE_HEAD.create_time;
}
/* Check whether this file is a different version */
else if ((file_create_time.tv_sec != FILE_HEAD.create_time.tv_sec ||
file_create_time.tv_usec != FILE_HEAD.create_time.tv_usec))
{
remove_file(1);
}
/* If file is corrupt (didn't finish all writes), remove it */
if (FILE_HEAD.lock_owner)
remove_file(1);
/* If file has not been removed then all done */
if (!FILE_HEAD.file_removed)
break;
/* File is invalid */
if (cur_state >= FS_HAVESLOTS) {
/* Too late for this proc - slotnums have changed, can't recover */
DIE_QUIET("temp file is corrupt");
} else {
/* Bad luck - the file was unlinked after we opened it (possibly
* by us because it was corrupt), but before we locked it.
* Try again.
*/
file_close2();
}
}
if (!tries) {
DIE_QUIET("could not open temp file");
}
/* Block all sigs while writing to file */
speedy_sig_blockall();
file_locked = 1;
FILE_HEAD.lock_owner = speedy_util_getpid();
}
static void file_close(void) {
/* If no groups left, remove the file */
if (cur_state >= FS_HAVESLOTS) {
file_lock();
if (!FILE_HEAD.group_head && !FILE_HEAD.fe_run_head)
remove_file(0);
}
file_close2();
}
int speedy_file_size(void) {
return maplen;
( run in 0.673 second using v1.01-cache-2.11-cpan-5b529ec07f3 )