blob: 428b419fc4fbf2a039489fcc577705c0f23612da [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 <ncurses.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include "types.h"
#include "mlog.h"
#include "inv_priv.h"
#include "getopt.h"
#include "invutil.h"
#include "timeutil.h"
#include "cmenu.h"
#include "list.h"
#include "stobj.h"
stobj_fileinfo_t *stobj_file;
int stobj_numfiles;
menu_ops_t stobjsess_ops = {
NULL,
stobj_undelete,
NULL,
stobj_select,
NULL,
NULL,
NULL,
NULL,
stobjsess_highlight,
menu_unhighlight,
stobjsess_commit,
stobj_prune,
};
menu_ops_t stobjstrm_ops = {
stobjstrm_delete,
stobj_undelete,
NULL,
stobj_select,
NULL,
NULL,
NULL,
NULL,
stobjstrm_highlight,
menu_unhighlight,
stobjstrm_commit,
NULL,
};
menu_ops_t stobjmed_ops = {
stobjmed_delete,
NULL,
NULL,
stobj_select,
NULL,
NULL,
NULL,
NULL,
stobjmed_highlight,
menu_unhighlight,
stobjmed_commit,
NULL,
};
/*ARGSUSED*/
int
stobjmed_commit(WINDOW *win, node_t *current, node_t *list)
{
data_t *d;
if(current == NULL || current->data == NULL) {
return 0;
}
d = (data_t *)(current->data);
return stobjstrm_commit(win, d->parent, list);
}
/*ARGSUSED*/
int
stobjstrm_commit(WINDOW *win, node_t *current, node_t *list)
{
data_t *d;
if(current == NULL || current->data == NULL) {
return 0;
}
d = (data_t *)(current->data);
return stobjsess_commit(win, d->parent, list);
}
/*ARGSUSED*/
int
stobjmed_delete(WINDOW *win, node_t *current, node_t *list)
{
data_t *d;
if(current == NULL || current->data == NULL) {
return 0;
}
d = (data_t *)(current->data);
return stobjstrm_delete(win, d->parent, list);
}
/*ARGSUSED*/
int
stobjstrm_delete(WINDOW *win, node_t *current, node_t *list)
{
data_t *d;
if(current == NULL || current->data == NULL) {
return 0;
}
d = (data_t *)(current->data);
return menu_delete(win, d->parent, list);
}
/*ARGSUSED*/
int
stobjsess_commit(WINDOW *win, node_t *current, node_t *list)
{
data_t *d;
invt_seshdr_t *stobjhdr;
if(current == NULL || current->data == NULL) {
return 0;
}
d = (data_t *)(current->data);
stobjhdr = ((stobjsess_t *)(stobj_file[d->file_idx].data[d->data_idx]))->header;
mark_all_children_commited(current);
if(d->deleted == BOOL_TRUE) {
stobjhdr->sh_pruned = 1;
}
else {
stobjhdr->sh_pruned = 0;
}
return 0;
}
/*ARGSUSED*/
int
stobjsess_highlight(WINDOW *win, node_t *current, node_t *list)
{
static char txt[256];
char uuidstr[UUID_STR_LEN + 1];
data_t *d;
invt_seshdr_t *stobjhdr;
invt_session_t *stobjses;
if(current == NULL || current->data == NULL) {
return 0;
}
d = (data_t *)(current->data);
stobjhdr = ((stobjsess_t *)(stobj_file[d->file_idx].data[d->data_idx]))->header;
stobjses = ((stobjsess_t *)(stobj_file[d->file_idx].data[d->data_idx]))->session;
wclear(infowin);
put_info_header("session entry");
snprintf(txt, sizeof(txt), "pruned: %s, flags: %#x, time: %s",
(stobjhdr->sh_pruned == BOOL_TRUE) ? "yes" : "no",
stobjhdr->sh_flag,
ctime32(&(stobjhdr->sh_time)));
txt[strlen(txt)-1] = '\0';
put_info_line(1, txt);
uuid_unparse(stobjses->s_fsid, uuidstr);
snprintf(txt, sizeof(txt), "mountpt: %s, fsid: %s", stobjses->s_mountpt, uuidstr);
put_info_line(2, txt);
uuid_unparse(stobjses->s_sesid, uuidstr);
snprintf(txt, sizeof(txt), "device: %s, sesid: %s", stobjses->s_devpath, uuidstr);
put_info_line(3, txt);
return FALSE;
}
/*ARGSUSED*/
int
stobjstrm_highlight(WINDOW *win, node_t *current, node_t *list)
{
static char txt[256];
data_t *d;
invt_stream_t *stobjstrm;
if(current == NULL || current->data == NULL) {
return 0;
}
d = (data_t *)(current->data);
stobjstrm = (invt_stream_t *)(stobj_file[d->file_idx].data[d->data_idx]);
wclear(infowin);
put_info_header("session stream");
snprintf(txt, sizeof(txt), "interrupted: %s, cmdarg: %s",
(stobjstrm->st_interrupted == BOOL_TRUE) ? "yes" : "no",
stobjstrm->st_cmdarg);
put_info_line(1, txt);
snprintf(txt, sizeof(txt), "start ino: %llu, offset %lld",
(unsigned long long) stobjstrm->st_startino.ino,
(long long) stobjstrm->st_startino.offset);
put_info_line(2, txt);
snprintf(txt, sizeof(txt), " end ino: %llu, offset %lld",
(unsigned long long) stobjstrm->st_endino.ino,
(long long) stobjstrm->st_endino.offset);
put_info_line(3, txt);
return FALSE;
}
/*ARGSUSED*/
int
stobjmed_highlight(WINDOW *win, node_t *current, node_t *list)
{
static char txt[256];
char uuidstr[UUID_STR_LEN + 1];
data_t *d;
invt_mediafile_t *stobjmed;
if(current == NULL || current->data == NULL) {
return 0;
}
d = (data_t *)(current->data);
stobjmed = (invt_mediafile_t *)(stobj_file[d->file_idx].data[d->data_idx]);
wclear(infowin);
put_info_header("session media file");
uuid_unparse(stobjmed->mf_moid, uuidstr);
snprintf(txt, sizeof(txt), "flags: %#x, id: %s", stobjmed->mf_flag, uuidstr);
put_info_line(1, txt);
snprintf(txt, sizeof(txt), "start ino: %llu, offset %lld",
(unsigned long long) stobjmed->mf_startino.ino,
(long long) stobjmed->mf_startino.offset);
put_info_line(2, txt);
snprintf(txt, sizeof(txt), " end ino: %llu, offset %lld",
(unsigned long long) stobjmed->mf_endino.ino,
(long long) stobjmed->mf_endino.offset);
put_info_line(3, txt);
return FALSE;
}
/*ARGSUSED*/
int
stobj_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
stobj_prune(char *mountpt, uuid_t *uuidp, time32_t prunetime, node_t *node, node_t *list)
{
data_t *d;
stobjsess_t *stobj;
invt_seshdr_t *stobj_header;
invt_session_t *stobj_session;
if(node == NULL || node->data == NULL) {
return BOOL_FALSE;
}
d = (data_t *)(node->data);
stobj = stobj_file[d->file_idx].data[d->data_idx];
stobj_header = stobj->header;
stobj_session = stobj->session;
if(stobj_header == NULL || stobj_session == NULL) {
return BOOL_FALSE;
}
if(stobj_header->sh_pruned) {
return BOOL_TRUE;
}
if(stobj_header->sh_time < prunetime) {
if(mountpt != NULL && mntpnt_equal(mountpt, stobj_session->s_mountpt)) {
return BOOL_TRUE;
}
if((!uuid_is_null(*uuidp))
&& (uuid_compare(*uuidp, stobj_session->s_fsid) == 0)) {
return BOOL_TRUE;
}
}
return BOOL_FALSE;
}
/*ARGSUSED*/
int
stobj_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;
}
int
add_stobj_data(int fidx, void *data)
{
if(stobj_file[fidx].numrecords == 0) {
stobj_file[fidx].data = malloc(sizeof(*stobj_file[fidx].data));
if(stobj_file[fidx].data == NULL) {
fprintf(stderr, "%s: internal memory error: stobj data allocation\n",
g_programName);
exit(1);
}
}
else {
stobj_file[fidx].data = realloc(stobj_file[fidx].data,
sizeof(*stobj_file[fidx].data)
* (stobj_file[fidx].numrecords + 1));
if(stobj_file[fidx].data == NULL) {
fprintf(stderr, "%s: internal memory error: stobj data reallocation\n",
g_programName);
exit(1);
}
}
stobj_file[fidx].data[stobj_file[fidx].numrecords] = data;
stobj_file[fidx].numrecords++;
return 0;
}
node_t *
generate_stobj_menu(node_t *startnode, int level, char *StObjFileName)
{
int i;
int j;
int k;
int idx;
int data_idx;
int len;
char *txt;
node_t *n;
node_t *parent_stream;
node_t *parent_session;
stobjsess_t *session;
invt_seshdr_t *StObjhdr;
invt_session_t *StObjses;
invt_stream_t *StObjstrm;
invt_mediafile_t *StObjmed;
if((idx = open_stobj(StObjFileName)) < 0) {
return startnode;
}
StObjhdr = (invt_seshdr_t *)( stobj_file[idx].mapaddr + sizeof(invt_sescounter_t));
StObjses = (invt_session_t *)(stobj_file[idx].mapaddr + StObjhdr->sh_sess_off);
data_idx = 0;
n = startnode;
for (i=0; i < stobj_file[idx].counter->ic_curnum; ) {
session = malloc(sizeof(*session));
if(session == NULL) {
fprintf(stderr, "%s: internal memory error: session malloc\n", g_programName);
exit(1);
}
session->header = StObjhdr;
session->session = StObjses;
len = 60+strlen(session->session->s_label);
txt = malloc(len);
if(txt == NULL) {
fprintf(stderr, "%s: internal memory error: invidx_text\n", g_programName);
exit(1);
}
snprintf(txt, len, " session level: %d label: %s",
session->header->sh_level,
session->session->s_label);
n = list_add(n, node_create(BOOL_TRUE, /* hidden */
BOOL_FALSE, /* expanded */
level, /* level */
session->header->sh_pruned, /* deleted */
idx, /* file_idx */
txt, /* text */
&(stobjsess_ops), /* menu ops */
startnode, /* parent */
NULL, /* children */
0, /* nbr_children */
data_idx));
if(n == NULL) {
fprintf(stderr, "%s: internal memory error: list_add: node_create: session\n", g_programName);
exit(1);
}
data_idx++;
add_stobj_data(idx, session);
parent_session = n;
for ( j = 0; j < (int) StObjses->s_cur_nstreams; j++ ) {
StObjstrm = (invt_stream_t *)(stobj_file[idx].mapaddr +
StObjhdr->sh_streams_off +
(j * sizeof(invt_stream_t)));
len = strlen(StObjstrm->st_cmdarg) + 33;
txt = malloc(len);
if(txt == NULL) {
fprintf(stderr, "%s: internal memory error: invidx_text\n", g_programName);
exit(1);
}
snprintf(txt, len, " stream: drive path: %s", StObjstrm->st_cmdarg);
n = list_add(n, node_create(BOOL_TRUE, /* hidden */
BOOL_FALSE, /* expanded */
level + 1, /* level */
session->header->sh_pruned, /* deleted */
idx, /* file_idx */
txt, /* text */
&(stobjstrm_ops), /* menu ops */
parent_session, /* parent */
NULL, /* children */
0, /* nbr_children */
data_idx));
if(n == NULL) {
fprintf(stderr, "%s: internal memory error: list_add: node_create: StObjstrm\n", g_programName);
exit(1);
}
data_idx++;
add_stobj_data(idx, StObjstrm);
parent_stream = n;
for ( k = 0; k < StObjstrm->st_nmediafiles; k++) {
StObjmed = (invt_mediafile_t *)(stobj_file[idx].mapaddr +
StObjstrm->st_firstmfile +
(k * sizeof(invt_mediafile_t)));
len = strlen(StObjmed->mf_label) + 26;
txt = malloc(len);
if(txt == NULL) {
fprintf(stderr, "%s: internal memory error: invidx_text\n", g_programName);
exit(1);
}
snprintf(txt, len, " media file: %s", StObjmed->mf_label);
n = list_add(n, node_create(BOOL_TRUE, /* hidden */
BOOL_FALSE, /* expanded */
level + 2, /* level */
session->header->sh_pruned, /* deleted */
idx, /* file_idx */
txt, /* text */
&(stobjmed_ops), /* menu ops */
parent_stream, /* parent */
NULL, /* children */
0, /* nbr_children */
data_idx));
if(n == NULL) {
fprintf(stderr, "%s: internal memory error: list_add: node_create: StObjmed\n", g_programName);
exit(1);
}
data_idx++;
add_stobj_data(idx, StObjmed);
}
}
i++;
StObjhdr = (invt_seshdr_t *)( stobj_file[idx].mapaddr + sizeof(invt_sescounter_t) +
(i * sizeof(invt_seshdr_t)) );
StObjses = (invt_session_t *)(stobj_file[idx].mapaddr + StObjhdr->sh_sess_off);
}
return n;
}
int
add_stobj(char *name, int fd, off_t size, char *mapaddr, invt_sescounter_t *counter)
{
static int highwatermark = 20;
if(stobj_numfiles == 0) {
stobj_file = malloc(sizeof(*stobj_file) * highwatermark);
if(stobj_file == NULL) {
fprintf(stderr, "%s: internal memory error: malloc stobj_file\n", g_programName);
exit(1);
}
}
else {
if(stobj_numfiles >= highwatermark - 1) {
highwatermark += highwatermark;
stobj_file = realloc(stobj_file, sizeof(*stobj_file) * highwatermark);
if(stobj_file == NULL) {
fprintf(stderr, "%s: internal memory error: realloc stobj_file\n", g_programName);
exit(1);
}
}
}
stobj_file[stobj_numfiles].size = size;
stobj_file[stobj_numfiles].mapaddr = mapaddr;
stobj_file[stobj_numfiles].fd = fd;
stobj_file[stobj_numfiles].counter = counter;
stobj_file[stobj_numfiles].name = name;
stobj_file[stobj_numfiles].data = NULL;
stobj_file[stobj_numfiles].numrecords = 0;
stobj_numfiles++;
return stobj_numfiles - 1;
}
int
open_stobj(char *StObjFileName)
{
int fd;
struct stat sb;
off_t size;
char *mapaddr;
invt_sescounter_t cnt;
char *name;
errno=0;
fd = open_and_lock( StObjFileName, FILE_WRITE, wait_for_locks );
if (fd < 0) {
return fd;
}
name = strdup(StObjFileName);
if(name == NULL) {
fprintf(stderr, "%s: internal memory error: strdup stobj_name\n", g_programName);
exit(1);
}
read_n_bytes(fd, &cnt, sizeof(invt_sescounter_t), StObjFileName);
lseek( fd, 0, SEEK_SET );
errno = 0;
if (fstat(fd, &sb) < 0) {
fprintf(stderr, "Could not get stat info on %s\n", StObjFileName);
perror("fstat");
return -1;
}
size = sb.st_size;
mapaddr = mmap_n_bytes(fd, size, BOOL_FALSE, StObjFileName);
return add_stobj(name, fd, size, mapaddr, (invt_sescounter_t *)mapaddr);
}
int
close_stobj_file(int fidx, int unlink_ok)
{
if(fidx >= stobj_numfiles || stobj_file[fidx].fd < 0)
return 0;
munmap( stobj_file[fidx].mapaddr, stobj_file[fidx].size);
close( stobj_file[fidx].fd );
stobj_file[fidx].fd = -1;
if(unlink_ok == BOOL_TRUE) {
unlink(stobj_file[fidx].name);
}
free( stobj_file[fidx].name );
free( stobj_file[fidx].data );
stobj_file[fidx].name = NULL;
stobj_file[fidx].data = NULL;
return 0;
}
int
close_all_stobj()
{
int i;
int j;
invt_seshdr_t *StObjhdr;
int unlink_ok;
for(i = 0; i < stobj_numfiles; i++) {
if(stobj_file[i].fd < 0)
continue;
unlink_ok = BOOL_TRUE;
StObjhdr = (invt_seshdr_t *)( stobj_file[i].mapaddr + sizeof(invt_sescounter_t));
for(j = 0; j < stobj_file[i].counter->ic_curnum; ) {
if(StObjhdr->sh_pruned != 1) {
unlink_ok = BOOL_FALSE;
break;
}
j++;
StObjhdr = (invt_seshdr_t *)( stobj_file[i].mapaddr + sizeof(invt_sescounter_t) +
(j * sizeof(invt_seshdr_t)) );
}
close_stobj_file(i, unlink_ok);
}
free(stobj_file);
stobj_file = NULL;
return 0;
}