/***************************************************************************/
/***************************************************************************/
/* */
/* (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 <Xm/ToggleB.h>
#include "xdir.h"
#include "xfer.h"
#include "str.h"
struct xfer_ctrl_block xc;
static char *not_implemented_msg = "Copying entry(s) from a remote host to itself not implemented.\n\nConsider moving entry(s) instead (by holding down the Control\nkey when the mouse button is released over the drop site).";
char *xfer_question = "You are attempting to copy a directory, but\nthe general preference COPY MODE is set to\nNONRECURSIVE.\n\nCopy directories anyway?";
char *recursion_disabled_msg = "Recursion disabled. Can't transfer directory %s";
char *merge_paths();
char *links_to_path();
char *entry_to_full_path();
char *entry_to_rel_path();
char **path_to_links();
void release_xfer_subforest();
int cb_examine_src_forest();
extern int inquire_on_copy;
extern struct st_host_info hinfo[];
extern XtAppContext app;
extern int rcopy_mode;
extern int xfer_mode;
/*
* init_copy - Initialize file transfer of selected files in directory
* window "src_dirwin" to directory window "snk_dirwin". If
* "einfo" is non-NULL then transfer the files into the
* directory represented by "einfo".
*/
void
init_copy(src_dirwin, snk_dirwin, einfo)
struct dirwin_st *src_dirwin;
struct dirwin_st *snk_dirwin;
struct entry_info *einfo;
{
int src_host = src_dirwin->host;
int snk_host = snk_dirwin->host;
int operation = rcopy_mode?RCOPY:COPY;
int asked_user = False;
int retval;
int indx;
int i;
int j;
int nlinks;
char *temp_snk_dir;
char *snk_dir;
struct forest_node **head;
char *ptr;
char *rel_path;
char **links;
char **link_ptr;
struct forest_node *forest;
struct forest_node *p;
struct forest_node *parent;
char msg[MAXPATHLEN+50];
/* Start operation */
if (!start_op(True))
return;
/* Clear error flag */
raise_okflag();
/* Is operation implemented */
if ((src_host != LOCAL) && (src_host == snk_host)) {
warn(not_implemented_msg, snk_dirwin->w_shell);
end_op();
return;
}
/* Ask the user if okay to copy */
if (inquire_on_copy) {
if (!verify_selection(src_dirwin, snk_dirwin,
"Do you really want to copy these entries?")) {
end_op();
return;
}
}
/* Make operation interruptable */
show_stop_button(snk_dirwin);
/* This might take some time */
use_busy_cursor();
/* Make sure remote connections are still good */
if (src_host != LOCAL) {
retval = check_connection(src_host, snk_dirwin);
if (retval < 0) {
switch (retval) {
case -6:
record_abort("Copy Files");
break;
case -1:
record_and_alert("Unable to transfer file(s).",
snk_dirwin->w_shell);
}
restore_prev_cursor();
hide_stop_button();
end_op();
return;
}
}
if (snk_host != LOCAL) {
retval = check_connection(snk_host, snk_dirwin);
if (retval < 0) {
switch (retval) {
case -6:
record_abort("Copy Files");
break;
case -1:
record_and_alert("Unable to transfer file(s).",
snk_dirwin->w_shell);
}
restore_prev_cursor();
hide_stop_button();
end_op();
return;
}
}
/* Determine true sink directory path */
if (einfo)
temp_snk_dir = entry_to_full_path(einfo);
else
temp_snk_dir = XtNewString(snk_dirwin->dirname);
retval = determine_true_path(snk_dirwin->host, temp_snk_dir, True, False,
False, &snk_dir);
XtFree(temp_snk_dir);
if (retval < 0) {
switch (retval) {
case -1:
record_and_alert("Unable to transfer file(s).",snk_dirwin->w_shell);
break;
case -3:
restore_lost_connection(snk_dirwin->host, snk_dirwin);
break;
case -6:
record_abort("Copy Files");
}
restore_prev_cursor();
hide_stop_button();
end_op();
return;
}
/* Form list of selected entries */
forest = NULL;
for (i=src_dirwin->nentries-1; i>=0; i--) {
if (src_dirwin->entries[i].state != SELECTED)
continue;
if (src_dirwin->entries[i].type == DIRECTORY_TYPE) {
if ((operation == COPY) && !asked_user) {
beep();
if (question_dialog(xfer_question, snk_dirwin->w_shell))
operation = RCOPY;
asked_user = True;
}
if (operation == COPY) {
rel_path = entry_to_rel_path(&src_dirwin->entries[i]);
sprintf(msg, recursion_disabled_msg, rel_path);
XtFree(rel_path);
record_warning(msg);
continue;
}
}
rel_path = entry_to_rel_path(&src_dirwin->entries[i]);
links = path_to_links(hinfo[src_dirwin->host].system, rel_path);
XtFree(rel_path);
if (hinfo[src_dirwin->host].system == SYS_VMS) {
nlinks = 0;
link_ptr = links;
while (*link_ptr++)
nlinks++;
if (src_dirwin->entries[i].type == UNKNOWN_TYPE) {
if (strstr(links[nlinks-1], ".dir"))
src_dirwin->entries[i].type = DIRECTORY_TYPE;
else
src_dirwin->entries[i].type = FILE_TYPE;
}
for (j=0; j<nlinks; j++) /* Remove ".dir;n" */
if ((ptr = strstr(links[j], ".dir")))
*ptr = '\0';
}
indx = 0;
p = forest;
head = &forest;
parent = NULL;
while (links[indx])
if (p && !strcmp(p->entry, links[indx])) {
if (p->position == AT_START_NODE)
break;
if (!links[indx+1]) {
p->position = AT_START_NODE;
release_xfer_subforest(p->first_child);
p->first_child = NULL;
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->position = AT_START_NODE;
switch (src_dirwin->entries[i].type) {
case UNKNOWN_TYPE:
case LINK_TYPE:
case SOCKET_TYPE:
p->type = TYPE_UNKNOWN;
break;
case DIRECTORY_TYPE:
p->type = TYPE_DIR;
break;
case FILE_TYPE:
case EXECUTABLE_TYPE:
p->type = TYPE_FILE;
}
}
parent = p;
*head = p;
head = &p->first_child;
p = p->first_child;
indx++;
}
release_path_links(links);
}
/* Set up transfer control block */
xc.operation = operation;
xc.mode = xfer_mode;
xc.level = 0;
xc.state = 0;
xc.nretries = 0;
xc.error = False;
xc.asked_user = asked_user;
xc.src_dirwin = src_dirwin;
xc.snk_dirwin = snk_dirwin;
xc.src_host_system = hinfo[src_dirwin->host].system;
xc.src_host_server = hinfo[src_dirwin->host].server;
xc.snk_host_system = hinfo[snk_dirwin->host].system;
xc.src_dirname = XtNewString(src_dirwin->dirname);
xc.snk_dirname = snk_dir;
xc.forest = forest;
xc.s0ptr = forest;
xc.s0head = &xc.forest;
xc.node[0] = forest;
xc.nstages = 0;
xc.more_files = True;
if (src_dirwin->host == LOCAL)
xc.src_host_type = XLOCAL;
else
xc.src_host_type = XREMOTE;
if (snk_dirwin->host == LOCAL)
xc.snk_host_type = XLOCAL;
else
xc.snk_host_type = XREMOTE;
/* Transfer files */
show_xfermon(snk_dirwin);
set_xfermon_status(STATUS_PASS1);
set_xfermon_name_label("Directory:");
set_xfermon_progress((long)-1, (long)-1, (double)0.0);
set_xfermon_file_count(0, -1);
XtAppAddWorkProc(app, (XtWorkProc)cb_examine_src_forest, NULL);
}
/*
* test_for_dir - Returns 0 if full path is a directory, -1 if path is not a
* directory, -3 if connection is lost, and -6 if stop button
* pushed.
*/
test_for_dir(host, path)
int host;
char *path;
{
if (host == LOCAL) {
if (local_cd(path, False) == 0)
return 0;
} else
switch (remote_cd(host, path, False)) {
case -3:
return -3;
case -6:
return -6;
case 0:
return 0;
}
return -1;
}
/*
* rel_path_of_xfer_node - Given an xfer node, return the corresponding
* entry's relative path in native format.
* "which" can be either SOURCE or SINK.
*/
char *
rel_path_of_xfer_node(system, node, which)
int system;
struct forest_node *node;
int which;
{
struct forest_node *ptr;
char **links;
char *rel_path;
int i;
int nlinks;
/* Determine number of links */
nlinks = 0;
ptr = node;
while (ptr) {
nlinks++;
if ((which == SINK) && (ptr->position == AT_START_NODE))
break;
ptr = ptr->parent;
}
links = (char **)XtMalloc(sizeof(char *)*(nlinks+1));
ptr = node;
for (i=nlinks-1; i>=0; i--) {
if (system == SYS_VMS) {
switch (ptr->type) {
case TYPE_DIR:
links[i] = XtMalloc(strlen(ptr->entry)+5);
strcpy(links[i], ptr->entry);
strcat(links[i], ".dir");
break;
case TYPE_FILE:
links[i] = XtNewString(ptr->entry);
break;
case TYPE_UNKNOWN:
fatal_error("Bug in rel_path_of_xfer_node()");
}
} else
links[i] = XtNewString(ptr->entry);
ptr = ptr->parent;
}
links[nlinks] = NULL;
rel_path = links_to_path(system, links, nlinks);
release_path_links(links);
return rel_path;
}
/*
* src_paths_of_xfer_node - Given an xfer node, return the corresponding
* entry's source relative path and source full
* path in native format. "rel_path" and
* "full_path" may be NULL, if that value is not
* to be returned. Use XtFree() to release the
* returned memory.
*/
void
src_paths_of_xfer_node(node, rel_path, full_path)
struct forest_node *node;
char **rel_path;
char **full_path;
{
char *tmp_rel_path;
char *tmp_full_path;
/* Create paths */
tmp_rel_path = rel_path_of_xfer_node(xc.src_host_system, node, SOURCE);
tmp_full_path = merge_paths(xc.src_host_system, xc.src_dirname,
tmp_rel_path);
/* Return relative path? */
if (rel_path)
*rel_path = tmp_rel_path;
else
XtFree(tmp_rel_path);
/* Return full path? */
if (full_path)
*full_path = tmp_full_path;
else
XtFree(tmp_full_path);
}
/*
* snk_paths_of_xfer_node - Given an xfer node, return the corresponding
* entry's sink relative path and sink full
* path in native format. "rel_path" and
* "full_path" may be NULL, if that value is not
* to be returned. Use XtFree() to release the
* returned memory.
*/
void
snk_paths_of_xfer_node(node, rel_path, full_path)
struct forest_node *node;
char **rel_path;
char **full_path;
{
char *tmp_rel_path;
char *tmp_full_path;
/* Create paths */
tmp_rel_path = rel_path_of_xfer_node(xc.snk_host_system, node, SINK);
tmp_full_path = merge_paths(xc.snk_host_system, xc.snk_dirname,
tmp_rel_path);
/* Return relative path? */
if (rel_path)
*rel_path = tmp_rel_path;
else
XtFree(tmp_rel_path);
/* Return full path? */
if (full_path)
*full_path = tmp_full_path;
else
XtFree(tmp_full_path);
}
/*
* print_xfer_forest
*/
void
print_xfer_forest()
{
struct forest_node *node[MAXLEVELS];
int level = 0;
int i;
node[0] = xc.forest;
while (1) {
if (node[level] == NULL) {
level--;
if (level < 0)
return;
node[level] = node[level]->next;
} else if (node[level]->type == TYPE_DIR) {
for (i=0; i<3*level; i++)
printf(" ");
if (node[level]->position == ABOVE_START_NODE)
printf("P %s\n", node[level]->entry);
else
printf("D %s\n", node[level]->entry);
node[level+1] = node[level]->first_child;
level++;
} else if (node[level]->type == TYPE_UNKNOWN) {
for (i=0; i<3*level; i++)
printf(" ");
printf("U %s\n", node[level]->entry);
node[level] = node[level]->next;
} else {
for (i=0; i<3*level; i++)
printf(" ");
printf("F %s\n", node[level]->entry);
node[level] = node[level]->next;
}
}
}
/*
* release_xfer_forest - Release memory used by transfer forest.
*/
void
release_xfer_forest()
{
release_xfer_subforest(xc.forest);
}
/*
* release_xfer_subforest - Release memory used by forest starting at "node".
*/
void
release_xfer_subforest(node)
struct forest_node *node;
{
struct forest_node *ptr1;
struct forest_node *ptr2;
/* If forest is empty, nothing to do */
if (!node)
return;
/* March through siblings */
ptr1 = node;
while (ptr1) {
release_xfer_subforest(ptr1->first_child);
XtFree(ptr1->entry);
ptr2 = ptr1;
ptr1 = ptr1->next;
XtFree((char *)ptr2);
}
}
/*
* nfiles_in_xfer_forest - Returns number of file in the transfer forest.
*/
nfiles_in_xfer_forest()
{
struct forest_node *node[MAXLEVELS];
int level = 0;
int count = 0;
node[0] = xc.forest;
while (1) {
if (node[level] == NULL) {
level--;
if (level < 0)
return count;
node[level] = node[level]->next;
} else if (node[level]->type == TYPE_DIR) {
node[level+1] = node[level]->first_child;
level++;
} else if (node[level]->type == TYPE_FILE) {
count++;
node[level] = node[level]->next;
} else
fatal_error("Bug in nfiles_in_xfer_forest()");
}
}
syntax highlighted by Code2HTML, v. 0.9.1