/***************************************************************************/
/***************************************************************************/
/* */
/* (c) 1995-1999. The Regents of the University of California. All */
/* rights reserved. */
/* */
/* This work was produced at the University of California, Lawrence */
/* Livermore National Laboratory (UC LLNL) under contract no. */
/* W-7405-ENG-48 (Contract 48) between the U.S. Department of Energy */
/* (DOE) and The Regents of the University of California (University) */
/* for the operation of UC LLNL. Copyright is reserved to the */
/* University for purposes of controlled dissemination, */
/* commercialization through formal licensing, or other disposition */
/* under terms of Contract 48; DOE policies, regulations and orders; */
/* and U.S. statutes. The rights of the Federal Government are */
/* reserved under Contract 48 subject to the restrictions agreed upon */
/* by the DOE and University. */
/* */
/* */
/* DISCLAIMER */
/* */
/* This software was prepared as an account of work sponsored by an */
/* agency of the United States Government. Neither the United States */
/* Government nor the University of California nor any of their */
/* employees, makes any warranty, express or implied, or assumes any */
/* liability or responsibility for the accuracy, completeness, or */
/* usefulness of any information, apparatus, product, or process */
/* disclosed, or represents that its specific commercial products, */
/* process, or service by trade name, trademark, manufacturer, or */
/* otherwise, does not necessarily constitute or imply its */
/* endorsement, recommendation, or favoring by the United States */
/* Government or the University of California. The views and opinions */
/* of the authors expressed herein do not necessarily state or reflect */
/* those of the United States Government or the University of */
/* California, and shall not be used for advertising or product */
/* endorsement purposes. */
/* */
/* Permission to use, copy, modify and distribute this software and its */
/* documentation for any non-commercial purpose, without fee, is */
/* hereby granted, provided that the above copyright notice and this */
/* permission notice appear in all copies of the software and */
/* supporting documentation, and that all UC LLNL identification in */
/* the user interface remain unchanged. The title to copyright LLNL */
/* XDIR shall at all times remain with The Regents of the University */
/* of California and users agree to preserve same. Users seeking the */
/* right to make derivative works with LLNL XDIR for commercial */
/* purposes may obtain a license from the Lawrence Livermore National */
/* Laboratory's Technology Transfer Office, P.O. Box 808, L-795, */
/* Livermore, CA 94550. */
/* */
/***************************************************************************/
/***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <errno.h>
#include <Xm/Xm.h>
#include "xdir.h"
#include "xfer.h"
#include "str.h"
#include "list.h"
#ifndef P_tmpdir
#define P_tmpdir "/usr/tmp/"
#endif
#define MAXTRIES 10
int init_local_copy();
int do_local_copy();
int init_get();
int do_get();
static int (*init_fn[2])() = { init_local_copy, init_get };
static int (*do_fn[2])() = { do_local_copy, do_get };
char **path_to_links();
double stop_timer();
char *temp_file_name();
int cb_view_files();
char *merge_paths();
void delete_file_and_its_dir();
extern int xfer_mode;
extern struct st_host_info hinfo[];
extern struct xfer_ctrl_block xc;
extern XtAppContext app;
extern Display *display;
extern int diagnostics;
/*
* init_view - Initialize file transfer of selected files in directory
* window "dirwin" to temporary directory on local host
* for viewing. "list" is an array list containing the
* relative paths of the files to view.
*/
void
init_view(dirwin, list)
struct dirwin_st *dirwin;
struct sl_struct *list;
{
int retval;
int i;
int indx;
struct forest_node *forest;
struct forest_node **head;
struct forest_node *p;
struct forest_node *parent;
char **links;
char **link_ptr;
char *ptr;
char *rel_path;
char msg[MAXPATHLEN+30];
/* Clear error flag */
raise_okflag();
/* Make operation interruptable */
show_stop_button(dirwin);
/* This might take some time */
use_busy_cursor();
/* Make sure connection is still good */
if (dirwin->host != LOCAL) {
retval = check_connection(dirwin->host, dirwin);
if (retval < 0) {
restore_prev_cursor();
switch (retval) {
case -6:
record_abort("View Files");
break;
case -1:
record_and_alert("Unable to view file(s).", dirwin->w_shell);
}
hide_stop_button();
end_op();
return;
}
}
/* Set transfer mode */
if ((dirwin->host != LOCAL)
&& ((retval = ftp_type(dirwin->host, xfer_mode)) < 0)) {
restore_prev_cursor();
switch (retval) {
case -1:
record_and_alert("Unable to view file(s).", dirwin->w_shell);
break;
case -3:
restore_lost_connection(dirwin->host, dirwin);
break;
case -6:
record_abort("View Files");
}
hide_stop_button();
end_op();
return;
}
/* Form list of selected items to transfer */
forest = NULL;
for (i=list->nentries-1; i>=0; i--) {
links = path_to_links(hinfo[dirwin->host].system, list->entries[i]);
if (hinfo[dirwin->host].system == SYS_VMS) { /* Remove ".dir;n" */
link_ptr = links;
while (*link_ptr) {
if ((ptr = strstr(*link_ptr, ".dir")))
*ptr = '\0';
link_ptr++;
}
}
indx = 0;
p = forest;
head = &forest;
parent = NULL;
while (links[indx])
if (p && !strcmp(p->entry, links[indx])) {
if (p->position == AT_START_NODE) {
if (links[indx+1]) {
src_paths_of_xfer_node(p, &rel_path, NULL);
sprintf(msg, "Can't view directory %s", rel_path);
XtFree(rel_path);
record_warning(msg);
xc.error = True;
p->position = ABOVE_START_NODE;
p->type = TYPE_DIR;
} else
break; /* Duplicate entry. Can this happen? */
} else if (!links[indx+1]) {
sprintf(msg, "Can't view directory %s", list->entries[i]);
record_warning(msg);
xc.error = True;
break;
}
parent = p;
head = &p->first_child;
p = p->first_child;
indx++;
} else if (p && p->next)
p = p->next;
else {
p = XtNew(struct forest_node);
p->entry = XtNewString(links[indx]);
p->first_child = NULL;
p->parent = parent;
p->status = NOT_PROCESSED;
p->next = *head;
if (links[indx+1]) {
p->position = ABOVE_START_NODE;
p->type = TYPE_DIR;
} else {
p->type = TYPE_FILE;
p->position = AT_START_NODE;
}
parent = p;
*head = p;
head = &p->first_child;
p = p->first_child;
indx++;
}
release_path_links(links);
}
/* Set up transfer control block */
xc.operation = VIEW;
xc.mode = xfer_mode;
xc.level = 0;
xc.state = 0;
xc.nretries = 0;
xc.error = False;
xc.src_dirwin = dirwin;
xc.src_host_system = hinfo[dirwin->host].system;
xc.src_host_server = hinfo[dirwin->host].server;
xc.snk_host_system = SYS_UNIX;
xc.src_dirname = XtNewString(dirwin->dirname);
xc.snk_dirname = XtNewString("");
xc.forest = forest;
xc.node[0] = forest;
xc.nstages = 0;
xc.file_count = 0;
xc.file_total = nfiles_in_xfer_forest();
xc.more_files = True;
if (dirwin->host == LOCAL)
xc.src_host_type = XLOCAL;
else
xc.src_host_type = XREMOTE;
/* Transfer file */
show_xfermon(dirwin);
set_xfermon_status(STATUS_PASS1);
set_xfermon_name_label("File Name:");
set_xfermon_progress((long)-1, (long)-1, (double)0.0);
set_xfermon_file_count(0, xc.file_total);
XSync(display, 0);
XtAppAddWorkProc(app, (XtWorkProc)cb_view_files, NULL);
}
/*
* cb_view_files - Work proc for transferring and viewing files.
*/
cb_view_files()
{
long current_time;
struct forest_node *tmp_node;
char *rel_path;
char *full_path;
char msg[MAXPATHLEN+40];
int i;
int retval;
int retval1;
int retval2;
double ftime;
char *temp_ptr;
char *snk_path;
char *src_path;
char *q;
/* Perform next step of file transfers */
switch (xc.state) {
case 0: /* No xfer in progress */
if (stop()) {
xfer_abort(False);
return True;
}
if ((xc.nstages == MAXSTAGES) || (xc.nstages && !xc.more_files)) {
src_paths_of_xfer_node(xc.staged_file[0].node, &rel_path, NULL);
set_xfermon_status(STATUS_WAIT);
set_xfermon_name(rel_path);
set_xfermon_progress((long)-1, (long)-1, (double)0.0);
XSync(display, 0);
XtFree(rel_path);
current_time = time_of_day();
if (current_time < xc.staged_file[0].time+STAGE_DELTA) {
if (rest_stop(DELTA) == -6) {
xfer_abort(False);
return True;
} else
return False;
}
src_paths_of_xfer_node(xc.staged_file[0].node, NULL, &full_path);
retval = stage_file(xc.src_dirwin->host, full_path);
XtFree(full_path);
switch (retval) {
case -6:
xfer_abort(False);
return True;
case -3:
xfer_done(True, False);
return True;
case -1:
src_paths_of_xfer_node(xc.staged_file[0].node, &rel_path, NULL);
sprintf(msg, "Unable to initialize transfer of %s", rel_path);
XtFree(rel_path);
record_warning(msg);
xc.error = True;
for (i=1; i<xc.nstages; i++) {
xc.staged_file[i-1].node = xc.staged_file[i].node;
xc.staged_file[i-1].time = xc.staged_file[i].time;
}
xc.nstages--;
break;
case 0:
xc.current_node = xc.staged_file[0].node;
for (i=1; i<xc.nstages; i++) {
xc.staged_file[i-1].node = xc.staged_file[i].node;
xc.staged_file[i-1].time = xc.staged_file[i].time;
}
xc.nstages--;
xc.state = 1;
break;
case 1:
tmp_node = xc.staged_file[0].node;
for (i=1; i<xc.nstages; i++) {
xc.staged_file[i-1].node = xc.staged_file[i].node;
xc.staged_file[i-1].time = xc.staged_file[i].time;
}
xc.staged_file[xc.nstages-1].node = tmp_node;
xc.staged_file[xc.nstages-1].time = current_time;
}
return False;
} else if (xc.more_files) {
while (1) {
if (xc.node[xc.level] == NULL) {
xc.level--;
if (xc.level < 0) {
xc.more_files = False;
return False;
}
xc.node[xc.level] = xc.node[xc.level]->next;
} else if (xc.node[xc.level]->type == TYPE_DIR) {
xc.node[xc.level+1] = xc.node[xc.level]->first_child;
xc.level++;
} else if (xc.node[xc.level]->type == TYPE_FILE) {
if ((xc.src_host_server == SERVER_UNIX_UNITREE) ||
(xc.src_host_server == SERVER_UNIX_NSL_UNITREE) ||
(xc.src_host_server == SERVER_UNIX_HPSS)) {
current_time = time_of_day();
src_paths_of_xfer_node(xc.node[xc.level], &rel_path,
&full_path);
set_xfermon_status(STATUS_STAGE);
set_xfermon_name(rel_path);
set_xfermon_progress((long)-1, (long)-1, (double)0.0);
XSync(display, 0);
retval = stage_file(xc.src_dirwin->host, full_path);
XtFree(rel_path);
XtFree(full_path);
switch (retval) {
case -6:
xfer_abort(False);
return True;
case -3:
xfer_done(True, False);
return True;
case -1:
src_paths_of_xfer_node(xc.node[xc.level], &rel_path,
NULL);
sprintf(msg, "Unable to initialize transfer of %s",
rel_path);
XtFree(rel_path);
record_warning(msg);
xc.error = True;
xc.node[xc.level] = xc.node[xc.level]->next;
return False;
case 1:
xc.staged_file[xc.nstages].node = xc.node[xc.level];
xc.staged_file[xc.nstages].time = current_time;
xc.nstages++;
xc.node[xc.level] = xc.node[xc.level]->next;
return False;
}
}
xc.current_node = xc.node[xc.level];
xc.node[xc.level] = xc.node[xc.level]->next;
xc.state = 1;
return False;
} else
fatal_error("Bug in cb_view_files()");
}
} else {
xfer_done(False, False);
if (xc.error)
record_and_alert("At least one file cannot be viewed.",
xc.src_dirwin->w_shell);
return True;
}
case 1: /* Initialize file transfer */
if (stop()) {
xfer_done(False, False);
return True;
}
if (xc.src_host_type == XLOCAL) {
src_paths_of_xfer_node(xc.current_node, NULL, &src_path);
if (!need_to_decompress(src_path)) {
if (view_file(xc.src_dirwin, src_path, True) == -6) {
xfer_abort(True);
XtFree(src_path);
return True;
}
XtFree(src_path);
xc.state = 0;
xc.nretries = 0;
return False;
}
XtFree(src_path);
}
if ((temp_ptr = temp_file_name()) == NULL) {
src_paths_of_xfer_node(xc.current_node, &rel_path, NULL);
sprintf(msg, "Can't create temp directory for %s.", rel_path);
record_warning("Unable to create temporary directory for viewer");
XtFree(rel_path);
xc.error = True;
xc.state = 0;
xc.nretries = 0;
return False;
}
XtFree(xc.snk_dirname);
xc.snk_dirname = temp_ptr;
src_paths_of_xfer_node(xc.current_node, &rel_path, NULL);
if (xc.mode == ASCII)
set_xfermon_status(STATUS_XFER_ASCII);
else
set_xfermon_status(STATUS_XFER_BINARY);
set_xfermon_name(rel_path);
set_xfermon_progress((long)-1, (long)-1, (double)0.0);
XSync(display, 0);
XtFree(rel_path);
retval1 = local_mkdir(xc.snk_dirname, 0700);
if (retval1 == 0)
retval2 = (*init_fn[xc.src_host_type])();
if ((retval1 == 0) && (retval2 == -6)) {
snk_paths_of_xfer_node(xc.current_node, NULL, &snk_path);
xfer_abort(True);
delete_file_and_its_dir(snk_path);
XtFree(snk_path);
return True;
} else if ((retval1 == -1) || (retval2 == -1)) {
src_paths_of_xfer_node(xc.current_node, &rel_path, NULL);
sprintf(msg, "Unable to initialize transfer of %s", rel_path);
record_warning(msg);
XtFree(rel_path);
snk_paths_of_xfer_node(xc.current_node, NULL, &snk_path);
delete_file_and_its_dir(snk_path);
XtFree(snk_path);
xc.error = True;
xc.state = 0;
xc.nretries = 0;
return False;
} else if ((retval1 == 0) && (retval2 == -3)) {
snk_paths_of_xfer_node(xc.current_node, NULL, &snk_path);
xfer_done(True, False);
delete_file_and_its_dir(snk_path);
XtFree(snk_path);
return True;
} else {
set_xfermon_progress(xc.file_len, xc.file_index, stop_timer());
XSync(display, 0);
start_timer();
xc.state = 2;
return False;
}
case 2: /* File transfer in progress */
if (stop()) {
snk_paths_of_xfer_node(xc.current_node, NULL, &snk_path);
xfer_abort(True);
delete_file_and_its_dir(snk_path);
XtFree(snk_path);
return True;
}
switch ((*do_fn[xc.src_host_type])()) {
case -6:
snk_paths_of_xfer_node(xc.current_node, NULL, &snk_path);
xfer_abort(True);
delete_file_and_its_dir(snk_path);
XtFree(snk_path);
return True;
case -3:
snk_paths_of_xfer_node(xc.current_node, NULL, &snk_path);
xfer_done(True, False);
delete_file_and_its_dir(snk_path);
XtFree(snk_path);
return True;
case -1:
src_paths_of_xfer_node(xc.current_node, &rel_path, NULL);
sprintf(msg, "Unable to complete transfer of %s", rel_path);
record_warning(msg);
XtFree(rel_path);
snk_paths_of_xfer_node(xc.current_node, NULL, &snk_path);
delete_file_and_its_dir(snk_path);
XtFree(snk_path);
xc.error = True;
xc.state = 0;
xc.nretries = 0;
return False;
case 0: /* Transfer complete */
set_xfermon_progress(xc.file_len, xc.file_index, stop_timer());
xc.file_count++;
set_xfermon_file_count(xc.file_count, xc.file_total);
XSync(display, 0);
ftime = stop_timer();
if (diagnostics >= NORMAL) {
src_paths_of_xfer_node(xc.current_node, &rel_path, NULL);
sprintf(msg, "*** Successfully transferred file: %s\n",
rel_path);
write_log(msg);
XtFree(rel_path);
print_xfer_stats(ftime, xc.file_len);
}
snk_paths_of_xfer_node(xc.current_node, NULL, &snk_path);
if (xc.src_host_system == SYS_VMS) {
if ((q = strrchr(snk_path, ';')))
*q = '\0';
}
if (view_file(xc.src_dirwin, snk_path, False) == -6) {
xfer_abort(True);
delete_file_and_its_dir(snk_path);
XtFree(snk_path);
return True;
}
XtFree(snk_path);
xc.state = 0;
xc.nretries = 0;
return False;
case 1: /* More to transfer */
set_xfermon_progress(xc.file_len, xc.file_index, stop_timer());
return False;
}
}
return True; /* Make gcc compiler happy (shouldn't get here) */
}
/*
* temp_file_name - Create a unique name for a temporary file in the
* directory defined as P_tmpdir in <stdio.h>. If the
* environment variable TMPDIR is defined, it is used
* as the directory. If successful, this function returns
* a pointer to the name, which can be released by calling
* XtFree(); if unsuccessful, NULL is returned. The name
* will begin with the prefix "xdir".
*/
char *
temp_file_name()
{
char *dir_path = NULL;
char *file_path;
char *temp;
int pid;
char pid_string[5];
char suffix[5];
int i;
int j;
/* Get directory path */
if ((temp = getenv("TMPDIR")))
dir_path = XtNewString(temp);
else
dir_path = XtNewString(P_tmpdir);
/* Verify that directory is accessible */
if (access(dir_path, 0) < 0) {
XtFree(dir_path);
return NULL;
}
/* Convert PID into string */
pid = getpid();
sprintf(pid_string, "%04d", pid%10000);
/* Try several times to create a unique name */
for (i=0; i<MAXTRIES; i++) {
for (j=0; j<4; j++)
suffix[j] = ((rand()&0xff)%26)+'A';
suffix[4] = '\0';
file_path = XtMalloc(strlen(dir_path)+14);
strcpy(file_path, dir_path);
if (file_path[strlen(file_path)-1] != '/')
strcat(file_path, "/");
strcat(file_path, "xdir");
strcat(file_path, pid_string);
strcat(file_path, suffix);
if (access(file_path, 0) < 0) {
if (errno == ENOENT) {
XtFree(dir_path);
return file_path;
}
}
XtFree(file_path);
}
XtFree(dir_path);
return NULL;
}
/*
* delete_file_and_its_dir - Delete "file" and the "dir" that contains it.
* No errors are reported if the file and/or
* directory do not exist, or if unable to
* delete either.
*/
void
delete_file_and_its_dir(file)
char *file;
{
char *dir;
parse_path(SYS_UNIX, file, &dir, NULL);
delete_dir_and_its_files(dir);
XtFree(dir);
}
/*
* delete_dir_and_its_files - Delete the directory specified by "dir"
* and any files it might contain. "dir"
* must be a full path specification. Returns
* 0 for success and -1 for failure.
*/
delete_dir_and_its_files(dir)
char *dir;
{
struct sl_struct *dlist;
char *temp;
char *temp_dir;
int i;
int retval = 0;
/* Important safety check. Delete only temp directories */
if ((temp = getenv("TMPDIR")))
temp_dir = XtNewString(temp);
else
temp_dir = XtNewString(P_tmpdir);
if (strlen(temp_dir) > strlen(dir))
fatal_error("Bug in delete_dir_and_its_files()");
temp = XtNewString(dir);
temp[strlen(temp_dir)] = '\0';
if (strcmp(temp, temp_dir))
fatal_error("Bug in delete_dir_and_its_files()");
XtFree(temp);
XtFree(temp_dir);
/* Delete all entries in the directory */
if (get_dirlist(LOCAL, dir, TABULAR, True, False, False, &dlist) == 0) {
for (i=0; i<dlist->nentries; i++) {
temp = merge_paths(SYS_UNIX, dir, dlist->entries[i]);
if (unlink(temp) < 0)
retval = -1;
XtFree(temp);
}
release_array_list(dlist);
} else
retval = -1;
/* Now remove its directory */
if (rmdir(dir) < 0)
retval = -1;
/* Get out of here */
return retval;
}
syntax highlighted by Code2HTML, v. 0.9.1