/*
* Copyright (C) 2003 Sam Horrocks
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "perperl.h"
static struct stat script_stat;
static int script_fd;
static time_t last_open;
void perperl_script_close(void) {
if (last_open)
close(script_fd);
last_open = 0;
}
void perperl_script_missing(void) {
DIE_QUIET("Missing script filename. "
"Type \"perldoc " PERPERL_PKGNAME "\" for PersistentPerl documentation.");
}
int perperl_script_open_failure(void) {
time_t now = perperl_util_time();
const char *fname;
if (!last_open || now - last_open > OPTVAL_RESTATTIMEOUT) {
perperl_script_close();
if (!(fname = perperl_opt_script_fname()))
return 1;
if ((script_fd = perperl_util_open_stat(fname, &script_stat)) == -1)
return 2;
last_open = now;
}
return 0;
}
int perperl_script_open(void) {
switch (perperl_script_open_failure()) {
case 1:
perperl_script_missing();
break;
case 2:
perperl_util_die(perperl_opt_script_fname());
break;
}
return script_fd;
}
#ifdef PERPERL_FRONTEND
int perperl_script_changed(void) {
struct stat stbuf;
if (!last_open)
return 0;
stbuf = script_stat;
(void) perperl_script_open();
return
stbuf.st_mtime != script_stat.st_mtime ||
stbuf.st_ino != script_stat.st_ino ||
stbuf.st_dev != script_stat.st_dev;
}
#endif
const struct stat *perperl_script_getstat(void) {
perperl_script_open();
return &script_stat;
}
slotnum_t perperl_script_find(void) {
slotnum_t gslotnum, next, name_match = 0;
int single_script = DOING_SINGLE_SCRIPT;
(void) perperl_script_getstat();
/* Find the slot for this script in the file */
for (gslotnum = FILE_HEAD.group_head; gslotnum; gslotnum = next) {
gr_slot_t *gslot = &FILE_SLOT(gr_slot, gslotnum);
slotnum_t sslotnum = 0;
next = perperl_slot_next(gslotnum);
/* The end of the list contains only invalid groups */
if (!perperl_group_isvalid(gslotnum)) {
gslotnum = 0;
break;
}
if (!single_script) {
if (perperl_group_name_match(gslotnum))
name_match = gslotnum;
else
/* Reject group names that don't match */
continue;
}
/* Search the script list */
for (sslotnum = gslot->script_head; sslotnum;
sslotnum = perperl_slot_next(sslotnum))
{
scr_slot_t *sslot = &FILE_SLOT(scr_slot, sslotnum);
if (sslot->dev_num == script_stat.st_dev &&
sslot->ino_num == script_stat.st_ino)
{
if (sslot->mtime != script_stat.st_mtime) {
/* Invalidate group */
perperl_group_invalidate(gslotnum);
sslotnum = 0;
} else {
/* Move this script to the front */
perperl_slot_move_head(
sslotnum, &(gslot->script_head), NULL
);
}
/* Done with this group */
break;
}
}
/* If we found the slot, all done */
if (sslotnum)
break;
}
/* Slot not found... */
if (!gslotnum) {
slotnum_t sslotnum;
scr_slot_t *sslot;
/* Get the group-name match from the previous search */
gslotnum = name_match;
/* If group not found create one */
if (!gslotnum || !perperl_group_isvalid(gslotnum))
gslotnum = perperl_group_create();
/* Create a new script slot */
sslotnum = SLOT_ALLOC("script (perperl_script_find)");
sslot = &FILE_SLOT(scr_slot, sslotnum);
sslot->dev_num = script_stat.st_dev;
sslot->ino_num = script_stat.st_ino;
sslot->mtime = script_stat.st_mtime;
/* Add script to this group */
perperl_slot_insert(
sslotnum, &(FILE_SLOT(gr_slot, gslotnum).script_head), NULL
);
}
/* Move this group to the beginning of the list */
perperl_slot_move_head(gslotnum,
&(FILE_HEAD.group_head), &(FILE_HEAD.group_tail));
return gslotnum;
}
static PersistentMapInfo *script_mapinfo;
void perperl_script_munmap(void) {
if (script_mapinfo) {
perperl_util_mapout(script_mapinfo);
script_mapinfo = NULL;
}
}
PersistentMapInfo *perperl_script_mmap(int max_size) {
perperl_script_munmap();
script_mapinfo = perperl_util_mapin(
perperl_script_open(), max_size, perperl_script_getstat()->st_size
);
return script_mapinfo;
}