blob: 82d89d9e8790f3ca07093f42455c4805a6fc8ac1 [file] [log] [blame]
/*
* Copyright (c) 2002 Silicon Graphics, Inc.
* All Rights Reserved.
*
* 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.
*
* This program is distributed in the hope that it would 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 the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <xfs/xfs.h>
#include <xfs/jdm.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <ncurses.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <string.h>
#include <uuid/uuid.h>
#include "types.h"
#include "mlog.h"
#include "inv_priv.h"
#include "getopt.h"
#include "invutil.h"
#include "cmenu.h"
#include "list.h"
#include "invidx.h"
#include "stobj.h"
#include "timeutil.h"
invidx_fileinfo_t *invidx_file;
int invidx_numfiles;
extern stobj_fileinfo_t *stobj_file;
extern int stobj_numfiles;
static void stobj_makefname_len( char *fname, int fname_len );
menu_ops_t invidx_ops = {
NULL,
invidx_undelete,
NULL,
invidx_select,
NULL,
NULL,
NULL,
NULL,
invidx_highlight,
menu_unhighlight,
invidx_commit,
invidx_prune,
};
/*ARGSUSED*/
int
invidx_commit(WINDOW *win, node_t *current, node_t *list)
{
int i;
int idx;
int fidx;
node_t *n;
data_t *d;
invt_entry_t *inv_entry;
n = current;
if(n == NULL || n->data == NULL)
return 0;
d = ((data_t *)(n->data));
fidx = d->file_idx;
inv_entry = invidx_file[fidx].data[d->data_idx];
idx = (int)(((long)inv_entry - (long)invidx_file[fidx].mapaddr - sizeof(invt_counter_t)) / sizeof(invt_entry_t));
if(d->deleted == BOOL_TRUE && d->imported == BOOL_FALSE) {
/* shortcut - just close and unlink stobj files */
for(i = 0; i < d->nbr_children; i++) {
close_stobj_file(((data_t *)(d->children[i]->data))->file_idx, BOOL_TRUE);
}
mark_all_children_commited(current);
if ( invidx_file[fidx].counter->ic_curnum > 1 ) {
memmove(&inv_entry[idx],
&inv_entry[idx + 1],
(sizeof(invt_entry_t) * (invidx_file[fidx].counter->ic_curnum - idx - 1)));
invidx_file[fidx].data[idx]=NULL;
for(i = idx + 1; i < invidx_file[fidx].numrecords; i++) {
if(invidx_file[fidx].data[i] != NULL)
invidx_file[fidx].data[i]--;
}
}
invidx_file[fidx].counter->ic_curnum--;
}
else if(d->imported == BOOL_TRUE) {
int dst_fileidx;
int dst_invpos;
int dst_invidx;
char dst_idxfile[MAXPATHLEN];
struct stat s;
char dst_stobjfile[MAXPATHLEN];
char *stobjfile;
char cmd[1024];
snprintf(dst_idxfile, sizeof(dst_idxfile), "%s/%s", inventory_path, basename(invidx_file[fidx].name));
/* append if we have the target open already, else write to a possibly new file */
if((dst_fileidx = find_matching_invidxfile(dst_idxfile)) >= 0) {
invt_entry_t *dest = NULL;
if((dst_invidx = find_overlapping_invidx(dst_fileidx, inv_entry)) >= 0) {
char *stobj_filename = NULL;
int stobj_fd = -1;
int stobj_fileidx;
int last_dst_invidx;
node_t *tmp_parent;
data_t *tmp_d;
node_t *dst_n;
data_t *dst_d;
invt_seshdr_t *hdr;
invt_session_t *ses;
invt_stream_t *strms;
invt_mediafile_t *mfiles;
last_dst_invidx = -1;
i = d->nbr_children - 1;
do {
if(dst_invidx != last_dst_invidx) {
stobj_fileidx = find_matching_stobjfile(invidx_file[dst_fileidx].data[dst_invidx]->ie_filename);
stobj_filename = stobj_file[stobj_fileidx].name;
stobj_fd = stobj_file[stobj_fileidx].fd;
last_dst_invidx = dst_invidx;
}
/* for each child of inv_entry, insert into invidx & stobj files */
tmp_d = d->children[i]->data;
read_stobj_info(stobj_file[tmp_d->file_idx].fd,
i,
&hdr,
&ses,
&strms,
&mfiles);
insert_stobj_into_stobjfile(dst_fileidx,
stobj_filename,
stobj_fd,
hdr,
ses,
strms,
mfiles);
free(hdr); free(ses); free(strms); free(mfiles);
if(--i < 0)
break;
}
while((dst_invidx = find_overlapping_invidx(dst_fileidx, inv_entry)) >= 0);
mark_all_children_commited(current);
/* Clean up the mess we just created */
/* find node for dst_fileidx */
dst_n = find_invidx_node(list, dst_fileidx);
tmp_parent = ((data_t *)(dst_n->data))->parent;
while(dst_n != NULL) {
node_t *tmp_n1;
dst_d = dst_n->data;
/* close affected invidx file and stobj files */
for(i = 0; i < dst_d->nbr_children; i++) {
close_stobj_file(((data_t *)(dst_d->children[i]->data))->file_idx, BOOL_FALSE);
}
/* free_all_children on that node */
free_all_children(dst_n);
tmp_n1 = find_invidx_node(dst_n->next, dst_fileidx);
node_free(list_del(dst_n));
dst_n = tmp_n1;
}
close_invidx(dst_fileidx);
/* generate invidx menu for the parent node */
dst_n = generate_invidx_menu(inventory_path, tmp_parent, 1, dst_idxfile);
if(dst_n != tmp_parent) {
/* mark all its children commited */
mark_all_children_commited(dst_n);
}
return 0;
}
else {
/* insert new invidx entry, and copy over stobj file */
if(invidx_file[dst_fileidx].counter->ic_curnum >= invidx_file[dst_fileidx].nEntries) {
dest = remmap_invidx(dst_fileidx, 1);
}
dst_invpos = find_invidx_insert_pos(dst_fileidx, inv_entry);
if(dst_invpos >= 0) {
memmove(invidx_file[dst_fileidx].data[dst_invpos + 1],
invidx_file[dst_fileidx].data[dst_invpos],
sizeof(*inv_entry) * (invidx_file[dst_fileidx].counter->ic_curnum - dst_invpos));
}
else {
dest = invidx_file[dst_fileidx].data[invidx_file[dst_fileidx].counter->ic_curnum - 1] + 1;
}
/* copy new data to mmap */
memmove(dest, inv_entry, sizeof(*inv_entry));
/* increment counter */
invidx_file[dst_fileidx].counter->ic_curnum++;
mark_all_children_commited(current);
/* shortcut - just copy stobj file over */
stobjfile = get_inventry_stobjfile(d);
if(stobjfile == NULL) {
put_error("Error: unable to work out stobj filename");
return 0;
}
snprintf(dst_stobjfile, sizeof(dst_stobjfile), "%s/%s", inventory_path, basename(stobjfile));
if(stat(dst_stobjfile, &s) < 0) {
if(errno != ENOENT) {
put_error("Error: unable to copy stobj file: stat error");
return 0;
}
}
else {
put_error("Error: unable to copy stobj file: file exists");
return 0;
}
snprintf(cmd, sizeof(cmd), "cp %s %s", stobjfile, dst_stobjfile);
if(system(cmd) != 0) {
put_error("Error: unable to copy stobj file: cp failed");
return 0;
}
open_stobj(dst_stobjfile);
return 0;
}
}
else {
/* no matching inventory index file - just copy entry to a new file */
invt_counter_t cnt;
int new_fd;
memset(&cnt, 0, sizeof(cnt));
cnt.ic_maxnum = INVT_MAX_INVINDICES;
cnt.ic_curnum = 0;
cnt.ic_vernum = INV_VERSION;
mark_all_children_commited(current);
if(stat(dst_idxfile, &s) < 0) {
if(errno != ENOENT) {
put_error("Error: unable to stat inventory index file");
return 0;
}
}
else {
put_error("Error: unable to copy inventory index file: file exists");
return 0;
}
new_fd = open(dst_idxfile, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR);
if(new_fd < 0) {
put_error("Error: unable to open inventory index file");
return 0;
}
INVLOCK(new_fd, LOCK_EX);
cnt.ic_curnum++;
write_n_bytes(new_fd, (char *)&cnt, sizeof(cnt), dst_idxfile);
write_n_bytes(new_fd, (char *)inv_entry, sizeof(*inv_entry), dst_idxfile);
INVLOCK(new_fd, LOCK_UN);
close(new_fd);
open_invidx(dst_idxfile);
/* shortcut - just copy stobj file over */
stobjfile = get_inventry_stobjfile(d);
if(stobjfile == NULL) {
put_error("Error: unable to work out stobj filename");
return 0;
}
snprintf(dst_stobjfile, sizeof(dst_stobjfile), "%s/%s", inventory_path, basename(stobjfile));
if(stat(dst_stobjfile, &s) < 0) {
if(errno != ENOENT) {
put_error("Error: unable to copy stobj file: stat error");
return 0;
}
}
else {
put_error("Error: unable to copy stobj file: file exists");
return 0;
}
snprintf(cmd, sizeof(cmd), "cp %s %s", stobjfile, dst_stobjfile);
if(system(cmd) != 0) {
put_error("Error: unable to copy stobj file: cp failed");
return 0;
}
open_stobj(dst_stobjfile);
return 0;
}
}
return 0;
}
int
create_stobjfile(int invidx_fileidx, char *filename, int fname_len,
invt_seshdr_t *hdr, invt_session_t *ses, invt_stream_t *strms,
invt_mediafile_t *mfiles)
{
int fd;
stobj_makefname_len(filename, fname_len);
fd = stobj_create(filename);
insert_stobj_into_stobjfile(invidx_fileidx, filename, fd, hdr, ses, strms, mfiles);
return fd;
}
int
read_stobj_info(int fd, int idx, invt_seshdr_t **out_hdr,
invt_session_t **out_ses, invt_stream_t **out_strms,
invt_mediafile_t **out_mfiles)
{
int i;
int nmfiles;
invt_seshdr_t *hdr;
invt_session_t *ses;
invt_stream_t *strms;
invt_mediafile_t *mfiles;
lseek(fd, STOBJ_OFFSET(idx, 0), SEEK_SET);
hdr = malloc(sizeof(*hdr));
read_n_bytes(fd, (char *)hdr, sizeof(*hdr), "stobj file");
lseek(fd, hdr->sh_sess_off, SEEK_SET);
ses = malloc(sizeof(*ses));
read_n_bytes(fd, (char *)ses, sizeof(*ses), "stobj file");
if(ses->s_cur_nstreams > 0) {
lseek(fd, hdr->sh_streams_off, SEEK_SET);
strms = malloc(sizeof(*strms) * ses->s_cur_nstreams);
read_n_bytes(fd, (char *)strms, sizeof(*strms) * ses->s_cur_nstreams, "stobj file");
nmfiles = 0;
for(i = 0; i < ses->s_cur_nstreams; i++) {
nmfiles += strms[i].st_nmediafiles;
}
if(nmfiles > 0) {
mfiles = malloc(sizeof(*mfiles) * nmfiles);
read_n_bytes(fd, (char *)mfiles, sizeof(*mfiles) * nmfiles, "stobj file");
}
else {
mfiles = NULL;
}
}
else {
strms = NULL;
mfiles = NULL;
}
*out_hdr = hdr;
*out_ses = ses;
*out_strms = strms;
*out_mfiles = mfiles;
return fd;
}
int
delete_stobj_entries(int fd, int deletepos)
{
invt_sescounter_t sescnt;
invt_seshdr_t *hdr;
invt_session_t *ses;
invt_stream_t *strms;
invt_mediafile_t *mfiles;
lseek(fd, 0, SEEK_SET);
read_n_bytes(fd, (char *)&sescnt, sizeof(sescnt), "stobj file");
read_stobj_info(fd, deletepos, &hdr, &ses, &strms, &mfiles);
sescnt.ic_eof = hdr->sh_streams_off;
free(hdr); free(ses); free(strms); free(mfiles);
sescnt.ic_curnum -= deletepos;
lseek(fd, 0, SEEK_SET);
write_n_bytes(fd, (char *)&sescnt, sizeof(sescnt), "stobj file");
return 0;
}
int
find_stobj_insert_point(int fd, invt_seshdr_t *hdr)
{
int i;
invt_sescounter_t sescnt;
invt_seshdr_t tmphdr;
lseek(fd, 0, SEEK_SET);
read_n_bytes(fd, (char *)&sescnt, sizeof(sescnt), "stobj file");
for(i = 0; i < sescnt.ic_curnum; i++) {
read_n_bytes(fd, (char *)&tmphdr, sizeof(tmphdr), "stobj file");
if(hdr->sh_time <= tmphdr.sh_time) {
break;
}
}
return i;
}
int
update_invidx_entry(int fd, char *filename, int stobj_fd)
{
int i;
time32_t start_time;
time32_t end_time;
invt_counter_t cnt;
invt_seshdr_t hdr;
invt_sescounter_t sescnt;
invt_entry_t entry;
off_t first_offset;
off_t last_offset;
/* find the start and stop in stobj file */
lseek(stobj_fd, 0, SEEK_SET);
read_n_bytes(stobj_fd, &sescnt, sizeof(sescnt), "stobj file");
memset(&hdr, 0, sizeof(hdr));
first_offset = STOBJ_OFFSET(0,0);
lseek(stobj_fd, first_offset, SEEK_SET);
read_n_bytes(stobj_fd, &hdr, sizeof(hdr), "stobj file");
start_time = hdr.sh_time;
memset(&hdr, 0, sizeof(hdr));
last_offset = STOBJ_OFFSET((sescnt.ic_curnum - 1), 0);
lseek(stobj_fd, last_offset, SEEK_SET);
read_n_bytes(stobj_fd, &hdr, sizeof(hdr), "stobj file");
end_time = hdr.sh_time;
lseek(fd, 0, SEEK_SET);
read_n_bytes(fd, &cnt, sizeof(cnt), "invidx file");
for(i = 0; i < cnt.ic_curnum; i++) {
lseek(fd, IDX_HDR_OFFSET(i), SEEK_SET);
read_n_bytes(fd, &entry, sizeof(entry), "invidx file");
if(strcmp(entry.ie_filename, filename) == 0) {
entry.ie_timeperiod.tp_start = start_time;
entry.ie_timeperiod.tp_end = end_time;
lseek(fd, IDX_HDR_OFFSET(i), SEEK_SET);
write_n_bytes(fd, &entry, sizeof(entry), "invidx file");
return i;
}
}
entry.ie_timeperiod.tp_start = start_time;
entry.ie_timeperiod.tp_end = end_time;
strcpy(entry.ie_filename, filename);
lseek(fd, 0, SEEK_END);
write_n_bytes(fd, &entry, sizeof(entry), "invidx file");
cnt.ic_curnum++;
lseek(fd, 0, SEEK_SET);
write_n_bytes(fd, &cnt, sizeof(cnt), "invidx file");
return i;
}
int
insert_stobj_into_stobjfile(int invidx_fileidx, char *filename, int fd,
invt_seshdr_t *hdr, invt_session_t *ses,
invt_stream_t *strms, invt_mediafile_t *mfiles)
{
int i;
invt_sescounter_t sescnt;
int pos;
char *buf;
int invidx_fd = invidx_file[invidx_fileidx].fd;
if(hdr == NULL || ses == NULL || strms == NULL || mfiles == NULL)
return 0;
lseek(fd, 0, SEEK_SET);
read_n_bytes(fd, (char *)&sescnt, sizeof(sescnt), "stobj file");
pos = find_stobj_insert_point(fd, hdr);
/* if stobj file is full, we need to split it */
if(sescnt.ic_curnum >= sescnt.ic_maxnum) {
int new_fd;
char new_filename[INV_STRLEN];
invt_seshdr_t *s_hdr;
invt_session_t *s_ses;
invt_stream_t *s_strms;
invt_mediafile_t *s_mfiles;
new_fd = create_stobjfile(invidx_fileidx, new_filename, sizeof(new_filename), hdr, ses, strms, mfiles);
for(i = pos; i < sescnt.ic_curnum; i++) {
read_stobj_info(fd, i, &s_hdr, &s_ses, &s_strms, &s_mfiles);
insert_stobj_into_stobjfile(invidx_fileidx, new_filename, new_fd, s_hdr, s_ses, s_strms, s_mfiles);
free(s_hdr); free(s_ses); free(s_strms); free(s_mfiles);
}
delete_stobj_entries(fd, pos);
update_invidx_entry(invidx_fd, new_filename, new_fd);
update_invidx_entry(invidx_fd, filename, fd);
return 0;
}
/* stobj file not full, just insert the entry */
hdr->sh_sess_off = STOBJ_OFFSET( sescnt.ic_maxnum, pos);
hdr->sh_streams_off = sescnt.ic_eof;
/* for seshdr: malloc buffer, copy new entry into buffer, read file entries into buffer, write the lot out */
buf = malloc(((sescnt.ic_curnum - pos) + 1) * sizeof(invt_seshdr_t));
memmove(buf, hdr, sizeof(invt_seshdr_t));
lseek(fd, STOBJ_OFFSET(pos, 0), SEEK_SET);
read_n_bytes(fd, buf + sizeof(invt_seshdr_t), (sescnt.ic_curnum - pos) * sizeof(invt_seshdr_t), "stobj file");
lseek(fd, STOBJ_OFFSET(pos, 0), SEEK_SET);
write_n_bytes(fd, buf, ((sescnt.ic_curnum - pos) + 1) * sizeof(invt_seshdr_t), "stobj file");
free(buf);
/* for session: malloc buffer, copy new entry into buffer, read file entries into buffer, write the lot out */
buf = malloc(((sescnt.ic_curnum - pos) + 1) * sizeof(invt_session_t));
memmove(buf, ses, sizeof(invt_session_t));
lseek(fd, STOBJ_OFFSET(sescnt.ic_maxnum, pos), SEEK_SET);
read_n_bytes(fd, buf + sizeof(invt_session_t), (sescnt.ic_curnum - pos) * sizeof(invt_session_t), "stobj file");
lseek(fd, STOBJ_OFFSET(sescnt.ic_maxnum, pos), SEEK_SET);
write_n_bytes(fd, buf, ((sescnt.ic_curnum - pos) + 1) * sizeof(invt_session_t), "stobj file");
free(buf);
/* write the streams and mediafile info at the end of the stobj file */
stobj_put_streams(fd, hdr, ses, strms, mfiles);
/* update counter */
sescnt.ic_curnum++;
sescnt.ic_eof = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
write_n_bytes(fd, (char *)&sescnt, sizeof(sescnt), "stobj file");
/* update the inventory index entry */
update_invidx_entry(invidx_fd, filename, fd);
return 0;
}
static void
stobj_makefname_len( char *fname, int fname_len )
{
/* come up with a new unique name */
uuid_t fn;
char str[UUID_STR_LEN + 1];
uuid_generate( fn );
uuid_unparse( fn, str );
snprintf(fname, fname_len, "%s/%s.StObj", inventory_path, str);
}
int
stobj_create( char *fname )
{
int fd;
invt_sescounter_t sescnt;
/* create the new storage object */
if (( fd = open( fname, O_RDWR | O_EXCL | O_CREAT, S_IRUSR|S_IWUSR )) < 0 ) {
return -1;
}
INVLOCK( fd, LOCK_EX );
fchmod( fd, INV_PERMS );
memset(&sescnt, 0, sizeof(sescnt));
sescnt.ic_vernum = INV_VERSION;
sescnt.ic_curnum = 0; /* there are no sessions as yet */
sescnt.ic_maxnum = INVT_STOBJ_MAXSESSIONS;
sescnt.ic_eof = SC_EOF_INITIAL_POS;
lseek(fd, 0, SEEK_SET);
write_n_bytes ( fd, (char *)&sescnt, sizeof(sescnt), "new stobj file" );
INVLOCK( fd, LOCK_UN );
return fd;
}
int
stobj_put_streams( int fd, invt_seshdr_t *hdr, invt_session_t *ses,
invt_stream_t *strms,
invt_mediafile_t *mfiles )
{
uint nstm = ses->s_cur_nstreams;
off64_t off = hdr->sh_streams_off;
off64_t mfileoff= off + (off64_t)( nstm * sizeof( invt_stream_t ) );
uint nmfiles = 0;
uint i,j;
/* fix the offsets in streams */
for ( i = 0; i < nstm; i++ ) {
strms[i].st_firstmfile = mfileoff + (off64_t) ((size_t) nmfiles * sizeof( invt_mediafile_t ) );
/* now fix the offsets in mediafiles */
for ( j = 0; j < strms[i].st_nmediafiles; j++ ) {
/* no need to fix the last element's next ptr */
if ( j < strms[i].st_nmediafiles - 1 )
mfiles[ nmfiles + j ].mf_nextmf = strms[i].st_firstmfile + (off64_t) ((j+1) * sizeof( invt_mediafile_t ));
/* no need to fix the first element's prev ptr */
if ( j )
mfiles[ nmfiles + j ].mf_prevmf = strms[i].st_firstmfile + (off64_t) ((j-1) * sizeof( invt_mediafile_t ));
}
/* adjust the offsets of the first and the last elements
in the mediafile chain */
mfiles[ nmfiles ].mf_prevmf = 0;
nmfiles += strms[i].st_nmediafiles;
mfiles[ nmfiles - 1 ].mf_nextmf = 0;
}
/* first put the streams. hdr already points at the right place */
lseek(fd, off, SEEK_SET);
write_n_bytes( fd, strms, nstm * sizeof( invt_stream_t ), "stobj file" );
lseek(fd, mfileoff, SEEK_SET);
write_n_bytes( fd, mfiles, nmfiles * sizeof( invt_mediafile_t ), "stobj file" );
return 1;
}
/*ARGSUSED*/
int
invidx_select(WINDOW *win, node_t *current, node_t *list)
{
data_t *d;
if(current == NULL || current->data == NULL) {
return 0;
}
d = (data_t *)(current->data);
if(d->expanded == TRUE) {
return menu_collapse(win, current, list);
}
return menu_expand(win, current, list);
}
/*ARGSUSED*/
int
invidx_highlight(WINDOW *win, node_t *current, node_t *list)
{
static char txt[256];
data_t *d;
invt_entry_t *invtentry;
if(current == NULL || current->data == NULL) {
return 0;
}
d = (data_t *)(current->data);
invtentry = invidx_file[d->file_idx].data[d->data_idx];
wclear(infowin);
put_info_header("inventory index entry");
snprintf(txt, sizeof(txt), "path: %s", invtentry->ie_filename);
put_info_line(1, txt);
snprintf(txt, sizeof(txt), "start: %s", ctime32(&invtentry->ie_timeperiod.tp_start));
txt[strlen(txt) - 1] = '\0';
put_info_line(2, txt);
snprintf(txt, sizeof(txt), "end: %s", ctime32(&invtentry->ie_timeperiod.tp_end));
txt[strlen(txt) - 1] = '\0';
put_info_line(3, txt);
return FALSE;
}
/*ARGSUSED*/
int
invidx_undelete(WINDOW *win, node_t *current, node_t *list)
{
node_t *n;
data_t *d;
if(current == NULL || current->data == NULL) {
return BOOL_FALSE;
}
list_undelete(current, list);
d = ((data_t *)(current->data));
n = current->next;
while(n != NULL && n->data != NULL && ((data_t *)(n->data))->level > d->level) {
((data_t *)(n->data))->deleted = BOOL_FALSE;
((data_t *)(n->data))->text[0] = ' ';
n = n->next;
}
redraw_screen = BOOL_TRUE;
return BOOL_FALSE;
}
/*ARGSUSED*/
int
invidx_prune(char *mountpt, uuid_t *uuidp, time32_t prunetime, node_t *node, node_t *list)
{
data_t *d;
invt_entry_t *invidx_entry;
if(node == NULL || node->data == NULL) {
return BOOL_FALSE;
}
d = ((data_t *)(node->data));
invidx_entry = invidx_file[d->file_idx].data[d->data_idx];
if(invidx_entry == NULL) {
return BOOL_FALSE;
}
if(invidx_entry->ie_timeperiod.tp_start < prunetime) {
return BOOL_TRUE;
}
return BOOL_FALSE;
}
node_t *
find_invidx_node(node_t *list, int inv_fileidx)
{
node_t *n;
data_t *d;
n = list;
while(n != NULL && n->data != NULL) {
d = n->data;
/* is this an invidx entry we're looking at? */
if(d->ops == &invidx_ops) {
if(d->file_idx == inv_fileidx) {
return n;
}
}
n = n->next;
}
return NULL;
}
char *
get_inventry_stobjfile(data_t *d)
{
data_t *child_data;
if(d->nbr_children <= 0) {
return NULL;
}
/* all the children will be from the same stobj file, so we can just
get the name for the first */
child_data = d->children[0]->data;
return stobj_file[child_data->file_idx].name;
}
int
find_overlapping_invidx(int fidx, invt_entry_t *inv_entry)
{
int i = 0;
invt_entry_t *entry;
for(i = 0; i < invidx_file[fidx].numrecords; i++) {
entry = invidx_file[fidx].data[i];
if(entry->ie_timeperiod.tp_end < inv_entry->ie_timeperiod.tp_start
|| entry->ie_timeperiod.tp_start > inv_entry->ie_timeperiod.tp_end) {
continue;
}
return i;
}
return -1;
}
int
find_invidx_insert_pos(int fidx, invt_entry_t *inv_entry)
{
int i = 0;
invt_entry_t *entry;
invt_entry_t *next_entry;
for(i = 0; i < invidx_file[fidx].numrecords - 1; i++) {
entry = invidx_file[fidx].data[i];
next_entry = invidx_file[fidx].data[i+1];
if(inv_entry->ie_timeperiod.tp_start > entry->ie_timeperiod.tp_end
&& inv_entry->ie_timeperiod.tp_end < next_entry->ie_timeperiod.tp_start ) {
return i;
}
}
return -1;
}
int
find_matching_stobjfile(char *filename)
{
int i = 0;
for(i = 0; i < stobj_numfiles; i++) {
if(stobj_file[i].name == NULL)
continue;
if(strcmp(stobj_file[i].name, filename) == 0) {
return i;
}
}
return -1;
}
int
find_matching_invidxfile(char *filename)
{
int i = 0;
for(i = 0; i < invidx_numfiles; i++) {
if(invidx_file[i].name == NULL)
continue;
if(strcmp(invidx_file[i].name, filename) == 0) {
return i;
}
}
return -1;
}
int
add_invidx_data(int fidx, invt_entry_t *data)
{
if(invidx_file[fidx].numrecords == 0) {
invidx_file[fidx].data = malloc(sizeof(*invidx_file[fidx].data));
if(invidx_file[fidx].data == NULL) {
fprintf(stderr, "%s: internal memory error: invidx data allocation\n",
g_programName);
exit(1);
}
}
else {
invidx_file[fidx].data = realloc(invidx_file[fidx].data,
sizeof(*invidx_file[fidx].data)
* (invidx_file[fidx].numrecords + 1));
if(invidx_file[fidx].data == NULL) {
fprintf(stderr, "%s: internal memory error: invidx data reallocation\n",
g_programName);
exit(1);
}
}
invidx_file[fidx].data[invidx_file[fidx].numrecords] = data;
invidx_file[fidx].numrecords++;
return 0;
}
node_t *
generate_invidx_menu(char * inv_path, node_t *startnode, int level, char *idxFileName)
{
int i;
int idx;
int len;
char *txt;
node_t *n;
invt_entry_t *invidx_entry;
char *stobjname;
if((idx = open_invidx(idxFileName)) < 0) {
return startnode;
}
invidx_entry = (invt_entry_t *)( invidx_file[idx].mapaddr + sizeof(invt_counter_t));
n = startnode;
for (i=0; i < invidx_file[idx].counter->ic_curnum; i++) {
len = strlen(invidx_entry[i].ie_filename) + 54;
txt = malloc(len);
if(txt == NULL) {
fprintf(stderr, "%s: internal memory error: invidx_text\n", g_programName);
exit(1);
}
snprintf(txt, len, " inv file: %s ", basename(invidx_entry[i].ie_filename));
n = list_add(n, node_create(BOOL_TRUE, /* hidden */
BOOL_FALSE, /* expanded */
level, /* level */
BOOL_FALSE, /* deleted */
idx, /* file_idx */
txt, /* text */
&(invidx_ops), /* menu ops */
startnode, /* parent */
NULL, /* children */
0, /* nbr_children */
i)); /* data_idx */
if(n == NULL) {
fprintf(stderr, "%s: internal memory error: list_add: node_create: invidx\n",
g_programName);
exit(1);
}
add_invidx_data(idx, &(invidx_entry[i]));
stobjname = GetNameOfStobj(inv_path, invidx_entry[i].ie_filename);
n = generate_stobj_menu( n, level + 1, stobjname );
free(stobjname);
}
return n;
}
int
add_invidx(char *name, int fd, int nEntries, char *mapaddr, invt_counter_t *counter)
{
static int highwatermark = 10;
if(invidx_numfiles == 0) {
invidx_file = malloc(sizeof(*invidx_file) * highwatermark);
if(invidx_file == NULL) {
fprintf(stderr, "%s: internal memory error: malloc invidx_file\n", g_programName);
exit(1);
}
}
else {
if(invidx_numfiles >= highwatermark - 1) {
highwatermark += highwatermark;
invidx_file = realloc(invidx_file, sizeof(*invidx_file) * highwatermark);
if(invidx_file == NULL) {
fprintf(stderr, "%s: internal memory error: realloc invidx\n", g_programName);
exit(1);
}
}
}
invidx_file[invidx_numfiles].nEntries = nEntries;
invidx_file[invidx_numfiles].mapaddr = mapaddr;
invidx_file[invidx_numfiles].fd = fd;
invidx_file[invidx_numfiles].name = name;
invidx_file[invidx_numfiles].counter = counter;
invidx_file[invidx_numfiles].data = NULL;
invidx_file[invidx_numfiles].numrecords = 0;
invidx_numfiles++;
return invidx_numfiles - 1;
}
void *
remmap_invidx(int fidx, int num)
{
int i;
int nEntries;
char *mapaddr;
invt_entry_t *inv_entry;
nEntries = invidx_file[fidx].counter->ic_curnum;
munmap( invidx_file[fidx].mapaddr,
(nEntries * sizeof(invt_entry_t)) + sizeof(invt_counter_t));
/* need to lseek on the file to grow it to the right size - no autogrow on linux */
lseek(invidx_file[fidx].fd, (num * sizeof(invt_entry_t)) - 1, SEEK_END);
write_n_bytes(invidx_file[fidx].fd, "", 1, invidx_file[fidx].name);
mapaddr = mmap_n_bytes(invidx_file[fidx].fd,
(nEntries + 1) * (num * sizeof(invt_entry_t))
+ sizeof(invt_counter_t),
BOOL_FALSE,
invidx_file[fidx].name);
invidx_file[fidx].nEntries += num;
invidx_file[fidx].mapaddr = mapaddr;
invidx_file[fidx].counter = (invt_counter_t *)mapaddr;
/* regenerate the data index for the file given the new mapping */
inv_entry = (invt_entry_t *)(invidx_file[fidx].mapaddr + sizeof(invt_counter_t));
for(i=0; i < nEntries; i++) {
if(i >= invidx_file[fidx].numrecords) {
add_invidx_data(fidx, &(inv_entry[i]));
}
else {
invidx_file[fidx].data[i] = &(inv_entry[i]);
}
}
return &(inv_entry[i]);
}
int
open_invidx(char *idxFileName)
{
int fd;
int nEntries;
char *mapaddr;
char *name;
invt_counter_t header;
errno=0;
fd = open_and_lock( idxFileName, FILE_WRITE, wait_for_locks );
if (fd < 0) {
return fd;
}
name = strdup(idxFileName);
if(name == NULL) {
fprintf(stderr, "%s: internal memory error: strdup idxFileName\n", g_programName);
exit(1);
}
read_n_bytes( fd, &header, sizeof(invt_counter_t), idxFileName);
nEntries = header.ic_curnum;
mapaddr = mmap_n_bytes(fd,
nEntries*sizeof(invt_entry_t) + sizeof(invt_counter_t),
BOOL_FALSE,
idxFileName);
return add_invidx(name, fd, nEntries, mapaddr, (invt_counter_t *)mapaddr);
}
int
close_invidx(int idx)
{
int nEntries;
if(idx >= invidx_numfiles || invidx_file[idx].fd < 0)
return 0;
nEntries = invidx_file[idx].counter->ic_curnum;
munmap( invidx_file[idx].mapaddr,
(invidx_file[idx].nEntries*sizeof(invt_entry_t)) + sizeof(invt_counter_t) );
if(nEntries != 0 && nEntries != invidx_file[idx].nEntries) {
ftruncate(invidx_file[idx].fd,
sizeof(invt_counter_t) + (nEntries * sizeof(invt_entry_t)) );
}
close( invidx_file[idx].fd );
if(nEntries == 0) {
unlink(invidx_file[idx].name);
}
free( invidx_file[idx].name );
free( invidx_file[idx].data );
invidx_file[idx].fd = -1;
invidx_file[idx].name = NULL;
invidx_file[idx].data = NULL;
return 0;
}
int
close_all_invidx()
{
int i;
for(i = 0; i < invidx_numfiles; i++) {
if(invidx_file[i].fd < 0)
continue;
close_invidx(i);
}
free(invidx_file);
invidx_file = NULL;
return 0;
}