Initial import of the CDE 2.1.30 sources from the Open Group.
This commit is contained in:
19
cde/programs/dtfile/dtcopy/Imakefile
Normal file
19
cde/programs/dtfile/dtcopy/Imakefile
Normal file
@@ -0,0 +1,19 @@
|
||||
XCOMM $XConsortium: Imakefile /main/7 1996/09/14 15:17:43 drk $
|
||||
|
||||
DEFINES = -DXK_MISCELLANY -DSHAPE
|
||||
|
||||
DEPLIBS = DepDtClientLibs
|
||||
LOCAL_LIBRARIES = DtClientLibs
|
||||
SYS_LIBRARIES = DtClientSysLibs DtClientExtraLibs
|
||||
|
||||
#if defined (SunArchitecture)
|
||||
EXTRA_CCOPTIONS = -xF
|
||||
#endif
|
||||
|
||||
SRCS = main_dtcopy.c copydialog.c overwrtdialog.c dosync.c \
|
||||
fsrtns.c utils.c errordialog.c sharedFuncs.c
|
||||
|
||||
OBJS = main_dtcopy.o copydialog.o overwrtdialog.o dosync.o \
|
||||
fsrtns.o utils.o errordialog.o sharedFuncs.o
|
||||
|
||||
ComplexProgramTarget(dtfile_copy)
|
||||
776
cde/programs/dtfile/dtcopy/copydialog.c
Normal file
776
cde/programs/dtfile/dtcopy/copydialog.c
Normal file
@@ -0,0 +1,776 @@
|
||||
/* $XConsortium: copydialog.c /main/6 1996/10/29 17:08:29 mustafa $ */
|
||||
/************************************<+>*************************************
|
||||
****************************************************************************
|
||||
*
|
||||
* FILE: copydialog.c
|
||||
*
|
||||
*
|
||||
* DESCRIPTION: create dtcopy main dialog window
|
||||
*
|
||||
* FUNCTIONS: cancel_callback
|
||||
* create_copydir_dialog
|
||||
* create_error_text_window
|
||||
* desensitize_copy_action_area
|
||||
* display_cancel_warning
|
||||
* get_icons
|
||||
* ok_callback
|
||||
* pause_callback
|
||||
* sensitize_copy_action_area
|
||||
* warning_no_callback
|
||||
* warning_yes_callback
|
||||
*
|
||||
*
|
||||
* (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
|
||||
* (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
|
||||
* (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
|
||||
* (c) Copyright 1993, 1994, 1995 Novell, Inc.
|
||||
*
|
||||
****************************************************************************
|
||||
************************************<+>*************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <sys/wait.h>
|
||||
#include <time.h>
|
||||
#include <X11/Intrinsic.h>
|
||||
#include <X11/StringDefs.h>
|
||||
#include <Xm/Xm.h>
|
||||
#include <Xm/XmP.h>
|
||||
#include <Xm/PushB.h>
|
||||
#include <Xm/Label.h>
|
||||
#include <Xm/Form.h>
|
||||
#include <Xm/Frame.h>
|
||||
#include <Xm/BulletinB.h>
|
||||
#include <Xm/Text.h>
|
||||
#include <Xm/TextF.h>
|
||||
#include <Xm/ScrolledW.h>
|
||||
#include <Xm/Separator.h>
|
||||
#include <Xm/XmStrDefs.h>
|
||||
#include <Xm/ToggleB.h>
|
||||
|
||||
#include "dtcopy.h"
|
||||
#include "sharedFuncs.h"
|
||||
|
||||
|
||||
#define VERTICAL_SPACING 5
|
||||
#define HORIZONTAL_SPACING 8
|
||||
#define TOP_SPACING (VERTICAL_SPACING + 5)
|
||||
#define INDENTED_SPACING (HORIZONTAL_SPACING + 5)
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* Global variables
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
static Pixmap pxWorking;
|
||||
static Pixmap pxStopped;
|
||||
static int pxWorkingMargin;
|
||||
static int pxStoppedMargin;
|
||||
static Widget icon;
|
||||
|
||||
|
||||
|
||||
|
||||
static void
|
||||
get_icons(
|
||||
Widget w)
|
||||
{
|
||||
Arg args[2];
|
||||
Pixel background, foreground, top_shadow, bottom_shadow, select;
|
||||
Colormap colormap;
|
||||
|
||||
unsigned int width1, width2, height, dummy;
|
||||
|
||||
/* get foreground and background colors */
|
||||
XtSetArg (args[0], XmNbackground, &background);
|
||||
XtSetArg (args[1], XmNcolormap, &colormap);
|
||||
XtGetValues (w, args, 2);
|
||||
XmGetColors ( XtScreen(w) , colormap, background,
|
||||
&foreground, &top_shadow, &bottom_shadow, &select);
|
||||
|
||||
/* get "working" pixmap */
|
||||
pxWorking = XmGetPixmapByDepth(XtScreen(w), "xm_working",
|
||||
foreground, background, w->core.depth);
|
||||
if (pxWorking == XmUNSPECIFIED_PIXMAP)
|
||||
pxWorking = XmGetPixmapByDepth(XtScreen(w), "default_xm_working",
|
||||
foreground, background, w->core.depth);
|
||||
|
||||
/* get "stopped/done" pixmap */
|
||||
pxStopped = XmGetPixmapByDepth(XtScreen(w), "xm_information",
|
||||
foreground, background, w->core.depth);
|
||||
if (pxStopped == XmUNSPECIFIED_PIXMAP)
|
||||
pxStopped = XmGetPixmapByDepth(XtScreen(w), "default_xm_information",
|
||||
foreground, background, w->core.depth);
|
||||
|
||||
/* get the width of the two pixmaps */
|
||||
XGetGeometry(XtDisplay(w), pxWorking,
|
||||
(Window *) &dummy, /* returned root window */
|
||||
(int *) &dummy, (int *) &dummy, /* x, y of pixmap */
|
||||
&width1, &height, /* pixmap width, height */
|
||||
&dummy, &dummy); /* border width, depth */
|
||||
XGetGeometry(XtDisplay(w), pxStopped,
|
||||
(Window *) &dummy, /* returned root window */
|
||||
(int *) &dummy, (int *) &dummy, /* x, y of pixmap */
|
||||
&width2, &height, /* pixmap width, height */
|
||||
&dummy, &dummy); /* border width, depth */
|
||||
|
||||
/* Compute margins necessary to make the labels the same width */
|
||||
if (width1 > width2)
|
||||
{
|
||||
pxWorkingMargin = 0;
|
||||
pxStoppedMargin = width1 - width2;
|
||||
}
|
||||
else
|
||||
{
|
||||
pxWorkingMargin = width2 - width1;
|
||||
pxStoppedMargin = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* sensitize & desensitize buttons in copy action area
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
sensitize_copy_action_area(
|
||||
Widget *pushbutton_array)
|
||||
{
|
||||
/* Change icon to "working" */
|
||||
XtVaSetValues (icon,
|
||||
XmNlabelPixmap, pxWorking,
|
||||
XmNmarginLeft, pxWorkingMargin/2,
|
||||
XmNmarginRight, (pxWorkingMargin + 1)/2,
|
||||
NULL);
|
||||
|
||||
/* Desensitize the OK button */
|
||||
XtVaSetValues (pushbutton_array[0],
|
||||
XmNsensitive, FALSE,
|
||||
NULL);
|
||||
|
||||
/* Sensitize the Pause button */
|
||||
XtVaSetValues (pushbutton_array[1],
|
||||
XmNsensitive, TRUE,
|
||||
NULL);
|
||||
|
||||
/* Sensitize the Cancel button */
|
||||
XtVaSetValues (pushbutton_array[2],
|
||||
XmNsensitive, TRUE,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
desensitize_copy_action_area(
|
||||
Widget *pushbutton_array)
|
||||
{
|
||||
/* Change icon to "stopped" */
|
||||
XtVaSetValues (icon,
|
||||
XmNlabelPixmap, pxStopped,
|
||||
XmNmarginLeft, pxStoppedMargin/2,
|
||||
XmNmarginRight, (pxStoppedMargin + 1)/2,
|
||||
NULL);
|
||||
|
||||
/* Sensitize the OK button */
|
||||
XtVaSetValues (pushbutton_array[0],
|
||||
XmNsensitive, TRUE,
|
||||
NULL);
|
||||
|
||||
/* Desensitize the Pause button */
|
||||
XtVaSetValues (pushbutton_array[1],
|
||||
XmNsensitive, FALSE,
|
||||
NULL);
|
||||
|
||||
/* Desensitize the Cancel button */
|
||||
XtVaSetValues (pushbutton_array[2],
|
||||
XmNsensitive, FALSE,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------
|
||||
*
|
||||
* warning_yes_callback and warning_no_callback
|
||||
*
|
||||
* callback for the warning dialog displayed when user selects cancel
|
||||
*
|
||||
*---------------------------------------------------------------------*/
|
||||
|
||||
static void
|
||||
warning_yes_callback(
|
||||
Widget w,
|
||||
XtPointer client_data,
|
||||
XtPointer call_data)
|
||||
{
|
||||
G_do_copy=FALSE;
|
||||
G_wait_on_input = FALSE;
|
||||
if (G_over_dialog != NULL) {
|
||||
G_overwrite_selection = G_SKIP;
|
||||
XtDestroyWidget(G_over_dialog);
|
||||
G_over_dialog = NULL;
|
||||
}
|
||||
if (G_error_dialog != NULL) {
|
||||
XtDestroyWidget(G_error_dialog);
|
||||
G_error_dialog = NULL;
|
||||
}
|
||||
G_dialog_closed = TRUE;
|
||||
G_pause_copy = FALSE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
warning_no_callback(
|
||||
Widget w,
|
||||
XtPointer client_data,
|
||||
XtPointer call_data)
|
||||
{
|
||||
G_pause_copy = G_user_pause_copy;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*-------------------------
|
||||
*
|
||||
* display_cancel_warning
|
||||
*
|
||||
*------------------------*/
|
||||
void
|
||||
display_cancel_warning(Widget parent)
|
||||
|
||||
{
|
||||
XmString msg, dialogTitle, cancelMsg, resumeMsg;
|
||||
int n;
|
||||
Arg args[20];
|
||||
Widget dialog;
|
||||
|
||||
String copyWarnMessage = "This will stop the copy process. Any files that have\n\
|
||||
already been copied will remain in the destination folder.";
|
||||
String moveWarnMessage = "This will stop the move process. Any files that have\n\
|
||||
already been moved will remain in the destination folder.";
|
||||
|
||||
|
||||
|
||||
if (G_move)
|
||||
{
|
||||
dialogTitle = XmStringCreateLocalized (GETMESSAGE(3, 12, "Folder Move - Warning"));
|
||||
msg = XmStringCreateLocalized (GETMESSAGE(3, 10, moveWarnMessage));
|
||||
cancelMsg = XmStringCreateLocalized (GETMESSAGE(3, 15, "Cancel Move"));
|
||||
resumeMsg = XmStringCreateLocalized (GETMESSAGE(3, 16, "Continue Move"));
|
||||
}
|
||||
else
|
||||
{
|
||||
dialogTitle = XmStringCreateLocalized (GETMESSAGE(3, 11, "Folder Copy - Warning"));
|
||||
msg = XmStringCreateLocalized (GETMESSAGE(3, 7, copyWarnMessage));
|
||||
cancelMsg = XmStringCreateLocalized (GETMESSAGE(3, 13, "Cancel Copy"));
|
||||
resumeMsg = XmStringCreateLocalized (GETMESSAGE(3, 14, "Continue Copy"));
|
||||
}
|
||||
|
||||
|
||||
n = 0;
|
||||
XtSetArg(args[n], XmNmessageString, msg); n++;
|
||||
XtSetArg(args[n], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); n++;
|
||||
XtSetArg(args[n], XmNdialogTitle, dialogTitle); n++;
|
||||
dialog = (Widget) XmCreateWarningDialog(parent, "warnDialog", args, n);
|
||||
|
||||
XmStringFree(msg);
|
||||
XmStringFree(dialogTitle);
|
||||
|
||||
n = 0;
|
||||
XtSetArg(args[n], XmNlabelString, cancelMsg); n++;
|
||||
XtSetValues((Widget) XmMessageBoxGetChild(dialog, XmDIALOG_OK_BUTTON), args, n);
|
||||
XmStringFree(cancelMsg);
|
||||
|
||||
n = 0;
|
||||
XtSetArg(args[n], XmNlabelString, resumeMsg); n++;
|
||||
XtSetValues((Widget) XmMessageBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON), args, n);
|
||||
XmStringFree(resumeMsg);
|
||||
|
||||
XtAddCallback((Widget) XmMessageBoxGetChild(dialog, XmDIALOG_OK_BUTTON),
|
||||
XmNactivateCallback,
|
||||
warning_yes_callback,
|
||||
dialog);
|
||||
XtAddCallback((Widget) XmMessageBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON),
|
||||
XmNactivateCallback,
|
||||
warning_no_callback,
|
||||
dialog);
|
||||
XtAddCallback((Widget) XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON),
|
||||
XmNactivateCallback,
|
||||
help_callback,
|
||||
(XtPointer) STOPW_HELP_DIALOG);
|
||||
|
||||
XtManageChild(dialog);
|
||||
|
||||
} /* end display_cancel_warning */
|
||||
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* callbacks
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
static void
|
||||
ok_callback(
|
||||
Widget w,
|
||||
XtPointer client_data,
|
||||
XtPointer call_data)
|
||||
{
|
||||
G_dialog_closed = TRUE;
|
||||
G_do_copy = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
cancel_callback(
|
||||
Widget w,
|
||||
XtPointer client_data,
|
||||
XtPointer call_data)
|
||||
{
|
||||
|
||||
display_cancel_warning(G_copy_dialog);
|
||||
|
||||
G_pause_copy = TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
pause_callback(w, client_data, call_data)
|
||||
Widget w;
|
||||
XtPointer client_data;
|
||||
XtPointer call_data;
|
||||
{
|
||||
XmString xm_string;
|
||||
Pixmap px;
|
||||
int margin;
|
||||
|
||||
G_pause_copy = !G_pause_copy;
|
||||
G_user_pause_copy = !G_user_pause_copy;
|
||||
|
||||
if (G_user_pause_copy)
|
||||
{
|
||||
xm_string = XmStringCreateLocalized(GETMESSAGE(3, 1, "Resume"));
|
||||
px = pxStopped;
|
||||
margin = pxStoppedMargin;
|
||||
}
|
||||
else
|
||||
{
|
||||
xm_string = XmStringCreateLocalized(GETMESSAGE(3, 2, "Pause"));
|
||||
px = pxWorking;
|
||||
margin = pxWorkingMargin;
|
||||
}
|
||||
|
||||
XtVaSetValues(w,
|
||||
XmNlabelString, xm_string,
|
||||
NULL);
|
||||
XtVaSetValues(icon,
|
||||
XmNlabelPixmap, px,
|
||||
XmNmarginLeft, margin/2,
|
||||
XmNmarginRight, (margin + 1)/2,
|
||||
NULL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* create dtcopy dialog
|
||||
* these widgets are not managed until there is an error
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
static Widget
|
||||
create_error_text_window (
|
||||
Widget parent_widget,
|
||||
Widget top_widget,
|
||||
Widget bottom_widget)
|
||||
{
|
||||
Widget scrolled_text;
|
||||
Arg args[15];
|
||||
int n;
|
||||
|
||||
n = 0;
|
||||
|
||||
/* set text to non-editable */
|
||||
XtSetArg(args[n], XmNeditable, FALSE); n ++;
|
||||
XtSetArg(args[n], XmNcursorPositionVisible, FALSE); n ++;
|
||||
XtSetArg(args[n], XmNeditMode, XmMULTI_LINE_EDIT); n++;
|
||||
XtSetArg(args[n], XmNrows, 5); n++;
|
||||
XtSetArg(args[n], XmNscrollVertical, True); n++;
|
||||
XtSetArg(args[n], XmNscrollHorizontal, True); n++;
|
||||
|
||||
/* create the scrolled_text_window */
|
||||
scrolled_text = XmCreateScrolledText(parent_widget,"error_text", args, n);
|
||||
|
||||
/* perform top attachments */
|
||||
XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
|
||||
XtSetArg(args[n], XmNtopWidget,top_widget); n++;
|
||||
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
|
||||
XtSetArg(args[n], XmNleftOffset, INDENTED_SPACING); n++;
|
||||
XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
|
||||
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
|
||||
XtSetArg(args[n], XmNbottomWidget,bottom_widget); n++;
|
||||
XtSetValues(XtParent(scrolled_text), args, n);
|
||||
|
||||
XtUnmanageChild(XtParent(scrolled_text));
|
||||
|
||||
return (scrolled_text);
|
||||
}
|
||||
|
||||
|
||||
Boolean
|
||||
create_copydir_dialog(
|
||||
Widget parent_widget,
|
||||
char *source,
|
||||
char *target)
|
||||
{
|
||||
Arg args[10];
|
||||
int n;
|
||||
XmString xm_string;
|
||||
Widget form, form1, action_area, summary_label, separator2;
|
||||
Widget source_label, source_text_field, target_label, target_text_field;
|
||||
char target_folder[MAX_PATH], target_object[MAX_PATH];
|
||||
|
||||
Pixel background;
|
||||
Pixel foreground;
|
||||
char *ttarget,*tsource;
|
||||
|
||||
Dimension width_target, width_source;
|
||||
|
||||
static ActionAreaItem action_items[] = {
|
||||
{"Ok", 6, 1, ok_callback, NULL},
|
||||
{"Pause", 6, 2, pause_callback, NULL},
|
||||
{"Cancel Copy", 6, 7, cancel_callback, NULL}, /* possibly changed below to Cancel Move*/
|
||||
{"Help", 6, 4, help_callback, (XtPointer) HELP_DIR_COPY},
|
||||
};
|
||||
|
||||
ActionAreaDefn copydirActions = {
|
||||
XtNumber(action_items),
|
||||
0, /* Ok is default action */
|
||||
action_items
|
||||
};
|
||||
|
||||
|
||||
/* Save the name of the source directory in order to truncate the pathname */
|
||||
/* displayed as the copy proceeds ... see function UpdateStatus. */
|
||||
strcpy(G_source_dir,source);
|
||||
|
||||
tsource = (char * )get_path(source);
|
||||
ttarget = (char * )get_path(target);
|
||||
if(Check(tsource,ttarget,G_move))
|
||||
return False;
|
||||
split_path(ttarget,target_folder,target_object);
|
||||
|
||||
if (G_move)
|
||||
{
|
||||
action_items[2].label = "Cancel Move";
|
||||
action_items[2].msg_num = 8;
|
||||
}
|
||||
|
||||
/* create a frame around the dialog for better
|
||||
separation from window border */
|
||||
G_copy_dialog =
|
||||
XtVaCreateWidget("outerFrame",
|
||||
xmFrameWidgetClass,
|
||||
parent_widget,
|
||||
XmNshadowThickness, 3,
|
||||
XmNshadowType, XmSHADOW_ETCHED_IN,
|
||||
NULL);
|
||||
|
||||
/* Create the Manager Widget, form, for the copy dialog */
|
||||
form = XtVaCreateManagedWidget ("dialog_form",
|
||||
xmFormWidgetClass,
|
||||
G_copy_dialog,
|
||||
XmNverticalSpacing, VERTICAL_SPACING,
|
||||
XmNwidth, 500,
|
||||
XmNhorizontalSpacing, HORIZONTAL_SPACING,
|
||||
NULL);
|
||||
|
||||
/* create the toggle button */
|
||||
xm_string = XmStringCreateLocalized(GETMESSAGE(4, 2, "Pause for errors"));
|
||||
G_toggle_main = XtVaCreateManagedWidget("toggle",
|
||||
xmToggleButtonWidgetClass,
|
||||
form,
|
||||
XmNlabelString, xm_string,
|
||||
XmNset, !G_ignore_errors,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNtopOffset, TOP_SPACING,
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
XmNrightOffset, INDENTED_SPACING,
|
||||
XmNalignment, XmALIGNMENT_BEGINNING,
|
||||
NULL);
|
||||
XtAddCallback(G_toggle_main, XmNvalueChangedCallback, toggle_callback, NULL);
|
||||
XmStringFree(xm_string);
|
||||
|
||||
/* Create a form for the working/stopped icon, from/to path names, and summary lines */
|
||||
form1 = XtVaCreateWidget ("msg_form",
|
||||
xmFormWidgetClass,
|
||||
form,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, G_toggle_main,
|
||||
XmNtopOffset, TOP_SPACING,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
NULL);
|
||||
|
||||
/* Create the working/stopped icon */
|
||||
get_icons(form1);
|
||||
|
||||
icon = XtVaCreateManagedWidget("working_icon",
|
||||
xmLabelWidgetClass,
|
||||
form1,
|
||||
XmNlabelType, XmPIXMAP,
|
||||
XmNlabelPixmap, pxWorking,
|
||||
XmNmarginLeft, pxWorkingMargin/2,
|
||||
XmNmarginRight, (pxWorkingMargin + 1)/2,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNbottomAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
NULL);
|
||||
|
||||
/* MJT Get color map from this particular spot in the
|
||||
widget hierarchy. This is being done because of a strange
|
||||
behavior found in the widget hierarchy. The behavior is
|
||||
identified by a change of the background and forground color
|
||||
making children widgets look somewhat odd. It is possible
|
||||
that this is a bug that will be modified in the future.
|
||||
*/
|
||||
XtSetArg (args[0], XmNbackground, &background);
|
||||
XtSetArg (args[1], XmNforeground, &foreground);
|
||||
XtGetValues (form1, args, 2);
|
||||
|
||||
/* Create the Source Directory Widgets */
|
||||
if (G_move)
|
||||
xm_string = XmStringCreateLocalized(GETMESSAGE(3, 3, "Moving:"));
|
||||
else
|
||||
xm_string = XmStringCreateLocalized(GETMESSAGE(3, 4, "Copying:"));
|
||||
source_label =
|
||||
XtVaCreateManagedWidget("source_label",
|
||||
xmLabelWidgetClass,
|
||||
form1,
|
||||
XmNlabelString, xm_string,
|
||||
XmNalignment, XmALIGNMENT_BEGINNING,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_WIDGET,
|
||||
XmNleftWidget, icon,
|
||||
XmNleftOffset, HORIZONTAL_SPACING,
|
||||
NULL);
|
||||
XmStringFree(xm_string);
|
||||
|
||||
xm_string = XmStringCreateLocalized(tsource);
|
||||
|
||||
source_text_field =
|
||||
XtVaCreateManagedWidget("source_text_field",
|
||||
xmLabelWidgetClass,
|
||||
form1,
|
||||
XmNlabelString, xm_string,
|
||||
XmNalignment, XmALIGNMENT_BEGINNING,
|
||||
XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||||
XmNtopWidget, source_label,
|
||||
XmNtopOffset, 0,
|
||||
XmNleftAttachment, XmATTACH_WIDGET,
|
||||
XmNleftWidget, source_label,
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
NULL);
|
||||
XmStringFree(xm_string);
|
||||
|
||||
/* Create the Target Directory Widgets */
|
||||
xm_string = XmStringCreateLocalized(GETMESSAGE(3, 5, "Into folder:"));
|
||||
target_label =
|
||||
XtVaCreateManagedWidget("target_label",
|
||||
xmLabelWidgetClass,
|
||||
form1,
|
||||
XmNlabelString, xm_string,
|
||||
XmNalignment, XmALIGNMENT_BEGINNING,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, source_label,
|
||||
XmNleftAttachment, XmATTACH_WIDGET,
|
||||
XmNleftWidget, icon,
|
||||
XmNleftOffset, HORIZONTAL_SPACING,
|
||||
NULL);
|
||||
XmStringFree(xm_string);
|
||||
|
||||
/* modify width of shorter label so the labels are right-aligned */
|
||||
XtVaGetValues(target_label,
|
||||
XmNwidth, &width_target,
|
||||
NULL);
|
||||
XtVaGetValues(source_label,
|
||||
XmNwidth, &width_source,
|
||||
NULL);
|
||||
|
||||
if (width_target < width_source)
|
||||
{
|
||||
XtVaSetValues(target_label,
|
||||
XmNwidth, width_source,
|
||||
XmNalignment, XmALIGNMENT_END,
|
||||
NULL);
|
||||
}
|
||||
else if (width_target > width_source) /* do nothing if widths are the same */
|
||||
{
|
||||
XtVaSetValues(source_label,
|
||||
XmNwidth, width_target,
|
||||
XmNalignment, XmALIGNMENT_END,
|
||||
NULL);
|
||||
}
|
||||
|
||||
xm_string = XmStringCreateLocalized(target_folder);
|
||||
target_text_field =
|
||||
XtVaCreateManagedWidget("target_text_field",
|
||||
xmLabelWidgetClass,
|
||||
form1,
|
||||
XmNlabelString, xm_string,
|
||||
XmNalignment, XmALIGNMENT_BEGINNING,
|
||||
XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||||
XmNtopWidget, target_label,
|
||||
XmNtopOffset, 0,
|
||||
XmNleftAttachment, XmATTACH_WIDGET,
|
||||
XmNleftWidget, target_label,
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
NULL);
|
||||
|
||||
|
||||
/* create copy-summary text field */
|
||||
if (G_move)
|
||||
xm_string = XmStringCreateLocalized(GETMESSAGE(3, 17, "Moved"));
|
||||
else
|
||||
xm_string = XmStringCreateLocalized(GETMESSAGE(3, 18, "Copied"));
|
||||
|
||||
summary_label =
|
||||
XtVaCreateManagedWidget("target_label",
|
||||
xmLabelWidgetClass,
|
||||
form1,
|
||||
XmNlabelString, xm_string,
|
||||
XmNalignment, XmALIGNMENT_END,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, target_label,
|
||||
XmNtopOffset, TOP_SPACING,
|
||||
XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||||
XmNrightWidget, target_label,
|
||||
XmNrightOffset, 0,
|
||||
XmNleftAttachment, XmATTACH_WIDGET,
|
||||
XmNleftWidget, icon,
|
||||
NULL);
|
||||
XmStringFree(xm_string);
|
||||
|
||||
G_summary_text =
|
||||
XtVaCreateManagedWidget("copy_summary",
|
||||
xmLabelWidgetClass,
|
||||
form1,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, target_label,
|
||||
XmNtopOffset, TOP_SPACING,
|
||||
XmNleftAttachment, XmATTACH_WIDGET,
|
||||
XmNleftWidget, summary_label,
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
XmNalignment, XmALIGNMENT_BEGINNING,
|
||||
NULL);
|
||||
|
||||
|
||||
/* that is all that goes in form1 */
|
||||
XtManageChild(form1);
|
||||
|
||||
/* create the action area of the Copy Directory Dialog */
|
||||
action_area =
|
||||
Create_Action_Area(form, copydirActions, G_copy_action_area_pbuttons);
|
||||
|
||||
/* create the second separator widget */
|
||||
separator2 =
|
||||
XtVaCreateManagedWidget("separator",
|
||||
xmSeparatorWidgetClass,
|
||||
form,
|
||||
XmNbottomAttachment, XmATTACH_WIDGET,
|
||||
XmNbottomWidget, action_area,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
NULL);
|
||||
|
||||
/* create copy-status text field */
|
||||
G_status_text =
|
||||
XtVaCreateManagedWidget("copy_status",
|
||||
xmTextFieldWidgetClass,
|
||||
form,
|
||||
XmNbackground, background,
|
||||
XmNforeground, foreground,
|
||||
/*
|
||||
XmNcolumns, 1,
|
||||
*/
|
||||
XmNresizeWidth, True,
|
||||
XmNshadowThickness, 0,
|
||||
XmNhighlightThickness, 0,
|
||||
XmNtraversalOn, False,
|
||||
XmNeditable, False,
|
||||
XmNcursorPositionVisible, False,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, G_summary_text,
|
||||
XmNtopOffset, TOP_SPACING,
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
XmNrightOffset, INDENTED_SPACING,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
XmNleftOffset, INDENTED_SPACING,
|
||||
XmNbottomAttachment, XmATTACH_WIDGET,
|
||||
XmNbottomWidget, separator2,
|
||||
NULL);
|
||||
|
||||
/* create copy-status text field */
|
||||
/*
|
||||
G_status_text2 =
|
||||
XtVaCreateManagedWidget("copy_status",
|
||||
xmTextFieldWidgetClass,
|
||||
form,
|
||||
XmNbackground, background,
|
||||
XmNforeground, foreground,
|
||||
XmNshadowThickness, 0,
|
||||
XmNhighlightThickness, 0,
|
||||
XmNtraversalOn, False,
|
||||
XmNeditable, False,
|
||||
XmNcursorPositionVisible, False,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, G_summary_text,
|
||||
XmNtopOffset, TOP_SPACING,
|
||||
XmNleftAttachment, XmATTACH_WIDGET,
|
||||
XmNleftWidget, G_status_text,
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
XmNbottomAttachment, XmATTACH_WIDGET,
|
||||
XmNbottomWidget, separator2,
|
||||
NULL);
|
||||
*/
|
||||
|
||||
/* create error-count text field ... not managed until there is an error */
|
||||
G_error_count =
|
||||
XtVaCreateWidget("error_count",
|
||||
xmTextFieldWidgetClass,
|
||||
form,
|
||||
XmNbackground, background,
|
||||
XmNforeground, foreground,
|
||||
XmNshadowThickness, 0,
|
||||
XmNhighlightThickness, 0,
|
||||
XmNtraversalOn, False,
|
||||
XmNeditable, False,
|
||||
XmNcursorPositionVisible, False,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, G_status_text,
|
||||
XmNtopOffset, TOP_SPACING,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
NULL);
|
||||
|
||||
/* create error-message scroll window ... not managed until there is an error */
|
||||
G_error_msgs = create_error_text_window (form,
|
||||
G_error_count,
|
||||
separator2);
|
||||
|
||||
/* set initial keyboard focus to the action button area */
|
||||
XtSetArg (args[0], XmNinitialFocus, action_area);
|
||||
XtSetValues(form, args, 1);
|
||||
|
||||
/* Manage the Copy Directory Dialog */
|
||||
XtManageChild(G_copy_dialog);
|
||||
|
||||
free(ttarget);
|
||||
free(tsource);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
966
cde/programs/dtfile/dtcopy/dosync.c
Normal file
966
cde/programs/dtfile/dtcopy/dosync.c
Normal file
@@ -0,0 +1,966 @@
|
||||
/* $TOG: dosync.c /main/6 1998/10/26 12:40:53 mgreess $ */
|
||||
/************************************<+>*************************************
|
||||
****************************************************************************
|
||||
*
|
||||
* FILE: dosync.c
|
||||
*
|
||||
*
|
||||
* DESCRIPTION: Routines synchronizing directories
|
||||
*
|
||||
* FUNCTIONS: CONFIRM
|
||||
* CmpPred
|
||||
* DTYPE
|
||||
* DirCmp
|
||||
* DirCmp2
|
||||
* DumpDir
|
||||
* ERROR_CHECK
|
||||
* FreeDir
|
||||
* GetDir
|
||||
* GetDirEntry
|
||||
* SortDir
|
||||
* SyncDirRecur
|
||||
* SyncDirectory
|
||||
* SyncItem
|
||||
* cmpSymlink
|
||||
* dirEraseCallback
|
||||
* dirErrorCallback
|
||||
* doCopy
|
||||
* doCopyLink
|
||||
* doMkdir
|
||||
* doSymlink
|
||||
* doUnlink
|
||||
* targetLink
|
||||
*
|
||||
* (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
|
||||
* (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
|
||||
* (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
|
||||
* (c) Copyright 1993, 1994, 1995 Novell, Inc.
|
||||
*
|
||||
****************************************************************************
|
||||
************************************<+>*************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/time.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/file.h>
|
||||
#include "fsrtns.h"
|
||||
#ifdef PATRTNS
|
||||
#include "patrtns.h"
|
||||
#endif
|
||||
#include "dosync.h"
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* global variables
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
char *FileOpNames[] = {
|
||||
"synchronize",
|
||||
"opendir",
|
||||
"lstat",
|
||||
"stat",
|
||||
"readlink",
|
||||
"delete",
|
||||
"copy",
|
||||
"mkdir",
|
||||
"copy link",
|
||||
"make link",
|
||||
"working",
|
||||
"is a copy",
|
||||
"is a link"
|
||||
};
|
||||
|
||||
|
||||
int (*syncConfirmCallback)(FileOp op,
|
||||
char *sname, int stype,
|
||||
char *tname, int ttype,
|
||||
char *link) = NULL;
|
||||
int (*syncErrorCallback)(FileOp op, char *fname, int errnum) = NULL;
|
||||
|
||||
|
||||
static SyncParams *SP;
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* macros for invoking callback functions
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
#define DTYPE(delP) ((delP)? (delP)->ftype: ft_noent)
|
||||
|
||||
#define CONFIRM(op, sn, st, tn, tt, l, rc) \
|
||||
if (periodicCallback && (*periodicCallback)() != 0) return -1; \
|
||||
else if (syncConfirmCallback && \
|
||||
(rc = syncConfirmCallback(op, sn, st, tn, tt, l)) != 0) return rc; else
|
||||
|
||||
#define ERROR_CHECK(op, f, rc) \
|
||||
if (rc < 0 || rc && syncErrorCallback && syncErrorCallback(op, f, rc) < 0) \
|
||||
return -1; else
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* reading directories
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
/* structure containing information anout a directory entry */
|
||||
typedef struct de {
|
||||
char name[256]; /* file name */
|
||||
int rc, lrc; /* return codes from stat, lstat */
|
||||
struct stat stat; /* stat */
|
||||
int ftype; /* file type flags (see #defines in dosync.h) */
|
||||
char exclude, skip; /* exclude, skip flags */
|
||||
char *link; /* value of symbolic link */
|
||||
struct de *teP; /* source dir: points to correspond. target dir entry */
|
||||
struct de *next; /* next directory entry */
|
||||
} DirEntry;
|
||||
|
||||
|
||||
/*
|
||||
* DumpDir: dump linked list of directory entries to stdout (debugging only)
|
||||
*/
|
||||
static void
|
||||
DumpDir(DirEntry *dP)
|
||||
{
|
||||
DirEntry *eP;
|
||||
|
||||
for (eP = dP; eP; eP = eP->next)
|
||||
printf(" %-15s %2d %c %c %c %c %c %s\n",
|
||||
eP->name,
|
||||
eP->rc,
|
||||
(eP->ftype & ft_isdir)? 'D': ' ',
|
||||
(eP->ftype & ft_islnk)? 'L': ' ',
|
||||
eP->exclude? 'X': ' ',
|
||||
eP->skip? 'S': ' ',
|
||||
eP->teP? 'F': ' ',
|
||||
eP->link? eP->link: "");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* DirCmp: compare function for sorting directory entries
|
||||
*/
|
||||
static int
|
||||
DirCmp(const void *p1, const void *p2)
|
||||
{
|
||||
return strcmp((*(DirEntry **)p1)->name, (*(DirEntry **)p2)->name);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* SortDir: sort linked list of directory entries by name
|
||||
*/
|
||||
static DirEntry *
|
||||
SortDir(DirEntry *dP, int (*cmp)(const void*, const void*))
|
||||
{
|
||||
int i, n;
|
||||
DirEntry *eP, **linkPP;
|
||||
DirEntry *da[1024], **daP;
|
||||
|
||||
/* count number of directory entries */
|
||||
n = 0;
|
||||
for (eP = dP; eP; eP = eP->next)
|
||||
n++;
|
||||
if (n < 2)
|
||||
return dP;
|
||||
|
||||
/* allocate pointer array */
|
||||
if (n <= 1024)
|
||||
daP = da;
|
||||
else
|
||||
daP = (DirEntry **)malloc(n * sizeof(DirEntry *));
|
||||
|
||||
/* sort pointer array */
|
||||
for (eP = dP, i = 0; eP; eP = eP->next, i++)
|
||||
daP[i] = eP;
|
||||
qsort(daP, n, sizeof(DirEntry *), cmp);
|
||||
|
||||
/* re-link the linked list */
|
||||
linkPP = &dP;
|
||||
for (i = 0; i < n; i++) {
|
||||
*linkPP = daP[i];
|
||||
linkPP = &(*linkPP)->next;
|
||||
}
|
||||
*linkPP = NULL;
|
||||
|
||||
/* free pointer array */
|
||||
if (daP != da)
|
||||
free(daP);
|
||||
|
||||
return dP;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* FreeDir: de-allocate linked list of directory entries
|
||||
*/
|
||||
static void
|
||||
FreeDir(DirEntry *deP)
|
||||
{
|
||||
DirEntry *nextP;
|
||||
|
||||
while (deP) {
|
||||
nextP = deP->next;
|
||||
free(deP);
|
||||
deP = nextP;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* GetDirEntry: Get information about one directory entry.
|
||||
* If an error occurs, returns the errno in *rc and the operation
|
||||
* that failed (op_lstat, op_stat, or op_readlink) in *op.
|
||||
*/
|
||||
static DirEntry *
|
||||
GetDirEntry(char *fname, FileOp *op, int *rc)
|
||||
{
|
||||
DirEntry *deP;
|
||||
char *p;
|
||||
char link[1024];
|
||||
int l;
|
||||
|
||||
/* allocate new DirEntry */
|
||||
deP = (DirEntry *)malloc(sizeof(DirEntry));
|
||||
memset(deP, 0, sizeof(DirEntry));
|
||||
|
||||
/* get file name */
|
||||
p = strrchr(fname, '/');
|
||||
if (p && p > fname)
|
||||
strcpy(deP->name, p + 1);
|
||||
else
|
||||
strcpy(deP->name, fname);
|
||||
|
||||
/* assume everything is fine */
|
||||
*op = 0;
|
||||
*rc = 0;
|
||||
|
||||
/* get information */
|
||||
deP->rc = lstat(fname, &deP->stat);
|
||||
if (deP->rc) {
|
||||
*op = op_lstat;
|
||||
*rc = errno;
|
||||
} else if ((deP->stat.st_mode & S_IFMT) == S_IFDIR)
|
||||
deP->ftype |= ft_isdir;
|
||||
else if ((deP->stat.st_mode & S_IFMT) == S_IFLNK) {
|
||||
deP->ftype |= ft_islnk;
|
||||
deP->lrc = stat(fname, &deP->stat);
|
||||
if (deP->lrc) {
|
||||
if (errno != ENOENT) {
|
||||
*op = op_stat;
|
||||
*rc = errno;
|
||||
}
|
||||
} else if ((deP->stat.st_mode & S_IFMT) == S_IFDIR)
|
||||
deP->ftype |= ft_isdir;
|
||||
l = readlink(fname, link, sizeof(link) - 1);
|
||||
if (l < 0) {
|
||||
*op = op_readlink;
|
||||
*rc = errno;
|
||||
} else {
|
||||
link[l] = 0;
|
||||
deP->link = strdup(link);
|
||||
}
|
||||
}
|
||||
|
||||
return deP;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* GetDir: read a directory and return linked list of directory entries
|
||||
*/
|
||||
static int
|
||||
GetDir(char *dirname, PatternList *xl, PatternList *sl, DirEntry **listPP)
|
||||
{
|
||||
DIR *dirP; /* open directory */
|
||||
struct dirent *entryP; /* directory entry */
|
||||
DirEntry *deP, *firstP, **linkPP;
|
||||
char fname[1024], *fnP;
|
||||
PatternList *pl;
|
||||
FileOp op;
|
||||
int rc;
|
||||
|
||||
|
||||
/* open directory */
|
||||
dirP = opendir(dirname);
|
||||
if (dirP == NULL) {
|
||||
rc = errno;
|
||||
if (syncErrorCallback &&
|
||||
syncErrorCallback(op_opendir, dirname, rc) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* copy dirname to file name buffer */
|
||||
strcpy(fname, dirname);
|
||||
fnP = fname + strlen(fname);
|
||||
*fnP++ = '/';
|
||||
|
||||
/* initialize linked list */
|
||||
firstP = NULL;
|
||||
linkPP = &firstP;
|
||||
|
||||
/* read the directory */
|
||||
while ((entryP = readdir(dirP)) != NULL) {
|
||||
/* skip . and .. */
|
||||
if (strcmp(entryP->d_name, ".") == 0 || strcmp(entryP->d_name, "..") == 0)
|
||||
continue;
|
||||
|
||||
/* get new DirEntry */
|
||||
strcpy(fnP, entryP->d_name);
|
||||
deP = GetDirEntry(fname, &op, &rc);
|
||||
|
||||
/* add to linked list */
|
||||
*linkPP = deP;
|
||||
linkPP = &deP->next;
|
||||
|
||||
/* if error occurred, call error callback function */
|
||||
if (rc != 0 && syncErrorCallback && syncErrorCallback(op, fname, rc) < 0) {
|
||||
FreeDir(firstP);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* check exclude and skip list */
|
||||
#ifdef PATRTNS
|
||||
for (pl = xl ; pl; pl = pl->next)
|
||||
if (MatchPattern(pl->pattern, fname))
|
||||
deP->exclude++;
|
||||
|
||||
for (pl = sl; pl; pl = pl->next)
|
||||
if (MatchPattern(pl->pattern, fname))
|
||||
deP->skip++;
|
||||
#endif
|
||||
}
|
||||
|
||||
closedir(dirP);
|
||||
*listPP = SortDir(firstP, DirCmp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* file operations
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
static int erase_rc;
|
||||
|
||||
/*
|
||||
* dirEraseCallback: used in doUnlink (below) for confirmation
|
||||
* during recursive directory deletes
|
||||
*/
|
||||
static int
|
||||
dirEraseCallback(char *fname)
|
||||
{
|
||||
erase_rc = syncConfirmCallback(op_delete, "", ft_noent, fname, 0, "");
|
||||
return erase_rc;
|
||||
}
|
||||
|
||||
static int
|
||||
dirErrorCallback(char *fname, int errnum)
|
||||
{
|
||||
erase_rc = syncErrorCallback(op_delete, fname, errnum);
|
||||
return erase_rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* doUnlink: delete a file from the target directory
|
||||
*/
|
||||
static int
|
||||
doUnlink(char *fname, DirEntry *fP, int confirm)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (confirm)
|
||||
CONFIRM(op_delete, "", ft_noent, fname, fP->ftype, "", rc);
|
||||
|
||||
if (SP->dontdoit)
|
||||
rc = 0;
|
||||
|
||||
else if (SP->keepold) {
|
||||
char newname[1024];
|
||||
|
||||
strcpy(newname, fname);
|
||||
strcat(newname, SP->keepold);
|
||||
fsMove(fname, newname, 1, &rc);
|
||||
|
||||
} else if ((fP->ftype & ft_isdir) && !(fP->ftype & ft_islnk)) {
|
||||
/* arrange for syncConfirmCallback's during recursive directory deletes */
|
||||
erase_rc = 0;
|
||||
if (syncErrorCallback)
|
||||
errorCallback = dirErrorCallback;
|
||||
if (syncConfirmCallback)
|
||||
progressCallback = dirEraseCallback;
|
||||
|
||||
fsErase(fname, &rc, 1);
|
||||
if (rc < 0 && erase_rc)
|
||||
rc = ENOTEMPTY;
|
||||
|
||||
errorCallback = NULL;
|
||||
progressCallback = NULL;
|
||||
|
||||
} else
|
||||
rc = (unlink(fname) != 0)? errno: 0;
|
||||
|
||||
/* check for errors */
|
||||
ERROR_CHECK(op_delete, fname, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* doCopy: copy a file from the source to target directory
|
||||
*/
|
||||
static int
|
||||
doCopy(char *sname, DirEntry *sP, char *tname, DirEntry *delP)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* display message */
|
||||
CONFIRM(op_copy, sname, sP->ftype, tname, DTYPE(delP), "", rc);
|
||||
|
||||
/* if necessary, delete target */
|
||||
if (delP && !SP->dontdoit)
|
||||
if ((rc = doUnlink(tname, delP, 0)) != 0)
|
||||
return rc;
|
||||
|
||||
/* copy the file */
|
||||
if (SP->dontdoit)
|
||||
rc = 0;
|
||||
else
|
||||
fsCopy(sname, tname, 0, &rc);
|
||||
|
||||
/* check for errors */
|
||||
ERROR_CHECK(op_copy, sname, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* doMkdir: create a new sub directory in the target directory
|
||||
*/
|
||||
static int
|
||||
doMkdir(char *sname, DirEntry *sP, char *tname, DirEntry *delP)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* display message */
|
||||
CONFIRM(op_mkdir, sname, sP->ftype, tname, DTYPE(delP), "", rc);
|
||||
|
||||
/* if necessary, delete target */
|
||||
if (delP && !SP->dontdoit)
|
||||
if ((rc = doUnlink(tname, delP, 0)) != 0)
|
||||
return rc;
|
||||
|
||||
/* make a new directory */
|
||||
rc = SP->dontdoit? 0: (mkdir(tname, sP->stat.st_mode & 07777) < 0)? errno: 0;
|
||||
|
||||
/* check for errors */
|
||||
ERROR_CHECK(op_mkdir, tname, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* targetLink: lookup symbloc link in the maplink list
|
||||
*/
|
||||
static void
|
||||
targetLink(char *source, char *target, char **tlPP, char **msgPP)
|
||||
/*
|
||||
*
|
||||
*/
|
||||
{
|
||||
static char buf[1024] = " -> ";
|
||||
MapList *ml;
|
||||
int l;
|
||||
|
||||
for (ml = SP->maplink; ml; ml = ml->next) {
|
||||
l = strlen(ml->from);
|
||||
if (strncmp(ml->from, source, l) == 0
|
||||
&& (source[l] == '/' || source[l] == 0))
|
||||
{
|
||||
strcpy(buf + 4, ml->to);
|
||||
if (source[l])
|
||||
strcat(buf, source +l);
|
||||
if (strcmp(buf + 4, target) != 0) {
|
||||
*tlPP = buf + 4;
|
||||
*msgPP = buf;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*tlPP = source;
|
||||
*msgPP = "";
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* doCopyLink: copy a symbolic link from the source to target directory
|
||||
*/
|
||||
static int
|
||||
doCopyLink(char *sname, DirEntry *sP, char *tname, DirEntry *delP)
|
||||
{
|
||||
char *tl, *msg;
|
||||
int rc;
|
||||
|
||||
/* determine where the link should point */
|
||||
targetLink(sP->link, tname, &tl, &msg);
|
||||
|
||||
/* display message */
|
||||
CONFIRM(op_cplink, sname, sP->ftype, tname, DTYPE(delP), msg, rc);
|
||||
|
||||
/* if necessary, delete target */
|
||||
if (delP && !SP->dontdoit)
|
||||
if ((rc = doUnlink(tname, delP, 0)) != 0)
|
||||
return rc;
|
||||
|
||||
/* create link */
|
||||
rc = SP->dontdoit? 0: (symlink(tl, tname) != 0)? errno: 0;
|
||||
|
||||
/* check for errors */
|
||||
ERROR_CHECK(op_cplink, tname, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* doSymlink: create a symbolic link in the target directory to a file
|
||||
* in the source directory
|
||||
*/
|
||||
static int
|
||||
doSymlink(char *sname, DirEntry *sP, char *tname, DirEntry *delP)
|
||||
{
|
||||
char *tl, *msg;
|
||||
int rc;
|
||||
|
||||
/* determine where the link should point */
|
||||
targetLink(sname, tname, &tl, &msg);
|
||||
|
||||
/* display message */
|
||||
CONFIRM(op_mklink, sname, sP->ftype, tname, DTYPE(delP), msg, rc);
|
||||
|
||||
/* if necessary, delete target */
|
||||
if (delP && !SP->dontdoit)
|
||||
if ((rc = doUnlink(tname, delP, 0)) != 0)
|
||||
return rc;
|
||||
|
||||
/* create link */
|
||||
targetLink(sname, tname, &tl, &msg);
|
||||
rc = SP->dontdoit? 0: (symlink(tl, tname) != 0)? errno: 0;
|
||||
|
||||
/* check for errors */
|
||||
ERROR_CHECK(op_mklink, sname, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* cmpSymlink: compare two symbolic links
|
||||
* return values:
|
||||
* -1 error reading one of the links
|
||||
* 0 links point to the same file
|
||||
* 1 tname link points to sname
|
||||
* 2 links point to different files
|
||||
*/
|
||||
static int
|
||||
cmpSymlink(char *sname, DirEntry *seP, char *tname, DirEntry *teP)
|
||||
{
|
||||
char *tl, *msg;
|
||||
|
||||
/* return error if target link could not be read */
|
||||
if (!teP->link)
|
||||
return -1;
|
||||
|
||||
/* check if target link points to source link */
|
||||
if (SP->keeplinks) {
|
||||
targetLink(sname, tname, &tl, &msg);
|
||||
if (strcmp(teP->link, tl) == 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* if source not a symbolic link, target must be pointing to wrong file */
|
||||
if (!(seP->ftype & ft_islnk))
|
||||
return 2;
|
||||
|
||||
/* compare the links */
|
||||
targetLink(seP->link, tname, &tl, &msg);
|
||||
if (strcmp(teP->link, tl) == 0)
|
||||
return 0;
|
||||
else
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* sync directories
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
static int SyncDirRecur(char *sdir, char *tdir);
|
||||
|
||||
|
||||
/*
|
||||
* SyncItem: copy or replace one item from the source to the target directory
|
||||
*/
|
||||
static int
|
||||
SyncItem(char *sname, DirEntry *sP, char *tname, DirEntry *tP)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (periodicCallback && (*periodicCallback)() != 0)
|
||||
return -1;
|
||||
|
||||
if (!tP) {
|
||||
/* target does not exist */
|
||||
|
||||
rpl_target:
|
||||
/*--------------------------------------------------------------------
|
||||
* target does not exist or should be replaced
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
/* check if -dontreplace or -dontadd options apply */
|
||||
if (tP && SP->dontreplace || !tP && SP->dontadd)
|
||||
return 0;
|
||||
|
||||
if (sP->ftype & ft_islnk) {
|
||||
/* source is a link */
|
||||
|
||||
if ((sP->ftype & ft_isdir) && !SP->copydirs ||
|
||||
!(sP->ftype & ft_isdir) && !SP->copyfiles)
|
||||
{
|
||||
/* just copy the link */
|
||||
return doCopyLink(sname, sP, tname, tP);
|
||||
}
|
||||
|
||||
} else {
|
||||
/* source is not a link */
|
||||
|
||||
if ((sP->ftype & ft_isdir) && SP->linkdirs ||
|
||||
!(sP->ftype & ft_isdir) && SP->linkfiles)
|
||||
{
|
||||
/* don't copy; just create a link to the target */
|
||||
return doSymlink(sname, sP, tname, tP);
|
||||
}
|
||||
}
|
||||
|
||||
if (sP->ftype & ft_isdir) {
|
||||
/* source is a dir: create target directory and do recursive sync */
|
||||
rc = doMkdir(sname, sP, tname, tP);
|
||||
if (rc || SP->dontdoit)
|
||||
return rc;
|
||||
else
|
||||
return SyncDirRecur(sname, tname);
|
||||
|
||||
} else
|
||||
/* source is a regular file: copy the file */
|
||||
return doCopy(sname, sP, tname, tP);
|
||||
|
||||
|
||||
} else if (tP->ftype & ft_islnk) {
|
||||
/*--------------------------------------------------------------------
|
||||
* target is a symbolic link
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
if ((tP->ftype & ft_isdir) == (sP->ftype & ft_isdir)) {
|
||||
/*
|
||||
* target points to the right type of object (dir vs regular file):
|
||||
* check if target points to the right place
|
||||
*/
|
||||
rc = cmpSymlink(sname, sP, tname, tP);
|
||||
if (rc < 0)
|
||||
return 1; /* something is wrong */
|
||||
|
||||
if (SP->listlinks && rc == 1)
|
||||
CONFIRM(op_info_link, sname, sP->ftype, tname, tP->ftype, "", rc);
|
||||
|
||||
if (rc < 2)
|
||||
/* target is pointing to the right place */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* target points to the wrong type of object:
|
||||
* delete target link and try again
|
||||
*/
|
||||
goto rpl_target;
|
||||
|
||||
|
||||
} else if (!(tP->ftype & ft_isdir)) {
|
||||
/*--------------------------------------------------------------------
|
||||
* target is regular file
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
if (sP->ftype & ft_isdir)
|
||||
/* source is a dir: delete target file and try again */
|
||||
goto rpl_target;
|
||||
|
||||
else {
|
||||
/* source is regular file or link to regular file */
|
||||
|
||||
if (sP->ftype & ft_islnk) {
|
||||
/* source is just a link */
|
||||
|
||||
if (!SP->keepcopies && !SP->copyfiles)
|
||||
/* replace target by a link */
|
||||
goto rpl_target;
|
||||
|
||||
else if (SP->listcopies)
|
||||
CONFIRM(op_info_copy, sname, sP->ftype, tname, tP->ftype, "", rc);
|
||||
}
|
||||
|
||||
if (!SP->forcecopies &&
|
||||
tP->stat.st_mtime == sP->stat.st_mtime &&
|
||||
tP->stat.st_size == sP->stat.st_size)
|
||||
{
|
||||
/* we assume the file hasn't changed: don't do anything */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (SP->keepnew && tP->stat.st_mtime > sP->stat.st_mtime)
|
||||
/* we should keep the target because it is newer than the source */
|
||||
return 0;
|
||||
|
||||
/* replace the target file */
|
||||
goto rpl_target;
|
||||
}
|
||||
|
||||
|
||||
} else if (!(tP->ftype & ft_islnk)) {
|
||||
/*--------------------------------------------------------------------
|
||||
* target is a directory
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
if (sP->ftype & ft_isdir) {
|
||||
if (sP->ftype & ft_islnk) {
|
||||
/* source is just a link */
|
||||
|
||||
if (!SP->keepcopies && !SP->copydirs)
|
||||
/* replace target by a link */
|
||||
goto rpl_target;
|
||||
|
||||
else if (SP->listcopies)
|
||||
CONFIRM(op_info_copy, sname, sP->ftype, tname, tP->ftype, "", rc);
|
||||
}
|
||||
|
||||
/* source is dir: recursively sync source and target dirs */
|
||||
return SyncDirRecur(sname, tname);
|
||||
|
||||
} else
|
||||
/* source is no dir: delete target dir and try again */
|
||||
goto rpl_target;
|
||||
}
|
||||
|
||||
/* should never be reached */
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* CmpPred: returns a precedence number that is used to determine in which
|
||||
* order source directory entries are processed:
|
||||
* 1 source is regular file
|
||||
* 2 source is symbolic link
|
||||
* 3 target is not a real directory
|
||||
* 4 target exists and is a real directory (not a sym link)
|
||||
*/
|
||||
static int
|
||||
CmpPred(DirEntry *dP)
|
||||
{
|
||||
if (!(dP->ftype & ft_isdir))
|
||||
return 1;
|
||||
|
||||
else if (dP->ftype & ft_islnk)
|
||||
return 2;
|
||||
|
||||
else if (!dP->teP ||
|
||||
!(dP->teP->ftype & ft_isdir) ||
|
||||
(dP->teP->ftype & ft_islnk))
|
||||
{
|
||||
return 3;
|
||||
|
||||
} else
|
||||
return 4;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* DirCmp2: compare function for sorting directory entries
|
||||
*/
|
||||
static int
|
||||
DirCmp2(const void *p1, const void *p2)
|
||||
{
|
||||
int d = CmpPred(*(DirEntry **)p1) - CmpPred(*(DirEntry **)p2);
|
||||
if (d)
|
||||
return d;
|
||||
else
|
||||
return strcmp((*(DirEntry **)p1)->name, (*(DirEntry **)p2)->name);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* SyncDirRecur: recursively synchronize source and target directories
|
||||
*/
|
||||
static int
|
||||
SyncDirRecur(char *sdir, char *tdir)
|
||||
{
|
||||
DirEntry *sP, *tP, *seP, *teP;
|
||||
char *fsP, *ftP;
|
||||
int rc;
|
||||
|
||||
/* informational callback */
|
||||
if (SP->verbose)
|
||||
CONFIRM(op_sync, sdir, ft_isdir, tdir, ft_isdir, "", rc);
|
||||
|
||||
/* read source and target directories */
|
||||
if ((rc = GetDir(sdir, SP->exclude, SP->skip, &sP)) != 0)
|
||||
return rc;
|
||||
if ((rc = GetDir(tdir, NULL, SP->skip, &tP)) != 0) {
|
||||
FreeDir(sP);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* append "/" to source and target directory names */
|
||||
fsP = sdir + strlen(sdir);
|
||||
ftP = tdir + strlen(tdir);
|
||||
*fsP++ = '/';
|
||||
*ftP++ = '/';
|
||||
|
||||
/* first delete files in target dir that don't exist in source dir */
|
||||
seP = sP;
|
||||
teP = tP;
|
||||
while (teP) {
|
||||
/* compare directory entries */
|
||||
rc = (seP != NULL)? strcmp(seP->name, teP->name): 1;
|
||||
|
||||
if ((seP != NULL) && seP->exclude) {
|
||||
/* skip excluded files */
|
||||
seP = seP->next;
|
||||
|
||||
} else if (rc == 0) {
|
||||
/* file exists in both directories */
|
||||
seP->teP = teP;
|
||||
seP = seP->next;
|
||||
teP = teP->next;
|
||||
|
||||
} else if (rc < 0) {
|
||||
/* source file not in target directory */
|
||||
seP = seP->next;
|
||||
|
||||
} else { /* rc > 0 */
|
||||
/* target file not in source directory */
|
||||
if (!SP->dontdelete && !teP->skip) {
|
||||
strcpy(ftP, teP->name);
|
||||
if (doUnlink(tdir, teP, 1) < 0) {
|
||||
FreeDir(sP);
|
||||
FreeDir(tP);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
teP = teP->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* re-sort source dir so that regular files are processed before sub dirs */
|
||||
sP = SortDir(sP, DirCmp2);
|
||||
|
||||
/* process all entires found in the source directory */
|
||||
for (seP = sP, rc = 0; seP && rc >= 0; seP = seP->next) {
|
||||
/* skip error entries */
|
||||
if (seP->rc)
|
||||
continue;
|
||||
|
||||
/* skip excluded and to-be-skipped files */
|
||||
if (seP->exclude || seP->skip)
|
||||
continue;
|
||||
|
||||
/* also skip sub directories if "don't recur" option is set */
|
||||
if (SP->dontrecur && (seP->ftype & ft_isdir))
|
||||
continue;
|
||||
|
||||
/* construct source and target file names */
|
||||
strcpy(fsP, seP->name);
|
||||
strcpy(ftP, seP->name);
|
||||
|
||||
/* sync directory item */
|
||||
rc = SyncItem(sdir, seP, tdir, seP->teP);
|
||||
}
|
||||
|
||||
/* free directory lists */
|
||||
FreeDir(sP);
|
||||
FreeDir(tP);
|
||||
|
||||
return (rc < 0)? -1: 0;
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* external entry point
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
SyncDirectory(SyncParams *p)
|
||||
{
|
||||
char sbuf[1024], tbuf[1024];
|
||||
DirEntry *sP, *tP;
|
||||
FileOp op;
|
||||
int rc;
|
||||
|
||||
/* the lower-level error and progress callbacks are not used */
|
||||
errorCallback = NULL;
|
||||
progressCallback = NULL;
|
||||
|
||||
/* save pointer to params; copy source & target names */
|
||||
SP = p;
|
||||
strcpy(sbuf, SP->source);
|
||||
strcpy(tbuf, SP->target);
|
||||
|
||||
/* get info about the source */
|
||||
sP = GetDirEntry(sbuf, &op, &rc);
|
||||
if (rc) {
|
||||
if (syncErrorCallback)
|
||||
syncErrorCallback(op, sbuf, rc);
|
||||
FreeDir(sP);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* The "copytop" option means: if the top-level source is a symbolic
|
||||
* make a copy of the real thing. To get this behavior we just switch
|
||||
* off the ft_islnk flag on the source.
|
||||
*/
|
||||
if (SP->copytop)
|
||||
sP->ftype &= ~ft_islnk;
|
||||
|
||||
/* get info about the target */
|
||||
tP = GetDirEntry(tbuf, &op, &rc);
|
||||
if (rc) {
|
||||
if (op == op_lstat && rc == ENOENT) {
|
||||
/* target does not yet exist; that's ok */
|
||||
FreeDir(tP);
|
||||
tP = NULL;
|
||||
|
||||
} else {
|
||||
/* we'll try to procede anyway ... unless the error callback says no */
|
||||
if (syncErrorCallback && syncErrorCallback(op, tbuf, rc) < 0) {
|
||||
FreeDir(sP);
|
||||
FreeDir(tP);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* now do the real work */
|
||||
SyncItem(sbuf, sP, tbuf, tP);
|
||||
|
||||
/* free storage and return */
|
||||
FreeDir(sP);
|
||||
FreeDir(tP);
|
||||
}
|
||||
|
||||
104
cde/programs/dtfile/dtcopy/dosync.h
Normal file
104
cde/programs/dtfile/dtcopy/dosync.h
Normal file
@@ -0,0 +1,104 @@
|
||||
/* $XConsortium: dosync.h /main/5 1995/11/30 13:48:34 rswiston $ */
|
||||
/************************************<+>*************************************
|
||||
****************************************************************************
|
||||
*
|
||||
* FILE: dosync.h
|
||||
*
|
||||
*
|
||||
* DESCRIPTION: Header file for dosync.c, main_dtcopy.c
|
||||
*
|
||||
* (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
|
||||
* (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
|
||||
* (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
|
||||
* (c) Copyright 1993, 1994, 1995 Novell, Inc.
|
||||
*
|
||||
****************************************************************************
|
||||
************************************<+>*************************************/
|
||||
|
||||
#ifndef _dosync_h
|
||||
#define _dosync_h
|
||||
|
||||
/* file type flags used in syncConfirmCallback */
|
||||
#define ft_noent 0x01 /* file does not exist */
|
||||
#define ft_isdir 0x02 /* file is a directory */
|
||||
#define ft_islnk 0x04 /* file is a symbolic link */
|
||||
|
||||
/* file operations used in syncConfirmCallback and syncErrorCallback */
|
||||
typedef enum {
|
||||
op_sync, /* beginning directory sync */
|
||||
op_opendir, /* opendir */
|
||||
op_lstat, /* lstat */
|
||||
op_stat, /* stat */
|
||||
op_readlink, /* readlink */
|
||||
op_delete, /* deleting file in target dir */
|
||||
op_copy, /* copy/replace file in target dir */
|
||||
op_mkdir, /* create new sub directory */
|
||||
op_cplink, /* copy/replace symbolic link in target dir */
|
||||
op_mklink, /* create link to source file/dir in target dir */
|
||||
op_info_working,/* informational: still working on the current operation */
|
||||
op_info_copy, /* informational: target is real copy of source */
|
||||
op_info_link, /* informational: target is only sym link to source */
|
||||
op_rename /* used in main_dtcopy.c to report an error */
|
||||
} FileOp;
|
||||
|
||||
/* array of strings naming the file operaions */
|
||||
extern char *FileOpNames[];
|
||||
|
||||
/* Callback functions */
|
||||
extern int (*syncConfirmCallback)(FileOp op,
|
||||
char *sname, int stype,
|
||||
char *tname, int ttype,
|
||||
char *link);
|
||||
extern int (*syncErrorCallback)(FileOp op, char *fname, int errnum);
|
||||
|
||||
/* info for mapping symbolic links (-ml option) */
|
||||
typedef struct ml {
|
||||
char *from;
|
||||
char *to;
|
||||
struct ml *next;
|
||||
} MapList;
|
||||
|
||||
|
||||
/* list of file name patterns for -exclude and -skip */
|
||||
typedef struct pl {
|
||||
char *pattern;
|
||||
struct pl *next;
|
||||
} PatternList;
|
||||
|
||||
|
||||
/* parameters for syncdir function */
|
||||
typedef struct {
|
||||
char *source; /* source directory */
|
||||
char *target; /* target directory */
|
||||
|
||||
int verbose; /* verbose output */
|
||||
int quiet; /* quiet output */
|
||||
int dontdoit; /* only print what would be done */
|
||||
|
||||
int keepnew; /* keep target files that are newer than the source */
|
||||
char *keepold; /* save target files that would be deleted/replaced */
|
||||
int dontdelete; /* don't delete any files that no longer exist */
|
||||
int dontadd; /* don't create new files */
|
||||
int dontreplace; /* don't replace existing files */
|
||||
int dontrecur; /* don't go into subdirectories */
|
||||
|
||||
MapList *maplink;
|
||||
int keeplinks; /* keep links that point to source file */
|
||||
int keepcopies; /* keep copies of files that are links in source */
|
||||
int forcecopies; /* copy files even if unmodified */
|
||||
int listlinks; /* list links that point to source file */
|
||||
int listcopies; /* list copies of links */
|
||||
int linkdirs; /* when new dir is found, just create a link to it */
|
||||
int linkfiles; /* when new file is found, just create a link to it */
|
||||
int copydirs; /* when link to dir is found, copy it */
|
||||
int copyfiles; /* when link to file is found, copy it */
|
||||
int copytop; /* if top-level is link, copy it */
|
||||
|
||||
PatternList *exclude; /* source files to be excluded */
|
||||
PatternList *skip; /* files to be skipped */
|
||||
} SyncParams;
|
||||
|
||||
|
||||
extern void SyncDirectory(SyncParams *p);
|
||||
|
||||
#endif /* _dosync_h */
|
||||
147
cde/programs/dtfile/dtcopy/dtcopy.h
Normal file
147
cde/programs/dtfile/dtcopy/dtcopy.h
Normal file
@@ -0,0 +1,147 @@
|
||||
/* $XConsortium: dtcopy.h /main/7 1996/10/29 17:08:48 mustafa $ */
|
||||
/************************************<+>*************************************
|
||||
****************************************************************************
|
||||
*
|
||||
* FILE: dtcopy.h
|
||||
*
|
||||
*
|
||||
* DESCRIPTION: Header file used in copydialog.c,errordialog.c
|
||||
* main_dtcopy.c,overwrtdialog.c,utils.c
|
||||
*
|
||||
* (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
|
||||
* (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
|
||||
* (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
|
||||
* (c) Copyright 1993, 1994, 1995 Novell, Inc.
|
||||
*
|
||||
****************************************************************************
|
||||
************************************<+>*************************************/
|
||||
|
||||
/* Macros */
|
||||
#define MAX_PATH 1024
|
||||
|
||||
#define G_OVERWRITE_EXISTING 0
|
||||
#define G_SKIP 1
|
||||
#define G_RENAME_EXISTING 2
|
||||
#define N_OVERWRITE_RADIO_BUTTONS 3
|
||||
|
||||
/* Help numbers that are used locally in dtcopy
|
||||
* to indentify what help volume should be used
|
||||
* for a particular callback. Look to utils.c
|
||||
* in help_callback for code. MJT
|
||||
*/
|
||||
#define HELP_HELP_MENU 1
|
||||
#define HELP_INTRODUCTION 2
|
||||
#define HELP_DIR_COPY 3
|
||||
#define HELP_DIR_ERROR 4
|
||||
#define HELP_OVERWRITE 5
|
||||
#define HELP_USING 6
|
||||
#define HELP_VERSION 7
|
||||
#define STOPW_HELP_DIALOG 9
|
||||
|
||||
/* debugging output */
|
||||
#ifdef DEBUG
|
||||
extern int debug;
|
||||
#define DPRINTF(p) if (debug) printf p
|
||||
#define DPRINTF2(p) if (debug >= 2) printf p
|
||||
#else
|
||||
#define DPRINTF(p) /* noop */
|
||||
#define DPRINTF2(p) /* noop */
|
||||
#endif
|
||||
|
||||
/* _DtMessage Dialog build defines */
|
||||
#define ERROR_DIALOG 1
|
||||
#define WARNING_DIALOG 2
|
||||
#define QUESTION_DIALOG 3
|
||||
|
||||
/* Global Variables */
|
||||
extern Widget G_toplevel;
|
||||
extern Widget G_overwrite_radio;
|
||||
extern Widget G_summary_text;
|
||||
extern Widget G_status_text;
|
||||
extern Widget G_status_text2;
|
||||
extern Widget G_error_count;
|
||||
extern Widget G_error_msgs;
|
||||
extern Widget G_copy_dialog;
|
||||
extern Widget G_error_dialog;
|
||||
extern Widget G_over_dialog;
|
||||
extern Widget G_over_confirm;
|
||||
extern Widget G_copy_action_area_pbuttons[4];
|
||||
extern Widget G_help_dialog;
|
||||
extern Widget G_rename_text;
|
||||
extern Widget G_toggle_main;
|
||||
extern Widget G_toggle_error;
|
||||
|
||||
extern char G_rename_oldname[];
|
||||
extern char G_source_dir[];
|
||||
extern int G_move;
|
||||
extern int G_do_copy;
|
||||
extern int G_pause_copy;
|
||||
extern int G_user_pause_copy;
|
||||
extern int G_wait_on_error;
|
||||
extern int G_error_status;
|
||||
extern int G_ignore_errors;
|
||||
extern int G_overwrite_selection;
|
||||
extern int G_overwrite_confirm;
|
||||
extern int G_wait_on_input;
|
||||
extern int G_dialog_closed;
|
||||
|
||||
/* Types */
|
||||
|
||||
|
||||
/* External Routines */
|
||||
|
||||
extern void help_callback(
|
||||
Widget widget,
|
||||
XtPointer client_data,
|
||||
XtPointer call_data);
|
||||
extern void sensitize_copy_action_area(
|
||||
Widget *pushbutton_array);
|
||||
extern void desensitize_copy_action_area(
|
||||
Widget *pushbutton_array);
|
||||
extern Boolean create_copydir_dialog(
|
||||
Widget parent_widget,
|
||||
char *source,
|
||||
char *target);
|
||||
extern void create_error_dialog(
|
||||
Widget parent_widget,
|
||||
char *op,
|
||||
char *filename,
|
||||
int errnum);
|
||||
extern void create_overwrite_dialog(
|
||||
Widget parent_widget,
|
||||
char *sname,
|
||||
char *tname,
|
||||
Boolean isdir);
|
||||
extern void _DtChildPosition(
|
||||
Widget w,
|
||||
Widget parent,
|
||||
Position *newX,
|
||||
Position *newY);
|
||||
extern void cancel_callback(
|
||||
Widget w,
|
||||
XtPointer client_data,
|
||||
XtPointer call_data);
|
||||
extern void display_cancel_warning(Widget parent);
|
||||
extern void toggle_callback(
|
||||
Widget w,
|
||||
XtPointer client_data,
|
||||
XtPointer call_data);
|
||||
extern int touch(String path);
|
||||
|
||||
/*
|
||||
* macro to get message catalog strings
|
||||
*/
|
||||
|
||||
#ifndef NO_MESSAGE_CATALOG
|
||||
# ifdef __ultrix
|
||||
# define _CLIENT_CAT_NAME "dtcopy.cat"
|
||||
# else /* __ultrix */
|
||||
# define _CLIENT_CAT_NAME "dtcopy"
|
||||
# endif /* __ultrix */
|
||||
extern char *_DtGetMessage(char *filename, int set, int n, char *s);
|
||||
# define GETMESSAGE(set, number, string)\
|
||||
(_DtGetMessage(_CLIENT_CAT_NAME, set, number, string))
|
||||
#else
|
||||
# define GETMESSAGE(set, number, string)\
|
||||
string
|
||||
#endif
|
||||
120
cde/programs/dtfile/dtcopy/dtcopy.msg
Normal file
120
cde/programs/dtfile/dtcopy/dtcopy.msg
Normal file
@@ -0,0 +1,120 @@
|
||||
$ $XConsortium: dtcopy.msg /main/4 1996/10/29 17:06:57 mustafa $
|
||||
$ ************************************<+>*************************************
|
||||
$ ****************************************************************************
|
||||
$ *
|
||||
$ * FILE: dtcopy.msg
|
||||
$ *
|
||||
$ *
|
||||
$ * DESCRIPTION: Message catalog file
|
||||
$ *
|
||||
$ * (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
|
||||
$ * (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
|
||||
$ * (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
|
||||
$ * (c) Copyright 1993, 1994, 1995 Novell, Inc.
|
||||
$ *
|
||||
$ ****************************************************************************
|
||||
$ ************************************<+>*************************************
|
||||
|
||||
$set 2
|
||||
$ ****** Module: main_dtcopy.c ******
|
||||
3 file
|
||||
4 files
|
||||
5 subfolder
|
||||
6 subfolders
|
||||
7 Errors: none
|
||||
8 Errors: %d
|
||||
10 Usage: %s [options ...] source target\n
|
||||
11 File Manager - Folder Move
|
||||
12 File Manager - Folder Copy
|
||||
13 %s not removed because of errors.
|
||||
14 Completed.
|
||||
15 Cancelled in
|
||||
$ ** Message 20 - 32
|
||||
$ ** LongFileOpNames ... message number = op + 20.
|
||||
20 processing
|
||||
21 opening
|
||||
22 opening
|
||||
23 opening
|
||||
24 reading link
|
||||
25 deleting
|
||||
26 copying
|
||||
27 creating directory
|
||||
28 copying link
|
||||
29 creating link
|
||||
30 working
|
||||
31 is a copy
|
||||
32 is a link
|
||||
33 renaming
|
||||
|
||||
$set 3
|
||||
$ ****** Module: copydialog.c ******
|
||||
1 Resume
|
||||
2 Pause
|
||||
3 Moving:
|
||||
4 Copying:
|
||||
5 Into folder:
|
||||
7 This will stop the copy process. Any files that have\n\
|
||||
already been copied will remain in the destination folder.
|
||||
10 This will stop the move process. Any files that have\n\
|
||||
already been moved will remain in the destination folder.
|
||||
11 Folder Copy - Warning
|
||||
12 Folder Move - Warning
|
||||
13 Cancel Copy
|
||||
14 Continue Copy
|
||||
15 Cancel Move
|
||||
16 Continue Move
|
||||
17 Moved
|
||||
18 Copied
|
||||
19 "Cannot move folder into itself\n\
|
||||
%s\n"
|
||||
20 "Cannot copy folder into itself\n\
|
||||
%s\n"
|
||||
|
||||
$set 4
|
||||
$ ****** Module: errordialog.c ******
|
||||
1 Error %s\n%s
|
||||
2 Pause for errors
|
||||
3 Folder Copy - Error
|
||||
4 Folder Move - Error
|
||||
5 Object Move - Error
|
||||
6 Object Copy - Error
|
||||
7 Object Trash - Error
|
||||
8 You do not have permission to put the object \n\n\
|
||||
%s\n\n\
|
||||
into trash.\n\n\
|
||||
Use the Change Permissions choice from the object's\n\
|
||||
popup menu or from the Selected menu to turn on your\n\
|
||||
Read permission on the object.\n\n\
|
||||
\n\
|
||||
Note: If this object is a folder, you must also have\n\
|
||||
Read permission for each of the objects inside the\n\
|
||||
folder before you can put the folder in the trash.
|
||||
|
||||
9 Cannot open %s
|
||||
|
||||
$set 5
|
||||
$ ****** Module: overwrtdialog.c ******
|
||||
1 A file named\n%s\nalready exists inside the folder\n%s
|
||||
2 Folder Move - File Overwrite
|
||||
3 Replace existing file
|
||||
4 Rename existing file to:
|
||||
5 Rename new object to:
|
||||
6 Skip this file
|
||||
7 Apply this action to subsequent name conflicts
|
||||
8 Action to take:
|
||||
9 Folder Copy - File Overwrite
|
||||
10 %s\nalready exists: choose another name.
|
||||
11 File Overwrite - Error
|
||||
12 %s\ncannot be renamed to\n%s\n%s
|
||||
|
||||
$set 6
|
||||
$ ****** Module: utils.c ******
|
||||
$ ** Button labels.
|
||||
1 OK
|
||||
2 Pause
|
||||
3 Cancel
|
||||
4 Help
|
||||
5 Directory Copy Help
|
||||
6 Continue
|
||||
7 Cancel Copy
|
||||
8 Cancel Move
|
||||
304
cde/programs/dtfile/dtcopy/errordialog.c
Normal file
304
cde/programs/dtfile/dtcopy/errordialog.c
Normal file
@@ -0,0 +1,304 @@
|
||||
/* $XConsortium: errordialog.c /main/6 1996/10/17 09:36:14 mustafa $ */
|
||||
/************************************<+>*************************************
|
||||
****************************************************************************
|
||||
*
|
||||
* FILE: errordialog.c
|
||||
*
|
||||
*
|
||||
* DESCRIPTION: Routines to create dialogs for error messages
|
||||
*
|
||||
* FUNCTIONS: create_error_dialog
|
||||
* error_cancel_callback
|
||||
* ok_callback
|
||||
* toggle_callback
|
||||
*
|
||||
* (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
|
||||
* (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
|
||||
* (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
|
||||
* (c) Copyright 1993, 1994, 1995 Novell, Inc.
|
||||
*
|
||||
****************************************************************************
|
||||
************************************<+>*************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <sys/wait.h>
|
||||
#include <time.h>
|
||||
#include <X11/Intrinsic.h>
|
||||
#include <X11/StringDefs.h>
|
||||
#include <Xm/XmP.h>
|
||||
#include <Xm/Xm.h>
|
||||
#include <Xm/PushB.h>
|
||||
#include <Xm/DialogS.h>
|
||||
#include <Xm/Form.h>
|
||||
#include <Xm/Frame.h>
|
||||
#include <Xm/BulletinB.h>
|
||||
#include <Xm/Label.h>
|
||||
#include <Xm/Text.h>
|
||||
#include <Xm/TextF.h>
|
||||
#include <Xm/ToggleB.h>
|
||||
#include <Xm/Separator.h>
|
||||
|
||||
#include "dtcopy.h"
|
||||
#include "sharedFuncs.h"
|
||||
|
||||
#define VERTICAL_SPACING 5
|
||||
#define HORIZONTAL_SPACING 8
|
||||
#define TOP_SPACING (VERTICAL_SPACING + 3)
|
||||
#define INDENTED_SPACING (HORIZONTAL_SPACING + 5)
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* callbacks
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
static void
|
||||
ok_callback(
|
||||
Widget w,
|
||||
XtPointer client_data,
|
||||
XtPointer call_data)
|
||||
{
|
||||
XtDestroyWidget(G_error_dialog);
|
||||
G_wait_on_input = FALSE;
|
||||
G_error_status = 0;
|
||||
G_error_dialog = NULL;
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
error_cancel_callback(
|
||||
Widget w,
|
||||
XtPointer client_data,
|
||||
XtPointer call_data)
|
||||
{
|
||||
display_cancel_warning(G_error_dialog);
|
||||
|
||||
G_pause_copy = TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
*
|
||||
* The toggle shows up in more than one dialog
|
||||
* thus the state of the two widgets must be
|
||||
* synchronized.
|
||||
*
|
||||
*------------------------------------------------*/
|
||||
void
|
||||
toggle_callback(
|
||||
Widget w,
|
||||
XtPointer client_data,
|
||||
XtPointer call_data)
|
||||
{
|
||||
|
||||
|
||||
G_ignore_errors = !G_ignore_errors;
|
||||
|
||||
if (w == G_toggle_main)
|
||||
{
|
||||
if (G_error_dialog != NULL)
|
||||
XtVaSetValues(G_toggle_error,
|
||||
XmNset, !G_ignore_errors,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
XtVaSetValues(G_toggle_main,
|
||||
XmNset, !G_ignore_errors,
|
||||
NULL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* create error dialog
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
create_error_dialog(
|
||||
Widget parent_widget,
|
||||
char *op,
|
||||
char *filename,
|
||||
int errnum)
|
||||
{
|
||||
char buf[1024];
|
||||
char *msg;
|
||||
|
||||
Arg args[10];
|
||||
int n;
|
||||
XmString xm_string;
|
||||
Widget form, outerFrame;
|
||||
Widget icon, error_header_label, error_text_label;
|
||||
Widget separator, action_area;
|
||||
Pixel background, foreground;
|
||||
Pixmap px;
|
||||
Position x, y;
|
||||
|
||||
static ActionAreaItem copy_action_items[] = {
|
||||
{"Continue", 6, 6, ok_callback, NULL},
|
||||
{"Cancel Copy", 6, 7, error_cancel_callback, NULL},
|
||||
{"Help", 6, 4, help_callback, (XtPointer) HELP_DIR_ERROR},
|
||||
};
|
||||
|
||||
ActionAreaDefn copyActions = {
|
||||
XtNumber(copy_action_items),
|
||||
0, /* Ok is default action */
|
||||
copy_action_items
|
||||
};
|
||||
|
||||
static ActionAreaItem move_action_items[] = {
|
||||
{"Continue", 6, 6, ok_callback, NULL},
|
||||
{"Cancel Move", 6, 8, error_cancel_callback, NULL},
|
||||
{"Help", 6, 4, help_callback, (XtPointer) HELP_DIR_ERROR},
|
||||
};
|
||||
|
||||
ActionAreaDefn moveActions = {
|
||||
XtNumber(move_action_items),
|
||||
0, /* Ok is default action */
|
||||
move_action_items
|
||||
};
|
||||
|
||||
|
||||
/* Create the dialog shell for the dialog */
|
||||
n=0;
|
||||
XtSetArg (args[n], XmNallowShellResize, True); n++;
|
||||
XtSetArg (args[n], XmNmappedWhenManaged, False); n++;
|
||||
if (G_move)
|
||||
{
|
||||
XtSetArg (args[n], XmNtitle, GETMESSAGE(4, 4, "Folder Move - Error")); n++;
|
||||
}
|
||||
else
|
||||
{
|
||||
XtSetArg (args[n], XmNtitle, GETMESSAGE(4, 3, "Folder Copy - Error")); n++;
|
||||
}
|
||||
|
||||
G_error_dialog = XmCreateDialogShell (G_copy_dialog, "dialog_shell", args, n);
|
||||
|
||||
/* create a frame around the dialog for better separation from window border */
|
||||
outerFrame = XtVaCreateManagedWidget("outerFrame",
|
||||
xmFrameWidgetClass, G_error_dialog,
|
||||
XmNshadowThickness, 3,
|
||||
XmNshadowType, XmSHADOW_ETCHED_IN,
|
||||
NULL);
|
||||
|
||||
|
||||
/* Create the Manager Widget, form, for the copy error dialog */
|
||||
form = XtVaCreateManagedWidget ("dialog_form",
|
||||
xmFormWidgetClass,
|
||||
outerFrame,
|
||||
XmNverticalSpacing, VERTICAL_SPACING,
|
||||
XmNhorizontalSpacing, HORIZONTAL_SPACING,
|
||||
NULL);
|
||||
|
||||
/* create the action area of the Error Dialog */
|
||||
if (G_move)
|
||||
action_area = Create_Action_Area(form, moveActions, NULL);
|
||||
else
|
||||
action_area = Create_Action_Area(form, copyActions, NULL);
|
||||
|
||||
/* create the separator widget */
|
||||
separator = XtVaCreateManagedWidget("seperator",
|
||||
xmSeparatorWidgetClass,
|
||||
form,
|
||||
XmNbottomAttachment, XmATTACH_WIDGET,
|
||||
XmNbottomWidget, action_area,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
NULL);
|
||||
|
||||
|
||||
|
||||
/* Create the error dialog icon */
|
||||
n = 0;
|
||||
XtSetArg (args[n], XmNbackground, &background); n++;
|
||||
XtSetArg (args[n], XmNforeground, &foreground); n++;
|
||||
XtGetValues (form, args, n);
|
||||
px = XmGetPixmapByDepth(XtScreen(form), "xm_error",
|
||||
foreground, background, form->core.depth);
|
||||
if (px == XmUNSPECIFIED_PIXMAP)
|
||||
px = XmGetPixmapByDepth(XtScreen(form), "default_xm_error",
|
||||
foreground, background, form->core.depth);
|
||||
|
||||
icon = XtVaCreateManagedWidget("error_icon",
|
||||
xmLabelWidgetClass,
|
||||
form,
|
||||
XmNlabelType, XmPIXMAP,
|
||||
XmNlabelPixmap, px,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNbottomAttachment, XmATTACH_WIDGET,
|
||||
XmNbottomWidget, separator,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
NULL);
|
||||
|
||||
/* Create the first error message label */
|
||||
sprintf(buf,GETMESSAGE(4, 1, "Error %s\n%s"), op, filename);
|
||||
xm_string = XmStringCreateLocalized(buf);
|
||||
error_header_label = XtVaCreateManagedWidget("msg_header",
|
||||
xmLabelWidgetClass,
|
||||
form,
|
||||
XmNlabelString, xm_string,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_WIDGET,
|
||||
XmNleftWidget, icon,
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
XmNalignment, XmALIGNMENT_BEGINNING,
|
||||
NULL);
|
||||
XmStringFree(xm_string);
|
||||
|
||||
/* Create the second error message label */
|
||||
msg = strerror(errnum);
|
||||
xm_string = XmStringCreateLocalized(msg);
|
||||
error_text_label = XtVaCreateManagedWidget("msg_text",
|
||||
xmLabelWidgetClass,
|
||||
form,
|
||||
XmNlabelString, xm_string,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, error_header_label,
|
||||
XmNleftAttachment, XmATTACH_WIDGET,
|
||||
XmNleftWidget, icon,
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
XmNalignment, XmALIGNMENT_BEGINNING,
|
||||
NULL);
|
||||
XmStringFree(xm_string);
|
||||
|
||||
/* create the toggle button */
|
||||
xm_string = XmStringCreateLocalized(GETMESSAGE(4, 2, "Pause for errors"));
|
||||
G_toggle_error = XtVaCreateManagedWidget("toggle",
|
||||
xmToggleButtonWidgetClass,
|
||||
form,
|
||||
XmNlabelString, xm_string,
|
||||
XmNset, !G_ignore_errors,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, error_text_label,
|
||||
XmNleftAttachment, XmATTACH_WIDGET,
|
||||
XmNleftWidget, icon,
|
||||
XmNbottomAttachment, XmATTACH_WIDGET,
|
||||
XmNbottomWidget, separator,
|
||||
XmNalignment, XmALIGNMENT_BEGINNING,
|
||||
NULL);
|
||||
XtAddCallback(G_toggle_error, XmNvalueChangedCallback, toggle_callback, NULL);
|
||||
XmStringFree(xm_string);
|
||||
/* set initial keyborad focus to the action button area */
|
||||
XtSetArg (args[0], XmNinitialFocus, action_area);
|
||||
XtSetValues(form, args, 1);
|
||||
|
||||
/* Manage the Dialog */
|
||||
XtManageChild(form);
|
||||
|
||||
|
||||
/* Choose a window position */
|
||||
_DtChildPosition(G_error_dialog, G_toplevel, &x, &y);
|
||||
n=0;
|
||||
XtSetArg (args[n], XmNx, x); n++;
|
||||
XtSetArg (args[n], XmNy, y); n++;
|
||||
XtSetValues(G_error_dialog, args, n);
|
||||
|
||||
/* Now that we have a window postion, mapp the dialog shell */
|
||||
XtMapWidget(G_error_dialog);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
509
cde/programs/dtfile/dtcopy/fsrtns.c
Normal file
509
cde/programs/dtfile/dtcopy/fsrtns.c
Normal file
@@ -0,0 +1,509 @@
|
||||
/* $TOG: fsrtns.c /main/6 1998/10/26 12:41:20 mgreess $ */
|
||||
/************************************<+>*************************************
|
||||
****************************************************************************
|
||||
*
|
||||
* FILE: fsrtns.c
|
||||
*
|
||||
*
|
||||
* DESCRIPTION: Routines to manipulate files and directores
|
||||
*
|
||||
* FUNCTIONS: CopyDir
|
||||
* CopyFile
|
||||
* CopyLink
|
||||
* CopyObject
|
||||
* EmptyDir
|
||||
* EraseObject
|
||||
* fsCopy
|
||||
* fsCopyLink
|
||||
* fsEmpty
|
||||
* fsErase
|
||||
* fsMove
|
||||
* fsRename
|
||||
*
|
||||
* (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
|
||||
* (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
|
||||
* (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
|
||||
* (c) Copyright 1993, 1994, 1995 Novell, Inc.
|
||||
*
|
||||
****************************************************************************
|
||||
************************************<+>*************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/time.h>
|
||||
#include <utime.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/file.h>
|
||||
#include <string.h>
|
||||
#include "fsrtns.h"
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* Callback functions
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
int (*progressCallback)(char *fname) = NULL;
|
||||
int (*errorCallback)(char *fname, int errnum) = NULL;
|
||||
int (*periodicCallback)() = NULL;
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* Local subroutines
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
static int CopyObject(char *sourceP, char *targetP, int repl, int link);
|
||||
static int EraseObject(char *nameP, int force);
|
||||
|
||||
|
||||
static int
|
||||
CopyFile(char *sourceP, char *targetP, int repl, struct stat *statP)
|
||||
/* copy a file; if repl non-zero, overwrite any existing file */
|
||||
{
|
||||
int src, tgt;
|
||||
int nread, nwrite;
|
||||
char buffer[2048];
|
||||
struct utimbuf ut;
|
||||
int rc;
|
||||
|
||||
/* open source file for read */
|
||||
src = open(sourceP, O_RDONLY, 0);
|
||||
if (src < 0)
|
||||
return errno;
|
||||
|
||||
/* create target file */
|
||||
tgt = open(targetP, O_CREAT | O_EXCL | O_WRONLY, statP->st_mode & 0777);
|
||||
if (tgt < 0 && errno == EEXIST && repl) {
|
||||
rc = EraseObject(targetP, repl);
|
||||
if (rc) {
|
||||
close(src);
|
||||
return rc;
|
||||
}
|
||||
tgt = open(targetP, O_CREAT | O_EXCL | O_WRONLY, statP->st_mode & 0777);
|
||||
}
|
||||
if (tgt < 0) {
|
||||
rc = errno;
|
||||
close(src);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* if we have root privileges, make sure file ownership is preserved */
|
||||
if (geteuid() == 0) {
|
||||
if (statP->st_uid != 0 || statP->st_gid != getegid()) {
|
||||
rc = fchown(tgt, statP->st_uid, statP->st_gid);
|
||||
if (rc) {
|
||||
rc = errno;
|
||||
close(src);
|
||||
close(tgt);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* copy data */
|
||||
for (;;) {
|
||||
/* read data from source file */
|
||||
do {
|
||||
errno = 0;
|
||||
nread = read(src, buffer, sizeof(buffer));
|
||||
} while (nread < 0 && errno == EINTR);
|
||||
if (nread <= 0)
|
||||
break;
|
||||
|
||||
/* write data to target file */
|
||||
do {
|
||||
errno = 0;
|
||||
nwrite = write(tgt, buffer, nread);
|
||||
} while (nwrite < 0 && errno == EINTR);
|
||||
if (nwrite != nread)
|
||||
break;
|
||||
|
||||
if (periodicCallback)
|
||||
if (periodicCallback() != 0) {
|
||||
unlink(targetP);
|
||||
close(src);
|
||||
close(tgt);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* check if data copy ended abnormally */
|
||||
rc = (nread == 0)? 0: (errno != 0)? errno: -1;
|
||||
|
||||
/* close files */
|
||||
close(src);
|
||||
if (rc) {
|
||||
close(tgt);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (close(tgt) != 0)
|
||||
return errno;
|
||||
|
||||
/* set target file attributes */
|
||||
ut.actime = statP->st_atime;
|
||||
ut.modtime = statP->st_mtime;
|
||||
rc = utime(targetP, &ut);
|
||||
|
||||
return (rc != 0)? errno: 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
CopyLink(char *sourceP, char *targetP, int repl, struct stat *statP)
|
||||
/* copy a symbolic link */
|
||||
{
|
||||
int l, rc;
|
||||
char buf[1024];
|
||||
|
||||
do {
|
||||
errno = 0;
|
||||
l = readlink(sourceP, buf, sizeof(buf));
|
||||
} while (l < 0 && errno == EINTR);
|
||||
if (l < 0)
|
||||
return errno;
|
||||
buf[l] = 0;
|
||||
if (symlink(buf, targetP) == 0)
|
||||
return 0;
|
||||
else if (errno != EEXIST || !repl)
|
||||
return errno;
|
||||
|
||||
if ((rc = EraseObject(targetP, repl)) != 0)
|
||||
return rc;
|
||||
if (symlink(buf, targetP) == 0)
|
||||
return 0;
|
||||
else
|
||||
return errno;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
CopyDir(char *sourceP, char *targetP, int repl, int link, struct stat *statP)
|
||||
/* copy a directory and recursively all its subdirectories */
|
||||
{
|
||||
DIR *dirP; /* open directory */
|
||||
struct dirent *entryP; /* directory entry */
|
||||
char srcname[1024], tgtname[1024];
|
||||
int srclen, tgtlen;
|
||||
int rc;
|
||||
|
||||
/* open source directory */
|
||||
dirP = opendir(sourceP);
|
||||
if (dirP == NULL)
|
||||
return errno;
|
||||
|
||||
/* create target directory */
|
||||
rc = mkdir(targetP, statP->st_mode & 0777);
|
||||
if (rc < 0 && errno == EEXIST && repl) {
|
||||
rc = EraseObject(targetP, repl);
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = mkdir(targetP, statP->st_mode & 0777);
|
||||
}
|
||||
if (rc < 0) {
|
||||
rc = errno;
|
||||
closedir(dirP);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* if we have root privileges, make sure directory ownership is preserved */
|
||||
if (geteuid() == 0) {
|
||||
if (statP->st_uid != 0 || statP->st_gid != getegid()) {
|
||||
rc = chown(targetP, statP->st_uid, statP->st_gid);
|
||||
if (rc) {
|
||||
rc = errno;
|
||||
closedir(dirP);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* prepare source and target names */
|
||||
strcpy(srcname, sourceP);
|
||||
srclen = strlen(srcname);
|
||||
if (srcname[srclen - 1] != '/')
|
||||
srcname[srclen++] = '/';
|
||||
strcpy(tgtname, targetP);
|
||||
tgtlen = strlen(tgtname);
|
||||
if (tgtname[tgtlen - 1] != '/')
|
||||
tgtname[tgtlen++] = '/';
|
||||
|
||||
for (rc = 0; rc == 0; ) {
|
||||
do {
|
||||
errno = 0;
|
||||
entryP = readdir(dirP);
|
||||
} while (entryP == NULL && errno == EINTR);
|
||||
if (entryP == NULL) {
|
||||
rc = errno;
|
||||
break;
|
||||
}
|
||||
if (strcmp(entryP->d_name, ".") == 0 || strcmp(entryP->d_name, "..") == 0)
|
||||
continue;
|
||||
|
||||
strcpy(srcname + srclen, entryP->d_name);
|
||||
strcpy(tgtname + tgtlen, entryP->d_name);
|
||||
|
||||
rc = CopyObject(srcname, tgtname, repl, link);
|
||||
}
|
||||
|
||||
closedir(dirP);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
CopyObject(char *sourceP, char *targetP, int repl, int link)
|
||||
/* copy a directory, file, or symbolic link */
|
||||
{
|
||||
struct stat src_stat;
|
||||
int rc;
|
||||
|
||||
if (progressCallback)
|
||||
if (progressCallback(sourceP) != 0)
|
||||
return -1;
|
||||
|
||||
if (periodicCallback)
|
||||
if (periodicCallback() != 0)
|
||||
return -1;
|
||||
|
||||
if (lstat(sourceP, &src_stat) < 0)
|
||||
rc = errno;
|
||||
|
||||
else {
|
||||
|
||||
copy_switch:
|
||||
|
||||
switch(src_stat.st_mode & S_IFMT) {
|
||||
|
||||
case S_IFDIR:
|
||||
rc = CopyDir(sourceP, targetP, repl, link, &src_stat);
|
||||
break;
|
||||
|
||||
case S_IFREG:
|
||||
rc = CopyFile(sourceP, targetP, repl, &src_stat);
|
||||
break;
|
||||
|
||||
case S_IFLNK:
|
||||
if (link)
|
||||
rc = CopyLink(sourceP, targetP, repl, &src_stat);
|
||||
else if (stat(sourceP, &src_stat) < 0)
|
||||
rc = errno;
|
||||
else
|
||||
goto copy_switch;
|
||||
break;
|
||||
|
||||
default:
|
||||
rc = EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return code zero means everything is ok;
|
||||
* return code -1 means the operation is aborted.
|
||||
* In either case, propagated the return code up.
|
||||
*/
|
||||
if (rc <= 0)
|
||||
return rc;
|
||||
|
||||
/*
|
||||
* Return code > 0 means an error occurred in the last operation.
|
||||
* Call the the error callback function. If the callback returns
|
||||
* zero, we return zero; this will cause the error to be ignored.
|
||||
* Otherwise we return -1 to signal that the operation is aborted.
|
||||
*/
|
||||
if (!errorCallback)
|
||||
return rc;
|
||||
else if (errorCallback(sourceP, rc) == 0)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
EmptyDir(char *sourceP, int rm, int force)
|
||||
{
|
||||
DIR *dirP; /* open directory */
|
||||
struct dirent *entryP; /* directory entry */
|
||||
char srcname[1024];
|
||||
int srclen;
|
||||
int rc;
|
||||
|
||||
/* open source directory */
|
||||
dirP = opendir(sourceP);
|
||||
if (dirP == NULL)
|
||||
return errno;
|
||||
|
||||
/* prepare source name */
|
||||
strcpy(srcname, sourceP);
|
||||
srclen = strlen(srcname);
|
||||
if (srcname[srclen - 1] != '/')
|
||||
srcname[srclen++] = '/';
|
||||
|
||||
rc = 0;
|
||||
while (rc == 0 && (entryP = readdir(dirP)) != NULL) {
|
||||
if (strcmp(entryP->d_name, ".") == 0 || strcmp(entryP->d_name, "..") == 0)
|
||||
continue;
|
||||
strcpy(srcname + srclen, entryP->d_name);
|
||||
rc = EraseObject(srcname, force);
|
||||
}
|
||||
|
||||
closedir(dirP);
|
||||
if (rc == 0 && rm) {
|
||||
rc = rmdir(sourceP);
|
||||
if (rc < 0)
|
||||
rc = errno;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
EraseObject(char *nameP, int force)
|
||||
{
|
||||
struct stat src_stat;
|
||||
int rc;
|
||||
|
||||
if (periodicCallback)
|
||||
if (periodicCallback() != 0)
|
||||
return -1;
|
||||
|
||||
if (lstat(nameP, &src_stat) < 0)
|
||||
rc = errno;
|
||||
else if ((src_stat.st_mode & S_IFMT) == S_IFDIR) {
|
||||
if (! access(nameP, X_OK|W_OK))
|
||||
return errno;
|
||||
rc = EmptyDir(nameP, 1, force);
|
||||
}
|
||||
else {
|
||||
if (! (force || access(nameP, W_OK)))
|
||||
return errno;
|
||||
|
||||
if (! unlink(nameP))
|
||||
rc = errno;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return code zero means everything is ok;
|
||||
* return code -1 means the operation is aborted.
|
||||
* In either case, propagated the return code up.
|
||||
*/
|
||||
if (rc <= 0)
|
||||
return rc;
|
||||
|
||||
/*
|
||||
* Return code > 0 means an error occurred in the last operation.
|
||||
* Call the the error callback function. If the callback returns
|
||||
* zero, we return zero; this will cause the error to be ignored.
|
||||
* Otherwise we return -1 to signal that the operation is aborted.
|
||||
*/
|
||||
if (!errorCallback)
|
||||
return rc;
|
||||
else if (errorCallback(nameP, rc) == 0)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* Exported routines
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
fsRename(char *sourceP, char *targetP, int replace, int *rcP)
|
||||
{
|
||||
int rc;
|
||||
struct stat buf;
|
||||
|
||||
if (!replace) {
|
||||
/* return error if target file already exists */
|
||||
rc = lstat(targetP, &buf);
|
||||
if (rc == 0) {
|
||||
*rcP = EEXIST;
|
||||
return;
|
||||
} else if (errno != ENOENT) {
|
||||
*rcP = errno;
|
||||
return;
|
||||
}
|
||||
}
|
||||
*rcP = rename(sourceP, targetP);
|
||||
if (*rcP < 0)
|
||||
*rcP = errno;
|
||||
|
||||
if (replace && *rcP == ENOTDIR || *rcP == EISDIR) {
|
||||
/* error reason: tried to replace file by directory or vice versa */
|
||||
*rcP = EraseObject(targetP, replace);
|
||||
if (*rcP < 0)
|
||||
return;
|
||||
*rcP = rename(sourceP, targetP);
|
||||
if (*rcP < 0)
|
||||
*rcP = errno;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
fsMove(char *sourceP, char *targetP, int replace, int *rcP)
|
||||
{
|
||||
/* try to rename */
|
||||
fsRename(sourceP, targetP, replace, rcP);
|
||||
if (*rcP == 0 || *rcP != EXDEV)
|
||||
return;
|
||||
|
||||
/* source and target on different file systems: do copy + erase */
|
||||
{
|
||||
/* first check if we have write permission in the source directory */
|
||||
char dir[1024], *p;
|
||||
|
||||
strcpy(dir, sourceP);
|
||||
p = strrchr(dir, '/');
|
||||
if (p == 0)
|
||||
strcpy(dir, ".");
|
||||
else if (p == dir)
|
||||
strcpy(dir, "/");
|
||||
else
|
||||
*p = 0;
|
||||
|
||||
if (access(dir, W_OK) != 0) {
|
||||
*rcP = errno;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
*rcP = CopyObject(sourceP, targetP, replace, 1);
|
||||
if (*rcP != 0)
|
||||
return;
|
||||
*rcP = EraseObject(sourceP, replace);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
fsCopy(char *sourceP, char *targetP, int replace, int *rcP)
|
||||
{
|
||||
*rcP = CopyObject(sourceP, targetP, replace, 0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
fsCopyLink(char *sourceP, char *targetP, int replace, int *rcP)
|
||||
{
|
||||
*rcP = CopyObject(sourceP, targetP, replace, 1);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
fsErase(char *nameP, int *rcP, int force)
|
||||
{
|
||||
*rcP = EraseObject(nameP, force);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
fsEmpty(char *nameP, int *rcP)
|
||||
{
|
||||
*rcP = EmptyDir(nameP, 0, 0);
|
||||
}
|
||||
|
||||
107
cde/programs/dtfile/dtcopy/fsrtns.h
Normal file
107
cde/programs/dtfile/dtcopy/fsrtns.h
Normal file
@@ -0,0 +1,107 @@
|
||||
/* $TOG: fsrtns.h /main/6 1998/10/26 12:42:04 mgreess $ */
|
||||
/************************************<+>*************************************
|
||||
****************************************************************************
|
||||
*
|
||||
* FILE: fsrtns.h
|
||||
*
|
||||
*
|
||||
* DESCRIPTION: Header files used in dosync.c,fsrtns.c,main_dtcopy.c
|
||||
*
|
||||
* (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
|
||||
* (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
|
||||
* (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
|
||||
* (c) Copyright 1993, 1994, 1995 Novell, Inc.
|
||||
*
|
||||
****************************************************************************
|
||||
************************************<+>*************************************/
|
||||
|
||||
#ifndef _fsrtns_h
|
||||
#define _fsrtns_h
|
||||
|
||||
/*
|
||||
* General comments:
|
||||
*
|
||||
* The file systems routines below support renaming, moving, copying,
|
||||
* and deleting single files as well as directories. The operations
|
||||
* check return codes on close, so they are safe to use with AFS.
|
||||
*
|
||||
* If the operation failed, the the reason for the failure (errno value)
|
||||
* is returned in *rcP.
|
||||
*
|
||||
* The rename, move and copy routines all take a parameter 'replace'
|
||||
* that determines what happens if the target file/directory already
|
||||
* exists: if 'replace' is zero, the routines return an ENOENT error;
|
||||
* if 'replace' is non-zero the routines will replace any existing
|
||||
* files/directories.
|
||||
*
|
||||
* The copy and move operations preserve the modified timestamps and
|
||||
* file permissions of the source. If the calling program is running
|
||||
* as root, file ownership is also preserved.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* fsRename:
|
||||
* Renames or moves source to target.
|
||||
* Source and target must be on the same file system.
|
||||
*/
|
||||
extern void fsRename(char *source, char *target, int replace, int *rcP);
|
||||
|
||||
/*
|
||||
* fsMove:
|
||||
* Like fsRename, but also works if source and target are on different
|
||||
* file systems by copying source to target and then deleting source.
|
||||
*/
|
||||
extern void fsMove(char *source, char *target, int replace, int *rcP);
|
||||
|
||||
/*
|
||||
* fsCopy:
|
||||
* Copies source to target.
|
||||
*/
|
||||
extern void fsCopy(char *source, char *target, int replace, int *rcP);
|
||||
|
||||
/*
|
||||
* fsCopyLink:
|
||||
* Like fsCopy, but copies symbolic links as links, i.e.,creates a link
|
||||
* that points to the same place as the source link. Applies in the case
|
||||
* where source itself is a symbolic link, as well as the case where
|
||||
* source is a directory that contains symbolic links.
|
||||
*/
|
||||
extern void fsCopyLink(char *source, char *target, int replace, int *rcP);
|
||||
|
||||
/*
|
||||
* fsErase:
|
||||
* Deletes a file or directory.
|
||||
*/
|
||||
extern void fsErase(char *name, int *rcP, int force);
|
||||
|
||||
/*
|
||||
* fsEmpty:
|
||||
* Deletes all files/directries in the named directory.
|
||||
*
|
||||
*/
|
||||
extern void fsEmpty(char *name, int *rcP);
|
||||
|
||||
|
||||
/*
|
||||
* Callback functions:
|
||||
*
|
||||
* progressCallback:
|
||||
* called each time a new file or directory is being processed
|
||||
*
|
||||
* errorCallback:
|
||||
* called when a file operation fails
|
||||
*
|
||||
* periodicCallback:
|
||||
* called periodically
|
||||
*
|
||||
* Each callback function should return zero if the file operation
|
||||
* is supposed to continue. To abort the operation, return a non-zero
|
||||
* value from one of the callback functions.
|
||||
*/
|
||||
extern int (*progressCallback)(char *fname);
|
||||
extern int (*errorCallback)(char *fname, int errnum);
|
||||
extern int (*periodicCallback)(void);
|
||||
|
||||
|
||||
#endif /* _fsrtns_h */
|
||||
918
cde/programs/dtfile/dtcopy/main_dtcopy.c
Normal file
918
cde/programs/dtfile/dtcopy/main_dtcopy.c
Normal file
@@ -0,0 +1,918 @@
|
||||
/* $TOG: main_dtcopy.c /main/10 1998/10/26 12:42:41 mgreess $ */
|
||||
/************************************<+>*************************************
|
||||
****************************************************************************
|
||||
*
|
||||
* FILE: main_dtcopy.c
|
||||
*
|
||||
* COMPONENT_NAME: dtcopy - Handles move/copy/link operations for 'dtfile'
|
||||
*
|
||||
* DESCRIPTION: Main program for dtfile_copy.
|
||||
*
|
||||
*
|
||||
* FUNCTIONS: AppendErrorMsg
|
||||
* CheckForMap
|
||||
* ConfirmHandler
|
||||
* ErrorHandler
|
||||
* EventCheck
|
||||
* InitNlsMessage
|
||||
* TimeoutHandler
|
||||
* UpdateErrorCount
|
||||
* UpdateStatus
|
||||
* UpdateSummary
|
||||
* get_command_line
|
||||
* main
|
||||
* moveDeleteCallback
|
||||
* moveErrorCallback
|
||||
*
|
||||
* (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
|
||||
* (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
|
||||
* (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
|
||||
* (c) Copyright 1993, 1994, 1995 Novell, Inc.
|
||||
*
|
||||
****************************************************************************
|
||||
************************************<+>*************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <locale.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <X11/Intrinsic.h>
|
||||
#include <X11/StringDefs.h>
|
||||
#include <Xm/Xm.h>
|
||||
|
||||
/* #Include <X11/Xmu/Editres.h> */ /* for editres debugging tool */
|
||||
|
||||
#include <Dt/Connect.h>
|
||||
#include <Dt/DtNlUtils.h>
|
||||
#include <Dt/EnvControlP.h>
|
||||
|
||||
#include "fsrtns.h"
|
||||
#include "dosync.h"
|
||||
#include "dtcopy.h"
|
||||
#include "sharedFuncs.h"
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* Global Variables
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
extern Widget G_toplevel;
|
||||
Widget G_summary_text;
|
||||
Widget G_status_text;
|
||||
/* Widget G_status_text2; */
|
||||
Widget G_error_count;
|
||||
Widget G_error_msgs;
|
||||
Widget G_copy_dialog;
|
||||
Widget G_error_dialog = NULL;
|
||||
Widget G_over_dialog = NULL;
|
||||
Widget G_over_confirm;
|
||||
Widget G_copy_action_area_pbuttons[4];
|
||||
Widget G_help_dialog;
|
||||
Widget G_overwrite_radio;
|
||||
Widget G_rename_text;
|
||||
Widget G_toggle_main;
|
||||
Widget G_toggle_error;
|
||||
|
||||
int G_overwrite_selection = G_OVERWRITE_EXISTING;
|
||||
int G_move = FALSE;
|
||||
int G_do_copy = TRUE;
|
||||
int G_pause_copy = FALSE;
|
||||
int G_user_pause_copy = FALSE;
|
||||
int G_wait_on_error = TRUE;
|
||||
int G_error_status = 0;
|
||||
int G_ignore_errors = FALSE;
|
||||
int G_overwrite_confirm = TRUE;
|
||||
int G_wait_on_input = TRUE;
|
||||
extern int G_dialog_closed;
|
||||
|
||||
char G_rename_oldname[MAX_PATH];
|
||||
char G_source_dir[MAX_PATH];
|
||||
|
||||
/* debugging flag */
|
||||
#ifdef DEBUG
|
||||
int debug = 0;
|
||||
#endif
|
||||
|
||||
static XtAppContext app_context;
|
||||
static Display *display;
|
||||
static Boolean is_mapped = False;
|
||||
static int nfiles = 0;
|
||||
static int ndirs = 0;
|
||||
static int nerr = 0;
|
||||
static char last_dir[MAX_PATH];
|
||||
|
||||
#define FILEOPNUM 14
|
||||
static char *LongFileOpNames[FILEOPNUM];
|
||||
static char *DefaultLongFileOpNames[] = {
|
||||
"processing",
|
||||
"opening",
|
||||
"opening",
|
||||
"opening",
|
||||
"reading link",
|
||||
"deleting",
|
||||
"copying",
|
||||
"creating directory",
|
||||
"copying link",
|
||||
"creating link",
|
||||
"working",
|
||||
"is a copy",
|
||||
"is a link",
|
||||
"renaming"
|
||||
};
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* application resource definitions
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *source_name;
|
||||
char *target_name;
|
||||
SyncParams sync;
|
||||
Boolean move;
|
||||
Boolean confirmreplace;
|
||||
Boolean confirmerrors;
|
||||
Boolean popdown;
|
||||
int delay;
|
||||
Boolean use_toggle_buttons;
|
||||
Boolean slow;
|
||||
Boolean checkPerms;
|
||||
} AppArgs, *AppArgsPtr;
|
||||
|
||||
static AppArgs app_args;
|
||||
|
||||
static XtResource resources[] =
|
||||
{
|
||||
/* source and target directories */
|
||||
|
||||
{ "source", "Source", XmRString, sizeof (char *),
|
||||
XtOffset (AppArgsPtr, source_name), XmRImmediate, (XtPointer) NULL, },
|
||||
|
||||
{ "target", "Target", XmRString, sizeof (char *),
|
||||
XtOffset (AppArgsPtr, target_name), XmRImmediate, (XtPointer) NULL, },
|
||||
|
||||
/* SyncParams */
|
||||
|
||||
{ "verbose", "Verbose", XmRBool, sizeof (int),
|
||||
XtOffset (AppArgsPtr, sync.verbose), XmRImmediate, (XtPointer) True, },
|
||||
|
||||
{ "quiet", "Quiet", XmRBool, sizeof (int),
|
||||
XtOffset (AppArgsPtr, sync.quiet), XmRImmediate, (XtPointer) False, },
|
||||
|
||||
{ "dontDoIt", "DontDoIt", XmRBool, sizeof (int),
|
||||
XtOffset (AppArgsPtr, sync.dontdoit), XmRImmediate, (XtPointer) False, },
|
||||
|
||||
|
||||
{ "keepNew", "KeepNew", XmRBool, sizeof (int),
|
||||
XtOffset (AppArgsPtr, sync.keepnew), XmRImmediate, (XtPointer) False, },
|
||||
|
||||
{ "keepOld", "KeepOld", XmRString, sizeof (char *),
|
||||
XtOffset (AppArgsPtr, sync.keepold), XmRImmediate, (XtPointer) NULL, },
|
||||
|
||||
{ "dontDelete", "DontDelete", XmRBool, sizeof (int),
|
||||
XtOffset (AppArgsPtr, sync.dontdelete), XmRImmediate, (XtPointer) False, },
|
||||
|
||||
{ "dontAdd", "DontAdd", XmRBool, sizeof (int),
|
||||
XtOffset (AppArgsPtr, sync.dontadd), XmRImmediate, (XtPointer) False, },
|
||||
|
||||
{ "dontReplace", "DontReplace", XmRBool, sizeof (int),
|
||||
XtOffset (AppArgsPtr, sync.dontreplace),
|
||||
XmRImmediate, (XtPointer) False, },
|
||||
|
||||
{ "dontRecur", "DontRecur", XmRBool, sizeof (int),
|
||||
XtOffset (AppArgsPtr, sync.dontrecur), XmRImmediate, (XtPointer) False, },
|
||||
|
||||
{ "keepLinks", "KeepLinks", XmRBool, sizeof (int),
|
||||
XtOffset (AppArgsPtr, sync.keeplinks), XmRImmediate, (XtPointer) False, },
|
||||
|
||||
{ "keepCopies", "KeepCopies", XmRBool, sizeof (int),
|
||||
XtOffset (AppArgsPtr, sync.keepcopies), XmRImmediate, (XtPointer) False, },
|
||||
|
||||
{ "forceCopies", "ForceCopies", XmRBool, sizeof (int),
|
||||
XtOffset (AppArgsPtr, sync.forcecopies), XmRImmediate, (XtPointer) False, },
|
||||
|
||||
{ "listLinks", "ListLinks", XmRBool, sizeof (int),
|
||||
XtOffset (AppArgsPtr, sync.listlinks), XmRImmediate, (XtPointer) False, },
|
||||
|
||||
{ "listCopies", "ListCopies", XmRBool, sizeof (int),
|
||||
XtOffset (AppArgsPtr, sync.listcopies), XmRImmediate, (XtPointer) False, },
|
||||
|
||||
{ "linkFolders", "LinkFolders", XmRBool, sizeof (int),
|
||||
XtOffset (AppArgsPtr, sync.linkdirs), XmRImmediate, (XtPointer) False, },
|
||||
|
||||
{ "linkFiles", "LinkFiles", XmRBool, sizeof (int),
|
||||
XtOffset (AppArgsPtr, sync.linkfiles), XmRImmediate, (XtPointer) False, },
|
||||
|
||||
{ "copyFolders", "CopyFolders", XmRBool, sizeof (int),
|
||||
XtOffset (AppArgsPtr, sync.copydirs), XmRImmediate, (XtPointer) False, },
|
||||
|
||||
{ "copyFiles", "CopyFiles", XmRBool, sizeof (int),
|
||||
XtOffset (AppArgsPtr, sync.copyfiles), XmRImmediate, (XtPointer) False, },
|
||||
|
||||
{ "copyTop", "CopyTop", XmRBool, sizeof (int),
|
||||
XtOffset (AppArgsPtr, sync.copytop), XmRImmediate, (XtPointer) False, },
|
||||
|
||||
/* other options */
|
||||
|
||||
{ "move", "Move", XmRBoolean, sizeof (Boolean),
|
||||
XtOffset (AppArgsPtr, move), XmRImmediate, (XtPointer) False, },
|
||||
|
||||
{ "confirmReplace", "ConfirmReplace", XmRBoolean, sizeof (Boolean),
|
||||
XtOffset (AppArgsPtr, confirmreplace), XmRImmediate, (XtPointer) False, },
|
||||
|
||||
{ "confirmErrors", "ConfirmErrors", XmRBoolean, sizeof (Boolean),
|
||||
XtOffset (AppArgsPtr, confirmerrors), XmRImmediate, (XtPointer) False, },
|
||||
|
||||
{ "popDown", "PopDown", XmRBoolean, sizeof (Boolean),
|
||||
XtOffset (AppArgsPtr, popdown), XmRImmediate, (XtPointer) False, },
|
||||
|
||||
{ "delay", "Delay", XmRInt, sizeof (int),
|
||||
XtOffset (AppArgsPtr, delay), XmRImmediate, (XtPointer) 5000, }, /* in milliseconds */
|
||||
|
||||
{ "toggle", "Toggle", XmRBoolean, sizeof (Boolean),
|
||||
XtOffset (AppArgsPtr, use_toggle_buttons), XmRImmediate, (XtPointer) True, },
|
||||
{ "slow", "Slow", XmRBoolean, sizeof (Boolean),
|
||||
XtOffset (AppArgsPtr, slow), XmRImmediate, (XtPointer) False, },
|
||||
|
||||
{ "checkPermissions", "CheckPermissions", XmRBoolean, sizeof (Boolean),
|
||||
XtOffset (AppArgsPtr, checkPerms), XmRImmediate, (XtPointer) False, },
|
||||
};
|
||||
|
||||
|
||||
static XrmOptionDescRec option_list[] =
|
||||
{
|
||||
{ "-from", "source", XrmoptionSepArg, NULL },
|
||||
{ "-to", "target", XrmoptionSepArg, NULL },
|
||||
|
||||
{ "-verbose", "verbose", XrmoptionNoArg, "True" },
|
||||
{ "-v", "verbose", XrmoptionNoArg, "True" },
|
||||
{ "-quiet", "quiet", XrmoptionNoArg, "True" },
|
||||
{ "-q", "quiet", XrmoptionNoArg, "True" },
|
||||
{ "-dontDoIt", "dontDoIt", XrmoptionNoArg, "True" },
|
||||
{ "-n", "dontDoIt", XrmoptionNoArg, "True" },
|
||||
|
||||
{ "-keepNew", "keepNew", XrmoptionNoArg, "True" },
|
||||
{ "-kn", "keepNew", XrmoptionNoArg, "True" },
|
||||
{ "-keepOld", "keepOld", XrmoptionSepArg, NULL },
|
||||
{ "-ko", "keepOld", XrmoptionSepArg, NULL },
|
||||
{ "-dontDelete", "dontDelete", XrmoptionNoArg, "True" },
|
||||
{ "-nd", "dontDelete", XrmoptionNoArg, "True" },
|
||||
{ "-dontAdd", "dontAdd", XrmoptionNoArg, "True" },
|
||||
{ "-na", "dontAdd", XrmoptionNoArg, "True" },
|
||||
{ "-dontReplace", "dontReplace", XrmoptionNoArg, "True" },
|
||||
{ "-nr", "dontReplace", XrmoptionNoArg, "True" },
|
||||
{ "-dontRecur", "dontRecur", XrmoptionNoArg, "True" },
|
||||
{ "-nR", "dontRecur", XrmoptionNoArg, "True" },
|
||||
|
||||
{ "-keepLinks", "keepLinks", XrmoptionNoArg, "True" },
|
||||
{ "-kl", "keepLinks", XrmoptionNoArg, "True" },
|
||||
{ "-keepCopies", "keepCopies", XrmoptionNoArg, "True" },
|
||||
{ "-kc", "keepCopies", XrmoptionNoArg, "True" },
|
||||
{ "-forceCopies", "forceCopies", XrmoptionNoArg, "True" },
|
||||
{ "-fc", "forceCopies", XrmoptionNoArg, "True" },
|
||||
{ "-listLinks", "listLinks", XrmoptionNoArg, "True" },
|
||||
{ "-ll", "listLinks", XrmoptionNoArg, "True" },
|
||||
{ "-listCopies", "listCopies", XrmoptionNoArg, "True" },
|
||||
{ "-lc", "listCopies", XrmoptionNoArg, "True" },
|
||||
{ "-linkFolders", "linkFolders", XrmoptionNoArg, "True" },
|
||||
{ "-ld", "linkFolders", XrmoptionNoArg, "True" },
|
||||
{ "-linkFiles", "linkFiles", XrmoptionNoArg, "True" },
|
||||
{ "-lf", "linkFiles", XrmoptionNoArg, "True" },
|
||||
{ "-copyFolders", "copyFolders", XrmoptionNoArg, "True" },
|
||||
{ "-cd", "copyFolders", XrmoptionNoArg, "True" },
|
||||
{ "-copyFiles", "copyFiles", XrmoptionNoArg, "True" },
|
||||
{ "-cf", "copyFiles", XrmoptionNoArg, "True" },
|
||||
{ "-copyTop", "copyTop", XrmoptionNoArg, "True" },
|
||||
{ "-ct", "copyTop", XrmoptionNoArg, "True" },
|
||||
|
||||
{ "-move", "move", XrmoptionNoArg, "True" },
|
||||
{ "-mv", "move", XrmoptionNoArg, "True" },
|
||||
{ "-confirmReplace", "confirmReplace", XrmoptionNoArg, "True" },
|
||||
{ "-cr", "confirmReplace", XrmoptionNoArg, "True" },
|
||||
{ "-confirmErrors", "confirmErrors", XrmoptionNoArg, "True" },
|
||||
{ "-ce", "confirmErrors", XrmoptionNoArg, "True" },
|
||||
{ "-popDown", "popDown", XrmoptionNoArg, "True" },
|
||||
{ "-delay", "delay", XrmoptionSepArg, NULL },
|
||||
{ "-slow", "slow", XrmoptionNoArg, "True" },
|
||||
{ "-toggle", "toggle", XrmoptionNoArg, "True" },
|
||||
{ "-notoggle", "toggle", XrmoptionNoArg, "False" },
|
||||
{ "-checkPerms", "checkPermissions",XrmoptionNoArg, "True" },
|
||||
};
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* display update functions
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
static void
|
||||
UpdateSummary(void)
|
||||
{
|
||||
XmString xs;
|
||||
char msg[1024];
|
||||
char files[128];
|
||||
char dirs[128];
|
||||
int new_nfiles = nfiles, new_ndirs = ndirs;
|
||||
|
||||
if (nfiles == 1)
|
||||
strcpy(files, GETMESSAGE(2, 3, "file"));
|
||||
else
|
||||
strcpy(files, GETMESSAGE(2, 4, "files"));
|
||||
|
||||
if (ndirs == 1)
|
||||
strcpy(dirs, GETMESSAGE(2, 5, "subfolder"));
|
||||
else
|
||||
strcpy(dirs, GETMESSAGE(2, 6, "subfolders"));
|
||||
|
||||
if ( nfiles < 0 )
|
||||
new_nfiles = 0;
|
||||
if ( ndirs < 0 )
|
||||
new_ndirs = 0;
|
||||
sprintf(msg, "%4d %s\n%4d %s", new_nfiles, files, new_ndirs, dirs);
|
||||
|
||||
xs = XmStringCreateLocalized(msg);
|
||||
XtVaSetValues (G_summary_text,
|
||||
XmNlabelString, xs,
|
||||
NULL);
|
||||
XmStringFree(xs);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
UpdateStatus(
|
||||
char *msg1,
|
||||
char *msg2)
|
||||
{
|
||||
|
||||
String msg;
|
||||
String pad;
|
||||
const String ellipsis="...";
|
||||
const int lenEllipsis = 3;
|
||||
int lenSourceDir, lenMsg, lenMsg2, numBlanks;
|
||||
static int maxMsg = -1;
|
||||
|
||||
DPRINTF(("%s %s\n",msg1,msg2));
|
||||
/*
|
||||
XtUnmanageChild(G_status_text2);
|
||||
|
||||
XtVaSetValues (G_status_text,
|
||||
XmNvalue, msg1,
|
||||
XmNcursorPosition, 0,
|
||||
NULL);
|
||||
|
||||
XtVaSetValues (G_status_text2,
|
||||
XmNvalue, msg2,
|
||||
NULL);
|
||||
|
||||
XtManageChild(G_status_text2);
|
||||
|
||||
XtVaSetValues (G_status_text2,
|
||||
XmNcursorPosition, strlen(msg2),
|
||||
NULL);
|
||||
*/
|
||||
|
||||
/* The pathname is truncated, if possible, by replacing */
|
||||
/* the name of the source directory with "...". Thus, */
|
||||
/* when copying /u/joeuser/mydir/myfile, the pathanme */
|
||||
/* is written as .../myfile */
|
||||
|
||||
lenSourceDir = strlen(G_source_dir);
|
||||
lenMsg2 = strlen(msg2);
|
||||
if ( (strncmp(G_source_dir,msg2,lenSourceDir) == 0) &&
|
||||
(lenMsg2 > lenSourceDir) )
|
||||
{
|
||||
msg = XtMalloc(strlen(msg1) + lenEllipsis + (lenMsg2 - lenSourceDir) + 2);
|
||||
sprintf(msg, "%s %s%s", msg1, ellipsis, msg2+lenSourceDir);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg = XtMalloc(strlen(msg1) + lenMsg2 + 2);
|
||||
sprintf(msg, "%s %s", msg1, msg2);
|
||||
}
|
||||
|
||||
/* In order to minimize re-sizing of the dialog, the */
|
||||
/* length of the message is not allowed to decrease. */
|
||||
/* Blanks are added to the end of shorter messages. */
|
||||
|
||||
lenMsg = strlen(msg);
|
||||
maxMsg = (maxMsg > lenMsg) ? maxMsg : lenMsg; /* MAX(maxMsg,lenMsg) */
|
||||
if (lenMsg < maxMsg)
|
||||
{
|
||||
numBlanks = maxMsg - lenMsg;
|
||||
pad = XtMalloc(numBlanks+1);
|
||||
memset(pad,' ',numBlanks);
|
||||
pad[numBlanks] = '\0';
|
||||
msg = XtRealloc(msg,maxMsg+1);
|
||||
strcat(msg,pad);
|
||||
XtFree(pad);
|
||||
}
|
||||
|
||||
|
||||
XmTextFieldSetString(G_status_text, msg);
|
||||
|
||||
XtFree(msg);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
UpdateErrorCount(void)
|
||||
{
|
||||
char msg[128];
|
||||
|
||||
if (nerr == 0)
|
||||
strcpy(msg, GETMESSAGE(2, 7, "Errors: none"));
|
||||
else
|
||||
sprintf(msg, GETMESSAGE(2, 8, "Errors: %d"), nerr);
|
||||
|
||||
/* for the first error, manage the widgets used to display errors */
|
||||
if (nerr == 1)
|
||||
{
|
||||
XtVaSetValues(G_status_text,
|
||||
XmNbottomAttachment, XmATTACH_NONE,
|
||||
NULL);
|
||||
/*
|
||||
XtVaSetValues(G_status_text2,
|
||||
XmNbottomAttachment, XmATTACH_NONE,
|
||||
NULL);
|
||||
*/
|
||||
XtManageChild(G_error_count);
|
||||
XtManageChild(G_error_msgs);
|
||||
XtManageChild(XtParent(G_error_msgs));
|
||||
}
|
||||
|
||||
XtVaSetValues (G_error_count,
|
||||
XmNvalue, msg,
|
||||
XmNcursorPosition, 0,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
AppendErrorMsg(char *msg)
|
||||
{
|
||||
XmTextPosition pos;
|
||||
|
||||
pos = XmTextGetLastPosition (G_error_msgs);
|
||||
XmTextInsert (G_error_msgs, pos, msg);
|
||||
XmTextSetInsertionPosition (G_error_msgs, pos);
|
||||
XmTextShowPosition (G_error_msgs, pos);
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* Callback functions
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
CheckForMap(
|
||||
Widget w,
|
||||
XtPointer client_data,
|
||||
XEvent *event,
|
||||
Boolean *cont)
|
||||
/* set a flag when the main window is mapped */
|
||||
{
|
||||
if (event->type == MapNotify)
|
||||
is_mapped = True;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
EventCheck(void)
|
||||
/* process X events until there are no more pending events queued */
|
||||
{
|
||||
XEvent event;
|
||||
unsigned long pend_result;
|
||||
|
||||
for (;;) {
|
||||
if (!G_pause_copy) {
|
||||
/* check if there are any X events */
|
||||
if (!(XtAppPending(app_context) & XtIMXEvent)) {
|
||||
/* maybe more events are "in the pipe" */
|
||||
XSync(XtDisplay(G_toplevel), False);
|
||||
if (!(XtAppPending(app_context) & XtIMXEvent))
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* get the next event and process it */
|
||||
XtAppNextEvent(app_context, &event);
|
||||
XtDispatchEvent(&event);
|
||||
}
|
||||
|
||||
/* if the user clicked on the Cancel button and Warning 'yes' btn, abort the copy */
|
||||
if (G_do_copy)
|
||||
return 0;
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
ErrorHandler(FileOp op, char *fname, int errnum)
|
||||
{
|
||||
char msg[2048];
|
||||
|
||||
/* increment the error count */
|
||||
nerr++;
|
||||
UpdateErrorCount();
|
||||
|
||||
/* don't count this file as one that has been copied */
|
||||
nfiles--;
|
||||
UpdateSummary();
|
||||
|
||||
/* add error message to error_msgs */
|
||||
sprintf(msg, "%s: %s\n", fname, strerror(errnum));
|
||||
AppendErrorMsg(msg);
|
||||
|
||||
XmUpdateDisplay(G_toplevel);
|
||||
|
||||
/* Initialize the error status variable. It will be set if the user */
|
||||
/* has chosen not to ignore errors */
|
||||
G_error_status = 0;
|
||||
|
||||
if (!G_ignore_errors)
|
||||
{
|
||||
create_error_dialog(G_toplevel, LongFileOpNames[op], fname, errnum);
|
||||
|
||||
G_wait_on_input = TRUE;
|
||||
while (G_wait_on_input)
|
||||
EventCheck();
|
||||
}
|
||||
|
||||
return (G_error_status);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int
|
||||
ConfirmHandler(
|
||||
FileOp op,
|
||||
char *sname,
|
||||
int stype,
|
||||
char *tname,
|
||||
int ttype,
|
||||
char *link)
|
||||
{
|
||||
char msg[1024];
|
||||
Arg args[5];
|
||||
Boolean is_overwrite = False;
|
||||
Boolean overwrite_dialog = False; /* was overwrite dialog invoked? */
|
||||
char *fname;
|
||||
int rc = 0;
|
||||
SyncParams sync;
|
||||
|
||||
/* update copy counts */
|
||||
if (op == op_sync)
|
||||
{
|
||||
ndirs++;
|
||||
strcpy(last_dir, sname);
|
||||
UpdateSummary();
|
||||
}
|
||||
else if (op == op_copy || op == op_cplink || op == op_mklink)
|
||||
{
|
||||
if (ttype != ft_noent)
|
||||
is_overwrite = True;
|
||||
if (!is_overwrite)
|
||||
{
|
||||
nfiles++;
|
||||
UpdateSummary();
|
||||
}
|
||||
}
|
||||
|
||||
/* display a message that tells the user what we are working on */
|
||||
if (op == op_delete || op == op_mkdir)
|
||||
UpdateStatus(LongFileOpNames[op], tname);
|
||||
else
|
||||
UpdateStatus(LongFileOpNames[op], sname);
|
||||
|
||||
XmUpdateDisplay(G_toplevel);
|
||||
|
||||
|
||||
if (is_overwrite) {
|
||||
|
||||
/* target already exists and would be replaced */
|
||||
|
||||
/* if confirmation is turned on, ask the user */
|
||||
/* set overwrite_dialog so we know if the user was prompted for this file */
|
||||
/* Otherwise, G_overwrite_selection is either the default or was set */
|
||||
/* by the user in a prior invocation of the overwrite dialog */
|
||||
if (G_overwrite_confirm)
|
||||
{
|
||||
overwrite_dialog = TRUE;
|
||||
create_overwrite_dialog (G_toplevel, sname, tname, ttype & ft_isdir);
|
||||
|
||||
G_wait_on_input = TRUE;
|
||||
while (G_wait_on_input)
|
||||
EventCheck();
|
||||
|
||||
}
|
||||
|
||||
if (G_overwrite_selection != G_SKIP)
|
||||
{
|
||||
nfiles++;
|
||||
UpdateSummary();
|
||||
XmUpdateDisplay(G_toplevel);
|
||||
}
|
||||
|
||||
switch (G_overwrite_selection)
|
||||
{
|
||||
case G_OVERWRITE_EXISTING:
|
||||
rc = 0;
|
||||
break;
|
||||
|
||||
case G_RENAME_EXISTING: /* i.e. move clashing target */
|
||||
if (!overwrite_dialog)
|
||||
{
|
||||
if (auto_rename(tname) == 0)
|
||||
{
|
||||
touch(tname); /* SyncDirectory complains if the file is gone */
|
||||
rc = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ErrorHandler(op_rename, tname, errno);
|
||||
rc = 1; /* do not do the copy */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case G_SKIP:
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (app_args.slow) {
|
||||
XFlush(XtDisplay(G_toplevel));
|
||||
XSync(XtDisplay(G_toplevel), False);
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* moveDeleteCallback, moveErrorCallback:
|
||||
* called if "-move" option was given, when the
|
||||
* source directory is deleted after a successful copy.
|
||||
*/
|
||||
|
||||
static int
|
||||
moveDeleteCallback(char *fname)
|
||||
{
|
||||
return ConfirmHandler(op_delete, "", ft_noent, fname, 0, "");
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
moveErrorCallback(char *fname, int errnum)
|
||||
{
|
||||
return ErrorHandler(op_delete, fname, errnum);
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* Get command line arguments
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
static int
|
||||
get_command_line(int argc, char *argv[])
|
||||
{
|
||||
int i = 1;
|
||||
|
||||
#define USAGE \
|
||||
"Usage: %s [options ...] source target\n"
|
||||
|
||||
/* get source & target directory, if not yet set */
|
||||
|
||||
if (app_args.source_name == NULL && i < argc)
|
||||
app_args.source_name = argv[i++];
|
||||
|
||||
if (app_args.target_name == NULL && i < argc)
|
||||
app_args.target_name = argv[i++];
|
||||
|
||||
/*
|
||||
* There should be no more arguments left, and
|
||||
* source & target directory should be set
|
||||
*/
|
||||
|
||||
if (i < argc ||
|
||||
app_args.source_name == NULL ||
|
||||
app_args.target_name == NULL)
|
||||
{
|
||||
fprintf(stderr, GETMESSAGE(2, 10, USAGE), argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* Initialize LongFileOpNames by message catalog.
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
static void
|
||||
InitNlsMessage(void)
|
||||
{
|
||||
int i;
|
||||
char *msg;
|
||||
|
||||
for (i = 0; i < FILEOPNUM; i++) {
|
||||
msg = GETMESSAGE(2, i + 20, DefaultLongFileOpNames[i]);
|
||||
LongFileOpNames[i] = XtNewString(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* Main
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
char msg[1024];
|
||||
XEvent event;
|
||||
Arg args[3];
|
||||
int rc, n,perm_status=0;
|
||||
char * tmpStr;
|
||||
|
||||
Boolean copy_status;
|
||||
|
||||
_DtEnvControl(DT_ENV_SET);
|
||||
XtSetLanguageProc(NULL, NULL, NULL);
|
||||
|
||||
/* initialize debugging flag */
|
||||
#ifdef DEBUG
|
||||
if ((tmpStr = getenv("DTFILE_DEBUG")) != NULL)
|
||||
{
|
||||
debug = atoi(tmpStr);
|
||||
if (debug <= 0)
|
||||
debug = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Initialize the toolkit and Open the Display */
|
||||
n=0;
|
||||
XtSetArg (args[n], XmNmappedWhenManaged, FALSE); n++;
|
||||
|
||||
G_toplevel = XtAppInitialize(&app_context,
|
||||
"Dtfile", /* Dtcopy is considered part of Dtfile */
|
||||
option_list, XtNumber(option_list),
|
||||
&argc, argv, NULL, args, n);
|
||||
|
||||
InitNlsMessage();
|
||||
|
||||
XtGetApplicationResources(G_toplevel, &app_args,
|
||||
resources, XtNumber(resources), NULL, 0);
|
||||
|
||||
/* add support for editres debugging tool */
|
||||
/* XtAddEventHandler(G_toplevel, (EventMask) 0, True, _XEditResCheckMessages, NULL); */
|
||||
|
||||
/* Get the source and destination directories */
|
||||
get_command_line(argc,argv);
|
||||
CheckDeleteAccess(app_context,app_args.delay,app_args.checkPerms,
|
||||
app_args.move,app_args.source_name);
|
||||
G_ignore_errors = !app_args.confirmerrors;
|
||||
G_overwrite_confirm = app_args.confirmreplace;
|
||||
G_move = app_args.move;
|
||||
|
||||
/* Set resources for the shell */
|
||||
n = 0;
|
||||
XtSetArg(args[n], XmNallowShellResize, TRUE); n++;
|
||||
if (G_move)
|
||||
{
|
||||
XtSetArg(args[n], XmNtitle, GETMESSAGE(2, 11, "File Manager - Folder Move"));
|
||||
n++;
|
||||
}
|
||||
else
|
||||
{
|
||||
XtSetArg(args[n], XmNtitle, GETMESSAGE(2, 12, "File Manager - Folder Copy"));
|
||||
n++;
|
||||
}
|
||||
|
||||
XtSetValues(G_toplevel, args, n);
|
||||
|
||||
/* Initialize images for error, warning, ... icons */
|
||||
ImageInitialize(XtDisplay(G_toplevel));
|
||||
|
||||
/* Create The Copy Directory Dialog */
|
||||
copy_status = create_copydir_dialog(G_toplevel, app_args.source_name,
|
||||
app_args.target_name);
|
||||
|
||||
if(copy_status == False)
|
||||
{
|
||||
XtRealizeWidget(G_toplevel);
|
||||
XtAppAddTimeOut(app_context, app_args.delay, TimeoutHandler, NULL);
|
||||
|
||||
/* wait for user to close the dialog before exiting */
|
||||
while (!G_dialog_closed)
|
||||
{
|
||||
XtAppNextEvent(app_context, &event);
|
||||
XtDispatchEvent(&event);
|
||||
}
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
/* initialize status, error count, etc ... */
|
||||
sensitize_copy_action_area(G_copy_action_area_pbuttons);
|
||||
nfiles = 0;
|
||||
ndirs = -1; /* -1 so the source folder does not get counted, only subfolders */
|
||||
UpdateSummary();
|
||||
nerr = 0;
|
||||
UpdateErrorCount();
|
||||
|
||||
/* Realize the top level Widget */
|
||||
XtRealizeWidget(G_toplevel);
|
||||
XtMapWidget(G_toplevel);
|
||||
|
||||
/*
|
||||
* Wait for the top level Widget to be mapped.
|
||||
* Reason: The routine for selecting a window position for popup windows
|
||||
* (error and overwrite warning dialogs) won't work until the main window
|
||||
* is mapped. Therefore, we don't want to start the actual copy operation
|
||||
* (which might generate error or warning messages) before the main window
|
||||
* is mapped.
|
||||
*/
|
||||
XtAddEventHandler(G_toplevel, StructureNotifyMask, False, CheckForMap, NULL);
|
||||
while (!is_mapped)
|
||||
EventCheck();
|
||||
XtRemoveEventHandler(G_toplevel, XtAllEvents, True, CheckForMap, NULL);
|
||||
|
||||
/* Set up the Callbacks for the copy operation */
|
||||
periodicCallback = EventCheck;
|
||||
syncConfirmCallback = ConfirmHandler;
|
||||
syncErrorCallback = ErrorHandler;
|
||||
|
||||
/* set up parameters for the copy operation */
|
||||
app_args.sync.source = app_args.source_name; /* source directory */
|
||||
app_args.sync.target = app_args.target_name; /* target directory */
|
||||
app_args.sync.verbose++;
|
||||
strcpy(last_dir, app_args.sync.source);
|
||||
|
||||
/*
|
||||
* Call the Copy Function. This copy function will look at the
|
||||
* even queue and see if there are any pending events. If so,
|
||||
* it will dispatch these events and then resume the copy
|
||||
* operation. The function will return after the copy operation
|
||||
* has completed or when the user aborts the operation by
|
||||
* clicking the "Cancel" button.
|
||||
*/
|
||||
SyncDirectory(&app_args.sync);
|
||||
|
||||
/* if move was requested and the copy was successful, delete the source now */
|
||||
if (G_move)
|
||||
{
|
||||
if (nerr > 0)
|
||||
{
|
||||
sprintf(msg, GETMESSAGE(2, 13, "%s not removed because of errors."),
|
||||
app_args.sync.source);
|
||||
AppendErrorMsg(msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* arrange for callback's during recursive directory delete */
|
||||
progressCallback = moveDeleteCallback;
|
||||
errorCallback = moveErrorCallback;
|
||||
|
||||
/* delete the source directory */
|
||||
fsErase(app_args.sync.source, &rc, True);
|
||||
}
|
||||
}
|
||||
|
||||
/* display the result */
|
||||
if (G_do_copy)
|
||||
UpdateStatus(GETMESSAGE(2, 14, "Completed."), "");
|
||||
else
|
||||
UpdateStatus(GETMESSAGE(2, 15, "Cancelled in"), last_dir);
|
||||
|
||||
XtVaSetValues (G_error_msgs,
|
||||
XmNcursorPosition, 0,
|
||||
XmNtopCharacter, 0,
|
||||
NULL);
|
||||
|
||||
/* desensitize the copy area */
|
||||
desensitize_copy_action_area(G_copy_action_area_pbuttons);
|
||||
|
||||
/* if successful popdown the window after a delay */
|
||||
if (app_args.popdown && nerr == 0)
|
||||
XtAppAddTimeOut(app_context, app_args.delay, TimeoutHandler, NULL);
|
||||
|
||||
/* wait for user to close the dialog before exiting */
|
||||
while (!G_dialog_closed)
|
||||
{
|
||||
XtAppNextEvent(app_context, &event);
|
||||
XtDispatchEvent(&event);
|
||||
}
|
||||
|
||||
exit(nerr);
|
||||
}
|
||||
|
||||
2
cde/programs/dtfile/dtcopy/nmrtns.h
Normal file
2
cde/programs/dtfile/dtcopy/nmrtns.h
Normal file
@@ -0,0 +1,2 @@
|
||||
/* $XConsortium: nmrtns.h /main/3 1995/11/02 14:48:07 rswiston $ */
|
||||
#error "obsolete file"
|
||||
490
cde/programs/dtfile/dtcopy/overwrtdialog.c
Normal file
490
cde/programs/dtfile/dtcopy/overwrtdialog.c
Normal file
@@ -0,0 +1,490 @@
|
||||
/* $XConsortium: overwrtdialog.c /main/5 1996/10/17 09:36:29 mustafa $ */
|
||||
/************************************<+>*************************************
|
||||
****************************************************************************
|
||||
*
|
||||
* FILE: overwrtdialog.c
|
||||
*
|
||||
*
|
||||
* DESCRIPTION: Routines to handle dialog for collision operations
|
||||
*
|
||||
* FUNCTIONS: confirmtoggle_callback
|
||||
* create_overwrite_dialog
|
||||
* ok_callback
|
||||
* overwrite_cancel_callback
|
||||
* radio_callback
|
||||
* renameError_ok_callback
|
||||
* touch
|
||||
*
|
||||
* (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
|
||||
* (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
|
||||
* (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
|
||||
* (c) Copyright 1993, 1994, 1995 Novell, Inc.
|
||||
*
|
||||
****************************************************************************
|
||||
************************************<+>*************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <sys/wait.h>
|
||||
#include <time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <X11/Intrinsic.h>
|
||||
#include <X11/StringDefs.h>
|
||||
#include <Xm/XmP.h>
|
||||
#include <Xm/Xm.h>
|
||||
#include <Xm/PushB.h>
|
||||
#include <Xm/DialogS.h>
|
||||
#include <Xm/Form.h>
|
||||
#include <Xm/Frame.h>
|
||||
#include <Xm/BulletinB.h>
|
||||
#include <Xm/Label.h>
|
||||
#include <Xm/Text.h>
|
||||
#include <Xm/TextF.h>
|
||||
#include <Xm/ToggleB.h>
|
||||
#include <Xm/MessageB.h>
|
||||
#include <Xm/Separator.h>
|
||||
|
||||
#include "dtcopy.h"
|
||||
#include "sharedFuncs.h"
|
||||
|
||||
#define VERTICAL_SPACING 5
|
||||
#define HORIZONTAL_SPACING 10
|
||||
#define TOP_SPACING (VERTICAL_SPACING + 3)
|
||||
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* Callback routines
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
static void
|
||||
radio_callback(
|
||||
Widget w,
|
||||
XtPointer client_data,
|
||||
XtPointer call_data)
|
||||
{
|
||||
XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)call_data;
|
||||
|
||||
|
||||
G_overwrite_selection = (int) client_data;
|
||||
|
||||
if (state->set)
|
||||
switch (G_overwrite_selection)
|
||||
{
|
||||
case G_OVERWRITE_EXISTING:
|
||||
XtVaSetValues (G_rename_text,
|
||||
XmNsensitive, FALSE,
|
||||
NULL);
|
||||
break;
|
||||
|
||||
case G_SKIP:
|
||||
XtVaSetValues (G_rename_text,
|
||||
XmNsensitive, FALSE,
|
||||
NULL);
|
||||
break;
|
||||
|
||||
case G_RENAME_EXISTING:
|
||||
XtVaSetValues (G_rename_text,
|
||||
XmNsensitive, TRUE,
|
||||
NULL);
|
||||
XmProcessTraversal(G_rename_text, XmTRAVERSE_CURRENT);
|
||||
break;
|
||||
|
||||
|
||||
} /* end switch */
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
renameError_ok_callback(
|
||||
Widget w,
|
||||
XtPointer client_data,
|
||||
XtPointer call_data)
|
||||
{
|
||||
XtDestroyWidget((Widget)client_data);
|
||||
XmProcessTraversal(G_rename_text, XmTRAVERSE_CURRENT);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ok_callback(
|
||||
Widget w,
|
||||
XtPointer client_data,
|
||||
XtPointer call_data)
|
||||
{
|
||||
struct stat buf;
|
||||
char msg[128];
|
||||
int saveError=0;
|
||||
String title;
|
||||
char tfolder[MAX_PATH], tobject[MAX_PATH];
|
||||
char *newObject, *renameNewName;
|
||||
|
||||
switch (G_overwrite_selection)
|
||||
{
|
||||
case G_OVERWRITE_EXISTING:
|
||||
case G_SKIP:
|
||||
break;
|
||||
|
||||
case G_RENAME_EXISTING:
|
||||
/* get object (i.e. file) name from text field and build the complete path */
|
||||
/* this procedure restricts renaming to be within a folder (directory) */
|
||||
split_path(G_rename_oldname,tfolder,tobject);
|
||||
newObject = XmTextFieldGetString(G_rename_text);
|
||||
renameNewName = build_path(tfolder,newObject);
|
||||
XtFree(newObject);
|
||||
|
||||
/* make sure renameNewName does not exist */
|
||||
if ( (lstat(renameNewName, &buf)) == 0)
|
||||
{
|
||||
title = GETMESSAGE(5, 11, "File Overwrite - Error");
|
||||
sprintf(msg,
|
||||
GETMESSAGE(5, 10, "%s\nalready exists: choose another name."),
|
||||
renameNewName);
|
||||
_DtMessageDialog (G_over_dialog, title, msg, 0, FALSE, NULL,
|
||||
renameError_ok_callback, NULL, NULL, False, ERROR_DIALOG);
|
||||
free(renameNewName);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
/* attempt the rename ... since rename function is being used, this */
|
||||
/* only allows renames within the same filesystem */
|
||||
errno = 0;
|
||||
if ( rename(G_rename_oldname, renameNewName) != 0)
|
||||
{
|
||||
saveError = errno;
|
||||
title = GETMESSAGE(5, 11, "File Overwrite - Error");
|
||||
sprintf(msg,
|
||||
GETMESSAGE(5, 10, "%s\ncannot be renamed to\n%s\n%s"),
|
||||
G_rename_oldname, renameNewName, strerror(saveError));
|
||||
_DtMessageDialog (G_over_dialog, title, msg, 0, FALSE, NULL,
|
||||
renameError_ok_callback, NULL, NULL, False, ERROR_DIALOG);
|
||||
free(renameNewName);
|
||||
return;
|
||||
|
||||
}
|
||||
/* the rename went ok ... create an empty file so SyncDirectory doesn't */
|
||||
/* generate an error trying to delete G_rename_oldname */
|
||||
else
|
||||
{
|
||||
free(renameNewName);
|
||||
touch(G_rename_oldname);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
XtDestroyWidget(G_over_dialog);
|
||||
G_over_dialog = NULL;
|
||||
G_wait_on_input = FALSE;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
confirmtoggle_callback(
|
||||
Widget w,
|
||||
XtPointer client_data,
|
||||
XtPointer call_data)
|
||||
{
|
||||
G_overwrite_confirm = !G_overwrite_confirm;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
overwrite_cancel_callback(
|
||||
Widget w,
|
||||
XtPointer client_data,
|
||||
XtPointer call_data)
|
||||
{
|
||||
display_cancel_warning(G_over_dialog);
|
||||
|
||||
G_pause_copy = TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* create overwrite dialog
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
create_overwrite_dialog(
|
||||
Widget parent_widget,
|
||||
char *sname,
|
||||
char *tname,
|
||||
Boolean isdir)
|
||||
{
|
||||
char buf[2048];
|
||||
char tfolder[MAX_PATH], tobject[MAX_PATH]; /* t for target */
|
||||
char gname[MAX_PATH], gfolder[MAX_PATH], gobject[MAX_PATH]; /* g for generated */
|
||||
|
||||
Arg args[10];
|
||||
int n =0;
|
||||
int i;
|
||||
XmString msg;
|
||||
XmString xm_string[N_OVERWRITE_RADIO_BUTTONS];
|
||||
Widget radiobtn[N_OVERWRITE_RADIO_BUTTONS];
|
||||
Widget form, outerFrame;
|
||||
Widget action_label, icon, action_area, separator, msg_label;
|
||||
Pixel background, foreground;
|
||||
Pixmap px;
|
||||
Position x, y;
|
||||
|
||||
static ActionAreaItem action_items[] = {
|
||||
{"Ok", 6, 1, ok_callback, NULL},
|
||||
{"Cancel Copy", 6, 7, overwrite_cancel_callback, NULL}, /* possibly changed below to "Cancel Move" */
|
||||
{"Help", 6, 4, help_callback, (XtPointer) HELP_OVERWRITE},
|
||||
};
|
||||
|
||||
ActionAreaDefn overwriteActions = {
|
||||
XtNumber(action_items),
|
||||
0, /* Ok is default action */
|
||||
action_items
|
||||
};
|
||||
|
||||
|
||||
/* save the target name for possible rename in ok_callback */
|
||||
strcpy(G_rename_oldname,tname);
|
||||
|
||||
|
||||
if (G_move)
|
||||
{
|
||||
action_items[2].label = "Cancel Move";
|
||||
action_items[2].msg_num = 8;
|
||||
}
|
||||
|
||||
/* Create the dialog shell for the dialog */
|
||||
n = 0;
|
||||
XtSetArg (args[n], XmNallowShellResize, True); n++;
|
||||
XtSetArg (args[n], XmNmappedWhenManaged, FALSE); n++;
|
||||
if (G_move)
|
||||
{
|
||||
XtSetArg (args[n], XmNtitle, GETMESSAGE(5, 2, "Folder Move - File Overwrite"));
|
||||
n++;
|
||||
}
|
||||
else
|
||||
{
|
||||
XtSetArg (args[n], XmNtitle, GETMESSAGE(5, 9, "Folder Copy - File Overwrite"));
|
||||
n++;
|
||||
}
|
||||
G_over_dialog = XmCreateDialogShell (parent_widget, "dialog_shell", args, n);
|
||||
|
||||
/* create a frame around the dialog for better separation from window border */
|
||||
outerFrame = XtVaCreateWidget("outerFrame",
|
||||
xmFrameWidgetClass,
|
||||
G_over_dialog,
|
||||
XmNshadowThickness, 3,
|
||||
XmNshadowType, XmSHADOW_ETCHED_IN,
|
||||
NULL);
|
||||
|
||||
/* Create the Manager Widget, form, for the copy dialog */
|
||||
form = XtVaCreateWidget ("dialog_form",
|
||||
xmFormWidgetClass,
|
||||
outerFrame,
|
||||
XmNverticalSpacing, VERTICAL_SPACING,
|
||||
XmNhorizontalSpacing, HORIZONTAL_SPACING,
|
||||
NULL);
|
||||
|
||||
/* Create a question dialog icon */
|
||||
n = 0;
|
||||
XtSetArg (args[n], XmNbackground, &background); n++;
|
||||
XtSetArg (args[n], XmNforeground, &foreground); n++;
|
||||
XtGetValues (form, args, n);
|
||||
|
||||
px = XmGetPixmapByDepth(XtScreen(form), "xm_question",
|
||||
foreground, background, form->core.depth);
|
||||
if (px == XmUNSPECIFIED_PIXMAP)
|
||||
px = XmGetPixmapByDepth(XtScreen(form), "default_xm_question",
|
||||
foreground, background, form->core.depth);
|
||||
|
||||
icon = XtVaCreateManagedWidget("question_icon",
|
||||
xmLabelWidgetClass,
|
||||
form,
|
||||
XmNlabelType, XmPIXMAP,
|
||||
XmNlabelPixmap, px,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
NULL);
|
||||
|
||||
/* Create the message label */
|
||||
split_path(tname,tfolder,tobject);
|
||||
sprintf(buf,
|
||||
GETMESSAGE(5, 1, "A file named\n%s\nalready exists inside the folder\n%s"),
|
||||
tobject, tfolder);
|
||||
msg = XmStringCreateLocalized(buf);
|
||||
msg_label = XtVaCreateManagedWidget("msg_header",
|
||||
xmLabelWidgetClass,
|
||||
form,
|
||||
XmNlabelString, msg,
|
||||
XmNalignment, XmALIGNMENT_BEGINNING,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_WIDGET,
|
||||
XmNleftWidget, icon,
|
||||
XmNleftOffset, HORIZONTAL_SPACING,
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
NULL);
|
||||
XmStringFree(msg);
|
||||
|
||||
|
||||
/* create the action-question */
|
||||
msg = XmStringCreateLocalized(GETMESSAGE(5, 8, "Action to take:"));
|
||||
action_label = XtVaCreateManagedWidget("action-question",
|
||||
xmLabelWidgetClass,
|
||||
form,
|
||||
XmNlabelString, msg,
|
||||
XmNalignment, XmALIGNMENT_BEGINNING,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, msg_label,
|
||||
XmNtopOffset, 2*VERTICAL_SPACING,
|
||||
XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||||
XmNleftWidget, msg_label,
|
||||
NULL);
|
||||
XmStringFree(msg);
|
||||
|
||||
|
||||
/* create radio box */
|
||||
|
||||
n = 0;
|
||||
XtSetArg (args[n], XmNorientation, XmVERTICAL); n++;
|
||||
XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
|
||||
XtSetArg (args[n], XmNtopWidget, action_label); n++;
|
||||
XtSetArg (args[n], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET); n++;
|
||||
XtSetArg (args[n], XmNleftWidget, action_label); n++;
|
||||
XtSetArg (args[n], XmNleftOffset, 2*HORIZONTAL_SPACING); n++;
|
||||
G_overwrite_radio = (Widget) XmCreateRadioBox(form, "radio_box", args, n);
|
||||
|
||||
/* create the radio buttons */
|
||||
xm_string[G_OVERWRITE_EXISTING] = XmStringCreateLocalized(
|
||||
GETMESSAGE(5, 3, "Replace existing file"));
|
||||
xm_string[G_RENAME_EXISTING] = XmStringCreateLocalized(
|
||||
GETMESSAGE(5, 4, "Rename existing file to:"));
|
||||
xm_string[G_SKIP] = XmStringCreateLocalized(
|
||||
GETMESSAGE(5, 6, "Skip this file"));
|
||||
|
||||
|
||||
for (i=0; i < N_OVERWRITE_RADIO_BUTTONS ;i++ )
|
||||
{
|
||||
|
||||
radiobtn[i] = XtVaCreateManagedWidget("radio_toggle",
|
||||
xmToggleButtonWidgetClass, G_overwrite_radio,
|
||||
XmNalignment, XmALIGNMENT_BEGINNING,
|
||||
XmNlabelString, xm_string[i],
|
||||
NULL);
|
||||
XtAddCallback(radiobtn[i], XmNvalueChangedCallback, radio_callback, (XtPointer) i);
|
||||
XmStringFree(xm_string[i]);
|
||||
}
|
||||
|
||||
/* initially set replace-file radio button to TRUE */
|
||||
G_overwrite_selection = G_OVERWRITE_EXISTING;
|
||||
n=0;
|
||||
XtSetArg (args[n], XmNset, TRUE); n++;
|
||||
XtSetValues(radiobtn[G_overwrite_selection], args, n);
|
||||
|
||||
/* create text field for entering a new file name */
|
||||
generate_NewPath(gname,tname);
|
||||
split_path(gname,gfolder,gobject);
|
||||
G_rename_text = XtVaCreateManagedWidget("rename_text",
|
||||
xmTextFieldWidgetClass,
|
||||
form,
|
||||
XmNleftAttachment, XmATTACH_WIDGET,
|
||||
XmNleftWidget, G_overwrite_radio,
|
||||
XmNleftOffset, HORIZONTAL_SPACING,
|
||||
XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||||
XmNbottomWidget, G_overwrite_radio,
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
XmNrightOffset, 5,
|
||||
XmNvalue, gobject,
|
||||
XmNsensitive, FALSE,
|
||||
XmNcursorPosition, strlen(gobject),
|
||||
NULL);
|
||||
|
||||
|
||||
/* create the toggle button */
|
||||
msg = XmStringCreateLocalized(GETMESSAGE(5, 7, "Apply this action to subsequent name conflicts"));
|
||||
G_over_confirm = XtVaCreateManagedWidget("over_confirm",
|
||||
xmToggleButtonWidgetClass,
|
||||
form,
|
||||
XmNlabelString, msg,
|
||||
XmNset, !G_overwrite_confirm,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, G_overwrite_radio,
|
||||
XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET,
|
||||
XmNleftWidget, action_label,
|
||||
XmNleftOffset, 0,
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
XmNalignment, XmALIGNMENT_BEGINNING,
|
||||
NULL);
|
||||
XtAddCallback(G_over_confirm, XmNvalueChangedCallback, confirmtoggle_callback, NULL);
|
||||
XmStringFree(msg);
|
||||
|
||||
/* create the action area of the Copy Directory Dialog */
|
||||
action_area = Create_Action_Area(form, overwriteActions, NULL);
|
||||
separator = XtVaCreateManagedWidget("separator",
|
||||
xmSeparatorWidgetClass,
|
||||
form,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, G_over_confirm,
|
||||
XmNbottomAttachment, XmATTACH_WIDGET,
|
||||
XmNbottomWidget, action_area,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
NULL);
|
||||
|
||||
|
||||
/* set initial keyborad focus to the action button area */
|
||||
XtSetArg (args[0], XmNinitialFocus, action_area);
|
||||
XtSetValues(form, args, 1);
|
||||
|
||||
/* Manage the overwrite Directory Dialog */
|
||||
XtManageChild(G_overwrite_radio);
|
||||
XtManageChild(form);
|
||||
XtManageChild(outerFrame);
|
||||
|
||||
/* Choose a window position */
|
||||
_DtChildPosition(G_over_dialog, parent_widget, &x, &y);
|
||||
n=0;
|
||||
XtSetArg (args[n], XmNx, x); n++;
|
||||
XtSetArg (args[n], XmNy, y); n++;
|
||||
XtSetValues(G_over_dialog, args, n);
|
||||
|
||||
/* Now that we have a window postion, map the dialog shell */
|
||||
XtMapWidget(G_over_dialog);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------
|
||||
*
|
||||
* touch
|
||||
*
|
||||
* create an empty file "path"
|
||||
*
|
||||
* return 0 if ok
|
||||
* return EOF and set errno if error
|
||||
*
|
||||
*------------------------------------*/
|
||||
|
||||
int
|
||||
touch(String path)
|
||||
|
||||
{
|
||||
|
||||
FILE *stream;
|
||||
|
||||
errno = 0;
|
||||
if ( ( stream = fopen(path, "w") ) == NULL)
|
||||
return ( EOF );
|
||||
|
||||
return ( fclose (stream) );
|
||||
|
||||
} /* end touch */
|
||||
770
cde/programs/dtfile/dtcopy/sharedFuncs.c
Normal file
770
cde/programs/dtfile/dtcopy/sharedFuncs.c
Normal file
@@ -0,0 +1,770 @@
|
||||
/* $TOG: sharedFuncs.c /main/9 1998/04/06 13:15:57 mgreess $ */
|
||||
/************************************<+>*************************************
|
||||
****************************************************************************
|
||||
*
|
||||
* FILE: sharedFuncs.c
|
||||
*
|
||||
*
|
||||
* DESCRIPTION: Common functions for both dtfile and dtfile_copy
|
||||
*
|
||||
* FUNCTIONS: CreateDefaultImage
|
||||
* ImageInitialize
|
||||
* auto_rename
|
||||
* build_path
|
||||
* generate_NewPath
|
||||
* split_path
|
||||
*
|
||||
* (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
|
||||
* (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
|
||||
* (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
|
||||
* (c) Copyright 1993, 1994, 1995 Novell, Inc.
|
||||
*
|
||||
****************************************************************************
|
||||
************************************<+>*************************************/
|
||||
|
||||
#if defined(SVR4) || defined(sco)
|
||||
|
||||
#if defined(USL) || defined(sco) || defined(__uxp__)
|
||||
# include <sys/param.h>
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
#ifdef sco
|
||||
# include <sys/fs/s5param.h>
|
||||
# define ROOTINO S5ROOTINO
|
||||
#else
|
||||
# include <sys/fs/ufs_fs.h>
|
||||
# define ROOTINO UFSROOTINO
|
||||
#endif /* ! sco */
|
||||
#endif /* SVR4 || sco */
|
||||
|
||||
#if defined(DEC)
|
||||
# include <rpc/key_prot.h>
|
||||
# define ROOTINO PROOT
|
||||
#endif
|
||||
|
||||
#if defined(__uxp__)
|
||||
# include <sys/fs/ufs_fs.h>
|
||||
# define ROOTINO UFSROOTINO
|
||||
#endif
|
||||
|
||||
#if defined(linux)
|
||||
# include <sys/param.h>
|
||||
# define ROOTINO 2
|
||||
#endif
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
#include <fcntl.h>
|
||||
#include <ustat.h>
|
||||
#include <dirent.h>
|
||||
|
||||
|
||||
#include <Xm/Xm.h>
|
||||
|
||||
#include <Xm/Form.h>
|
||||
#include <Xm/PushB.h>
|
||||
|
||||
#include <Dt/Connect.h>
|
||||
#include <Dt/DtNlUtils.h>
|
||||
|
||||
#include "sharedFuncs.h"
|
||||
#include "dtcopy.h"
|
||||
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* Bitmap Data for Default Symbol
|
||||
**********************************<->***********************************/
|
||||
|
||||
static unsigned char errorBits[] = {
|
||||
0x00, 0x00, 0x00, 0xc0, 0x0f, 0x00, 0xf0, 0x3a, 0x00, 0x58, 0x55, 0x00,
|
||||
0x2c, 0xa0, 0x00, 0x56, 0x40, 0x01, 0xaa, 0x80, 0x02, 0x46, 0x81, 0x01,
|
||||
0x8a, 0x82, 0x02, 0x06, 0x85, 0x01, 0x0a, 0x8a, 0x02, 0x06, 0x94, 0x01,
|
||||
0x0a, 0xe8, 0x02, 0x14, 0x50, 0x01, 0x28, 0xb0, 0x00, 0xd0, 0x5f, 0x00,
|
||||
0xa0, 0x2a, 0x00, 0x40, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
static unsigned char infoBits[] = {
|
||||
0x00, 0x00, 0x78, 0x00, 0x54, 0x00, 0x2c, 0x00, 0x54, 0x00, 0x28, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x2a, 0x00, 0x5c, 0x00, 0x28, 0x00,
|
||||
0x58, 0x00, 0x28, 0x00, 0x58, 0x00, 0x28, 0x00, 0x58, 0x00, 0x28, 0x00,
|
||||
0x58, 0x00, 0xae, 0x01, 0x56, 0x01, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
static unsigned char questionBits[] = {
|
||||
0xf0, 0x3f, 0x00, 0x58, 0x55, 0x00, 0xac, 0xaa, 0x00, 0xd6, 0x5f, 0x01,
|
||||
0xea, 0xbf, 0x02, 0xf6, 0x7f, 0x01, 0xea, 0xba, 0x02, 0xf6, 0x7d, 0x05,
|
||||
0xea, 0xba, 0x0a, 0x56, 0x7d, 0x15, 0xaa, 0xbe, 0x1e, 0x56, 0x5f, 0x01,
|
||||
0xac, 0xaf, 0x02, 0x58, 0x57, 0x01, 0xb0, 0xaf, 0x00, 0x60, 0x55, 0x01,
|
||||
0xa0, 0xaa, 0x00, 0x60, 0x17, 0x00, 0xa0, 0x2f, 0x00, 0x60, 0x17, 0x00,
|
||||
0xb0, 0x2a, 0x00, 0x50, 0x55, 0x00};
|
||||
|
||||
static unsigned char warningBits[] = {
|
||||
0x00, 0x00, 0x18, 0x00, 0x2c, 0x00, 0x56, 0x00, 0x2a, 0x00, 0x56, 0x00,
|
||||
0x2a, 0x00, 0x56, 0x00, 0x2c, 0x00, 0x14, 0x00, 0x2c, 0x00, 0x14, 0x00,
|
||||
0x2c, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x14, 0x00,
|
||||
0x2c, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
static unsigned char workingBits[] = {
|
||||
0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0xaa, 0xaa, 0x0a, 0x44, 0x55, 0x06,
|
||||
0xcc, 0x2a, 0x02, 0x44, 0x55, 0x06, 0xcc, 0x2a, 0x02, 0x84, 0x15, 0x06,
|
||||
0x8c, 0x2a, 0x02, 0x04, 0x15, 0x06, 0x0c, 0x0a, 0x02, 0x04, 0x06, 0x06,
|
||||
0x0c, 0x0b, 0x02, 0x84, 0x15, 0x06, 0xcc, 0x2a, 0x02, 0x44, 0x55, 0x06,
|
||||
0xcc, 0x2a, 0x02, 0x44, 0x55, 0x06, 0xcc, 0x2a, 0x02, 0x44, 0x55, 0x06,
|
||||
0xfe, 0xff, 0x0f, 0x56, 0x55, 0x05, 0x00, 0x00, 0x00};
|
||||
|
||||
Widget G_toplevel;
|
||||
int G_dialog_closed = FALSE;
|
||||
|
||||
/*----------------------------------------------------------
|
||||
*
|
||||
* split_path
|
||||
*
|
||||
* Given a path, return a pointer to the directory (folder)
|
||||
* and file (object). On error, both will be set to empty
|
||||
* strings.
|
||||
*
|
||||
* The calling routine is responsible for allocating space
|
||||
* for object and folder.
|
||||
*
|
||||
* This function simply searches for the last slash (/) in
|
||||
* the path and returns the characters preceeding the slash
|
||||
* as folder and the characters after the last slash as
|
||||
* object. Thus, object could be a directory/folder or a
|
||||
* file.
|
||||
*
|
||||
* There is a complimentary function, build_path, to put
|
||||
* object and folder back together to form a path.
|
||||
*
|
||||
*-----------------------------------------------------------*/
|
||||
|
||||
void
|
||||
split_path(const String path, String folder, String object)
|
||||
|
||||
{
|
||||
|
||||
String lastSlash;
|
||||
|
||||
if ( (lastSlash = strrchr(path,'/')) != NULL)
|
||||
{
|
||||
strcpy(object,lastSlash+1);
|
||||
if(lastSlash == path) /* Must be root Folder */
|
||||
strcpy(folder,"/");
|
||||
else
|
||||
{
|
||||
*lastSlash = '\0';
|
||||
strcpy(folder,path);
|
||||
*lastSlash = '/';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
folder[0] = object[0] = '\0';
|
||||
}
|
||||
} /* end split_path */
|
||||
|
||||
char *
|
||||
get_path(char *path)
|
||||
{
|
||||
char *rpath, tmppath[MAX_PATH];
|
||||
char * _DtCopyPathFromInput();
|
||||
getcwd(tmppath,MAX_PATH);
|
||||
rpath = _DtCopyPathFromInput(path,tmppath);
|
||||
return rpath;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
*
|
||||
* build_path
|
||||
*
|
||||
* Given a directory (folder) and file (object), build a string
|
||||
* with the complete path and return it.
|
||||
*
|
||||
* The calling routine is responsible for freeing storage used
|
||||
* for the returned string.
|
||||
*
|
||||
* There is a complimentary function, split_path, to take
|
||||
* path apart to form folder and object
|
||||
*
|
||||
*-----------------------------------------------------------------*/
|
||||
|
||||
String
|
||||
build_path(const String folder, const String object)
|
||||
|
||||
{
|
||||
char s[MAX_PATH];
|
||||
String path;
|
||||
|
||||
strncpy(s, folder, MAX_PATH);
|
||||
strncat(s, "/", MAX_PATH-strlen(s));
|
||||
strncat(s, object, MAX_PATH-strlen(s));
|
||||
path = (String) malloc(strlen(s)+1);
|
||||
strcpy(path,s);
|
||||
|
||||
return path;
|
||||
|
||||
} /* end build_path */
|
||||
|
||||
|
||||
|
||||
/*--------------------------------------------------------------
|
||||
*
|
||||
* auto_rename
|
||||
*
|
||||
* Given a path, generate a new file name and rename the file.
|
||||
*
|
||||
* The rc from the system call is returned and errno is set.
|
||||
*
|
||||
*--------------------------------------------------------------*/
|
||||
|
||||
int
|
||||
auto_rename(const String path)
|
||||
|
||||
{
|
||||
char newPath[MAX_PATH];
|
||||
|
||||
generate_NewPath(newPath,path);
|
||||
errno = 0;
|
||||
return (rename(path,newPath));
|
||||
|
||||
} /* end auto_rename */
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
*
|
||||
* generate_NewPath
|
||||
*
|
||||
* Given a path (and a complete path is required), append a
|
||||
* sequence number to generate a new file name. The new file
|
||||
* will not exist. The sequence number consists of a one-character
|
||||
* delimiter and an integer. The function will start with
|
||||
* 1, if the file with 1 exists it will continue to 2, etc.
|
||||
* newPath and oldPath can point to the same area. The sequence number
|
||||
* is appended to the end of the name unless it contains a
|
||||
* dot, in which case the sequence number precedes the dot. For example,
|
||||
* /cde/dtfile/dtcopy/overwrtdialog.c becomes
|
||||
* /cde/dtfile/dtcopy/overwrtdialog~1.c. However, if the dot
|
||||
* is the first character in the file name, the sequence number is
|
||||
* appended, (e.g. .profile --> .profile~1).
|
||||
*
|
||||
*-----------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
generate_NewPath(String newPath, String oldPath)
|
||||
|
||||
{
|
||||
|
||||
const char delim = '_';
|
||||
|
||||
struct stat buf;
|
||||
String lastDot, lastSlash;
|
||||
char firstPart[MAX_PATH], lastPart[MAX_PATH];
|
||||
int i = 0;
|
||||
int len;
|
||||
|
||||
|
||||
lastDot = strrchr(oldPath,'.');
|
||||
lastSlash = strrchr(oldPath,'/');
|
||||
if (lastSlash == NULL)
|
||||
lastSlash = oldPath - 1; /* allows for no path and first char is dot */
|
||||
len = lastDot - oldPath;
|
||||
if ( lastDot != NULL && /* no dot */
|
||||
lastDot > lastSlash+1 && /* dot is in filename, not directory name */
|
||||
len != strlen(oldPath)-1 ) /* dot is not last character of filename */
|
||||
{
|
||||
/* sequence number will be inserted before filename suffix */
|
||||
memcpy(firstPart,oldPath,len);
|
||||
firstPart[len] = '\0';
|
||||
strcpy(lastPart,lastDot);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* sequence number will be appended to filename */
|
||||
strcpy(firstPart,oldPath);
|
||||
lastPart[0] = '\0';
|
||||
}
|
||||
|
||||
|
||||
do
|
||||
{
|
||||
i++;
|
||||
sprintf(newPath,"%s%c%d%s",firstPart,delim,i,lastPart);
|
||||
} while (lstat(newPath,&buf) == 0);
|
||||
|
||||
return;
|
||||
|
||||
|
||||
} /* end generate_NewPath */
|
||||
|
||||
|
||||
/****************************************************************
|
||||
* Create a default images for symbol... used in ClassInitialize.
|
||||
****************/
|
||||
|
||||
XImage *
|
||||
CreateDefaultImage(
|
||||
Display *display,
|
||||
char *bits,
|
||||
unsigned int width,
|
||||
unsigned int height )
|
||||
{
|
||||
XImage *image ;
|
||||
|
||||
image = XCreateImage(display,
|
||||
DefaultVisual(display, DefaultScreen(display)),
|
||||
1, XYBitmap, 0, bits, width, height, 8,
|
||||
(width+7) >> 3);
|
||||
image->byte_order = LSBFirst;
|
||||
image->bitmap_unit = 8;
|
||||
image->bitmap_bit_order = LSBFirst;
|
||||
|
||||
return( image) ;
|
||||
} /* end CreateDefaultImage */
|
||||
|
||||
|
||||
|
||||
void
|
||||
ImageInitialize( Display *display )
|
||||
{
|
||||
XImage *image;
|
||||
|
||||
/* create and install the default images for the symbol */
|
||||
|
||||
image = CreateDefaultImage (display, (char *)errorBits, 20, 20);
|
||||
XmInstallImage (image, "default_xm_error");
|
||||
|
||||
image = CreateDefaultImage (display, (char *)infoBits, 11, 24);
|
||||
XmInstallImage (image, "default_xm_information");
|
||||
|
||||
image = CreateDefaultImage (display, (char *)questionBits, 22, 22);
|
||||
XmInstallImage (image, "default_xm_question");
|
||||
|
||||
image = CreateDefaultImage (display, (char *)warningBits, 9, 22);
|
||||
XmInstallImage (image, "default_xm_warning");
|
||||
|
||||
image = CreateDefaultImage (display, (char *)workingBits, 21, 23);
|
||||
XmInstallImage (image, "default_xm_working");
|
||||
|
||||
return ;
|
||||
} /* end ImageInitialize */
|
||||
|
||||
static int
|
||||
CopyFileSysType(
|
||||
int dev)
|
||||
{
|
||||
struct ustat u1;
|
||||
if(ustat(dev,&u1) < 0)
|
||||
return -2;
|
||||
return u1.f_tinode;
|
||||
}
|
||||
|
||||
static int
|
||||
CopyCheckDeletePermissionRecur(
|
||||
char *destinationPath)
|
||||
{
|
||||
struct stat statbuf;
|
||||
DIR *dirp;
|
||||
struct dirent * dp;
|
||||
Boolean first_file;
|
||||
char *fnamep;
|
||||
|
||||
DPRINTF(("CheckDeletePermissionRecur(\"%s\")\n", destinationPath));
|
||||
|
||||
if (lstat(destinationPath, &statbuf) < 0)
|
||||
return -1; /* probably does not exist */
|
||||
|
||||
if (! S_ISDIR(statbuf.st_mode))
|
||||
{
|
||||
if(access(destinationPath,04) < 0)
|
||||
return -1;
|
||||
return 0; /* no need to check anything more */
|
||||
}
|
||||
|
||||
dirp = opendir (destinationPath);
|
||||
if (dirp == NULL)
|
||||
return -1; /* could not read directory */
|
||||
|
||||
|
||||
first_file = True;
|
||||
|
||||
while (dp = readdir (dirp))
|
||||
{
|
||||
if (strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0)
|
||||
{
|
||||
if (first_file)
|
||||
{
|
||||
/* check for write permission in this directory */
|
||||
if (access(destinationPath, 04|02|01) < 0)
|
||||
return -1;
|
||||
|
||||
/* append a '/' to the end of directory name */
|
||||
fnamep = destinationPath + strlen(destinationPath);
|
||||
*fnamep++ = '/';
|
||||
|
||||
first_file = False;
|
||||
}
|
||||
|
||||
/* append file name to end of directory name */
|
||||
strcpy(fnamep, dp->d_name);
|
||||
|
||||
/* recursively check permission on this file */
|
||||
if (CopyCheckDeletePermissionRecur(destinationPath))
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
CopyCheckDeletePermission(
|
||||
char *parentdir,
|
||||
char *destinationPath)
|
||||
{
|
||||
struct stat statbuf;
|
||||
char fname[1024];
|
||||
|
||||
if (lstat(parentdir,&statbuf) < 0) /* does not exist */
|
||||
return -1;
|
||||
|
||||
/* check if we are root */
|
||||
if (getuid() == 0)
|
||||
{
|
||||
/* if NFS, need to check if server trusts root */
|
||||
if (CopyFileSysType(statbuf.st_dev) < 0) /* Root user and nfs */
|
||||
{
|
||||
char *tmpfile;
|
||||
tmpfile = tempnam(parentdir,"quang");
|
||||
if (creat(tmpfile,O_RDONLY)< 0) /* Create a temporary file */
|
||||
return -1;
|
||||
if (remove(tmpfile) < 0) /* Delete the created file */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* root user can delete anything */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check for write and execute permisssion on parent dir */
|
||||
if (access(parentdir, 04|02 | 01) < 0)
|
||||
return -1;
|
||||
|
||||
/* copy destinationPath to tmp buffer */
|
||||
strcpy(fname, destinationPath);
|
||||
|
||||
return CopyCheckDeletePermissionRecur(fname);
|
||||
}
|
||||
|
||||
void
|
||||
CloseTopLevel(
|
||||
Widget w,
|
||||
void *client_data,
|
||||
void *call_data)
|
||||
{
|
||||
XtDestroyWidget((Widget)G_toplevel);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
void
|
||||
CheckDeleteAccess(
|
||||
XtAppContext app_context,
|
||||
int delay,
|
||||
Boolean checkPerms,
|
||||
Boolean move,
|
||||
char *source_name)
|
||||
{
|
||||
if(checkPerms && move)
|
||||
{
|
||||
char title[200],*msg,*tmpmsg;
|
||||
char *tmpstring = strdup(source_name),*tmpptr;
|
||||
XEvent event;
|
||||
int perm_status;
|
||||
|
||||
delay = 10000;
|
||||
tmpptr = strrchr(tmpstring,'/');
|
||||
if(!tmpptr) /* Error */
|
||||
perm_status = 1;
|
||||
else
|
||||
{
|
||||
if(tmpptr == tmpstring)
|
||||
tmpptr = "/";
|
||||
else
|
||||
{
|
||||
*tmpptr = '\0';
|
||||
tmpptr = tmpstring;
|
||||
}
|
||||
perm_status = CopyCheckDeletePermission(tmpptr,source_name);
|
||||
free(tmpstring);
|
||||
}
|
||||
if(!perm_status) /* Everything is fine just return */
|
||||
return;
|
||||
|
||||
strcpy(title,GETMESSAGE(4,7,"Object Trash - Error"));
|
||||
tmpmsg = GETMESSAGE(4,8,"You do not have permission to put the object \n\n%s\n\ninto trash.\n\nUse the Change Permissions choice from the object's\npopup menu or from the Selected menu to turn on your\nRead permission on the object.\n\nNote: If this object is a folder, you must also have\nRead permission for each of the objects inside the\nfolder before you can put the folder in the trash.");
|
||||
|
||||
msg = XtMalloc(strlen(tmpmsg)+strlen(source_name)+2);
|
||||
sprintf(msg,tmpmsg,source_name);
|
||||
_DtMessageDialog (G_toplevel, title, msg, 0, FALSE, NULL,
|
||||
CloseTopLevel, NULL, NULL, False, ERROR_DIALOG);
|
||||
/*
|
||||
XtAppAddTimeOut(app_context, delay, TimeoutHandler, NULL);
|
||||
*/
|
||||
|
||||
/* wait for user to close the dialog before exiting */
|
||||
XtFree(msg);
|
||||
while (!G_dialog_closed)
|
||||
{
|
||||
XtAppNextEvent(app_context, &event);
|
||||
XtDispatchEvent(&event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TimeoutHandler(XtPointer client_data, XtIntervalId *id)
|
||||
{
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a generic function for resolving a cannonical path from user input.
|
||||
*/
|
||||
|
||||
char *
|
||||
#ifdef _NO_PROTO
|
||||
_DtCopyPathFromInput(input_string, current_dir)
|
||||
char *input_string;
|
||||
char *current_dir;
|
||||
#else
|
||||
_DtCopyPathFromInput(
|
||||
char *input_string,
|
||||
char *current_dir)
|
||||
#endif /* _NO_PROTO */
|
||||
|
||||
{
|
||||
char *path;
|
||||
char *tmp_path = NULL;
|
||||
int dir_len;
|
||||
char *_DtCopyChangeTildeToHome();
|
||||
|
||||
/* find relative path */
|
||||
|
||||
tmp_path = path = XtNewString(input_string);
|
||||
|
||||
|
||||
/* Strip any spaces from name -- input is overwritten */
|
||||
path = (char *) _DtStripSpaces(path);
|
||||
|
||||
/* Resolve, if there're any, environement variables */
|
||||
{
|
||||
FILE *pfp;
|
||||
char command[MAX_PATH];
|
||||
|
||||
sprintf(command,"echo %s",path);
|
||||
if((pfp=popen(command,"r")) == NULL)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
fscanf(pfp,"%s",command);
|
||||
XtFree(path);
|
||||
path = XtNewString(command);
|
||||
pclose(pfp);
|
||||
}
|
||||
}
|
||||
|
||||
/* Resolve '~' -- new memory is allocated, old memory is freed */
|
||||
if (*path == '~')
|
||||
path = _DtCopyChangeTildeToHome(path);
|
||||
|
||||
/* If current dir provided, check for relative path */
|
||||
if (path && current_dir)
|
||||
{
|
||||
if (*path != '/')
|
||||
{
|
||||
/* file is relative path i.e. xyz/abc */
|
||||
if (strcmp(current_dir, "/") == 0)
|
||||
{
|
||||
tmp_path = (char *)XtMalloc(strlen(current_dir) + strlen(path) + 1);
|
||||
sprintf(tmp_path, "%s%s", current_dir, path);
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp_path = (char *)XtMalloc(strlen(current_dir) + strlen(path) + 2);
|
||||
sprintf(tmp_path, "%s/%s", current_dir, path);
|
||||
}
|
||||
|
||||
XtFree(path);
|
||||
path = tmp_path;
|
||||
tmp_path = NULL;
|
||||
}
|
||||
}
|
||||
else if (!path)
|
||||
{
|
||||
XtFree(tmp_path);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Resolve '.' or '..' -- input is overwritten, output may be NULL! */
|
||||
/* Save pointer to path to free if output is NULL. */
|
||||
tmp_path = path;
|
||||
path = (char *) XeEliminateDots(path);
|
||||
|
||||
/* Strip off trailing '/' */
|
||||
dir_len = strlen(path);
|
||||
if (dir_len > 1 && *(path + dir_len - 1) == '/')
|
||||
*(path + dir_len - 1) = NULL;
|
||||
return path;
|
||||
}
|
||||
char *
|
||||
#ifdef _NO_PROTO
|
||||
_DtCopyChangeTildeToHome (input_string)
|
||||
char *input_string;
|
||||
#else
|
||||
_DtCopyChangeTildeToHome (
|
||||
char *input_string)
|
||||
#endif
|
||||
{
|
||||
char *path;
|
||||
char *full_path;
|
||||
struct passwd * pwInfo;
|
||||
char * homedir = (char *) XtNewString(getenv("HOME"));
|
||||
|
||||
if ((input_string[1] != '/'))
|
||||
{
|
||||
char *path;
|
||||
|
||||
/* ~user or ~user/path format */
|
||||
|
||||
/* is there a path? */
|
||||
path = (char *) DtStrchr(input_string, '/');
|
||||
|
||||
/* find user */
|
||||
if (path)
|
||||
*path = '/';
|
||||
if ((pwInfo = getpwnam(input_string + 1)) == NULL)
|
||||
{
|
||||
/* user doesn't exist */
|
||||
if (path)
|
||||
*path = '/';
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (path)
|
||||
{
|
||||
/* ~user/path format */
|
||||
|
||||
*path = '/';
|
||||
|
||||
if (strcmp(pwInfo->pw_dir, "/") == 0)
|
||||
{
|
||||
/* We don't want to end up with double '/' in the path */
|
||||
full_path = (char *) XtMalloc(strlen(path) + 1);
|
||||
strcpy(full_path, path);
|
||||
}
|
||||
else
|
||||
{
|
||||
full_path = (char *) XtMalloc(strlen(pwInfo->pw_dir) +
|
||||
strlen(path) + 1);
|
||||
sprintf(full_path, "%s%s", pwInfo->pw_dir, path);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ~user format */
|
||||
|
||||
full_path = XtMalloc(strlen(pwInfo->pw_dir) + 1);
|
||||
strcpy(full_path, pwInfo->pw_dir);
|
||||
}
|
||||
}
|
||||
else if (input_string[1])
|
||||
{
|
||||
/* ~/path format */
|
||||
|
||||
/* NOTE: users_home_dir has trailing '/' */
|
||||
full_path = (char *) XtMalloc(strlen(homedir) + strlen(input_string+2) + 1);
|
||||
sprintf(full_path, "%s%s", homedir, (input_string + 2));
|
||||
free(homedir);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* ~ format */
|
||||
|
||||
full_path = XtMalloc(strlen(homedir) + 1);
|
||||
strcpy(full_path, homedir);
|
||||
}
|
||||
|
||||
XtFree(homedir);
|
||||
XtFree(input_string);
|
||||
return(full_path);
|
||||
}
|
||||
|
||||
int
|
||||
#ifdef _NO_PROTO
|
||||
Check( spth,dpth, mode)
|
||||
register char *spth ;
|
||||
register char *dpth ;
|
||||
int mode ;
|
||||
#else
|
||||
Check(
|
||||
register char *spth,
|
||||
register char *dpth,
|
||||
int mode)
|
||||
#endif /* _NO_PROTO */
|
||||
{
|
||||
struct stat sbuf,dbuf;
|
||||
char filename [MAX_PATH];
|
||||
char * msg;
|
||||
char * tmpStr;
|
||||
char title[300];
|
||||
|
||||
sbuf.st_ino = 0;
|
||||
if (lstat (spth, &sbuf) < 0)
|
||||
{
|
||||
tmpStr = (GETMESSAGE(4,9, "Cannot open %s"));
|
||||
msg = XtMalloc(strlen(tmpStr)+strlen(filename)+1);
|
||||
sprintf(msg,tmpStr,filename);
|
||||
_DtMessageDialog (G_toplevel, title, msg, 0, FALSE, NULL,
|
||||
CloseTopLevel, NULL, NULL, False, ERROR_DIALOG);
|
||||
XtFree(msg);
|
||||
return 0;
|
||||
}
|
||||
(void) strcpy (filename, dpth);
|
||||
if(mode)
|
||||
strcpy(title,GETMESSAGE(4,5,"Object Move - Error"));
|
||||
else
|
||||
strcpy(title,GETMESSAGE(4,6,"Object Copy - Error"));
|
||||
while (dbuf.st_ino != ROOTINO)
|
||||
{
|
||||
/* Destination may not be available, in which case we need to
|
||||
create it, so just return as successful and the remaining
|
||||
code takes care of everything */
|
||||
|
||||
if (lstat (filename, &dbuf) < 0)
|
||||
return 0;
|
||||
|
||||
if (dbuf.st_ino == sbuf.st_ino)
|
||||
{
|
||||
if(mode)
|
||||
tmpStr = GETMESSAGE(3,19,"Cannot move folder into itself. %s");
|
||||
else
|
||||
tmpStr = GETMESSAGE(3,20,"Cannot copy folder into itself. %s");
|
||||
msg = XtMalloc(strlen(tmpStr)+strlen(dpth)+1);
|
||||
sprintf(msg,tmpStr,dpth);
|
||||
_DtMessageDialog (G_toplevel, title, msg, 0, FALSE, NULL,
|
||||
CloseTopLevel, NULL, NULL, False, ERROR_DIALOG);
|
||||
|
||||
XtFree(msg);
|
||||
return(1);
|
||||
}
|
||||
|
||||
(void) strcat (filename, "/..");
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
79
cde/programs/dtfile/dtcopy/sharedFuncs.h
Normal file
79
cde/programs/dtfile/dtcopy/sharedFuncs.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/* $XConsortium: sharedFuncs.h /main/4 1995/11/02 14:48:35 rswiston $ */
|
||||
/************************************<+>*************************************
|
||||
****************************************************************************
|
||||
*
|
||||
* FILE: sharedFuncs.h
|
||||
*
|
||||
*
|
||||
* DESCRIPTION: Header file used in copydialog.c,errordialog.c,
|
||||
* main_dtcopy.c,overwrtdialog.c,sharedFuncs.c,utils.c
|
||||
*
|
||||
* (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
|
||||
* (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
|
||||
* (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
|
||||
* (c) Copyright 1993, 1994, 1995 Novell, Inc.
|
||||
*
|
||||
****************************************************************************
|
||||
************************************<+>*************************************/
|
||||
|
||||
#ifndef SHAREDFUNCS_H
|
||||
#define SHAREDFUNCS_H
|
||||
|
||||
/* Includes */
|
||||
|
||||
#include <X11/Intrinsic.h>
|
||||
|
||||
/* Macros */
|
||||
|
||||
#define TIGHTNESS 20 /* button spacing in Create_Action_Area */
|
||||
|
||||
#define MAX_PATH 1024 /* Maximum path length */
|
||||
|
||||
/* Types */
|
||||
|
||||
typedef struct {
|
||||
char *label; /* PushButton's default Label */
|
||||
int msg_set; /* set from which PushButton's Label is taken */
|
||||
int msg_num; /* message number of PushButton's Label */
|
||||
void (*callback)(); /* pointer to callback routine */
|
||||
XtPointer data; /* client data for callback routine */
|
||||
} ActionAreaItem;
|
||||
|
||||
typedef struct {
|
||||
int numActions;
|
||||
int defaultAction; /* index in actionList[], >=0, <numActions */
|
||||
ActionAreaItem *actionList;
|
||||
} ActionAreaDefn;
|
||||
|
||||
|
||||
/* Global Variables */
|
||||
|
||||
/* External Routines */
|
||||
|
||||
extern int auto_rename(const String path);
|
||||
extern void generate_NewPath(String newPath, String oldPath);
|
||||
extern void split_path(const String path, String folder, String object);
|
||||
extern String build_path(const String folder, const String object);
|
||||
extern XImage * CreateDefaultImage(
|
||||
Display *display,
|
||||
char *bits,
|
||||
unsigned int width,
|
||||
unsigned int height );
|
||||
extern void ImageInitialize(Display *display);
|
||||
extern Widget Create_Action_Area(
|
||||
Widget parent_widget,
|
||||
ActionAreaDefn actions,
|
||||
Widget * pushbutton_array);
|
||||
extern void CheckDeleteAccess(
|
||||
XtAppContext app_context,
|
||||
int delay,
|
||||
Boolean checkPerms,
|
||||
Boolean move,
|
||||
char *source_name);
|
||||
extern void TimeoutHandler(
|
||||
XtPointer client_data,
|
||||
XtIntervalId *id);
|
||||
|
||||
|
||||
|
||||
#endif /* SHAREDFUNCS_H */
|
||||
421
cde/programs/dtfile/dtcopy/utils.c
Normal file
421
cde/programs/dtfile/dtcopy/utils.c
Normal file
@@ -0,0 +1,421 @@
|
||||
/* $XConsortium: utils.c /main/5 1996/10/17 09:36:36 mustafa $ */
|
||||
/************************************<+>*************************************
|
||||
****************************************************************************
|
||||
*
|
||||
* FILE: utils.c
|
||||
*
|
||||
*
|
||||
* DESCRIPTION: Utility routines
|
||||
*
|
||||
* FUNCTIONS: Create_Action_Area
|
||||
* Display_Help
|
||||
* Get_Help_Dialog
|
||||
* Help
|
||||
* _DtChildPosition
|
||||
* help_callback
|
||||
* help_close_callback
|
||||
* help_hyperyperlink_callback
|
||||
*
|
||||
* (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
|
||||
* (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
|
||||
* (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
|
||||
* (c) Copyright 1993, 1994, 1995 Novell, Inc.
|
||||
*
|
||||
****************************************************************************
|
||||
************************************<+>*************************************/
|
||||
|
||||
#include <time.h>
|
||||
#include <X11/Intrinsic.h>
|
||||
#include <X11/StringDefs.h>
|
||||
#include <Xm/XmP.h>
|
||||
#include <Xm/Xm.h>
|
||||
#include <Xm/VendorSEP.h>
|
||||
#include <Xm/PushB.h>
|
||||
#include <Xm/Form.h>
|
||||
#include <Xm/BulletinB.h>
|
||||
#include <Xm/TextF.h>
|
||||
/* Copied from Xm/BaseClassI.h */
|
||||
extern XmWidgetExtData _XmGetWidgetExtData(
|
||||
Widget widget,
|
||||
#if NeedWidePrototypes
|
||||
unsigned int extType) ;
|
||||
#else
|
||||
unsigned char extType) ;
|
||||
#endif /* NeedWidePrototypes */
|
||||
|
||||
#include <Dt/HelpDialog.h>
|
||||
|
||||
#include "dtcopy.h"
|
||||
#include "sharedFuncs.h"
|
||||
|
||||
|
||||
|
||||
/*............... definitions for Help .............................*/
|
||||
void
|
||||
Help(
|
||||
char *helpVolume,
|
||||
char *locationId);
|
||||
void
|
||||
Display_Help(
|
||||
char *helpVolume,
|
||||
char *locationId);
|
||||
|
||||
/* Help volume tags used to attach a certian help volume
|
||||
* to a particular call back. Look to function help_callback
|
||||
* for more code. MJT
|
||||
*/
|
||||
#define HELP_USING_HELP_VOLUME "Help4Help"
|
||||
#define HELP_USING_STR "_HomeTopic"
|
||||
#define HELP_VOLUME "Filemgr"
|
||||
#define HELP_HELP_MENU_STR "Reference"
|
||||
#define HELP_INTRODUCTION_STR "_HomeTopic"
|
||||
#define HELP_DIR_COPY_STR "FMCopyDirDialogStatusDE"
|
||||
#define HELP_DIR_ERROR_STR "FMCopyDIrDialogErrorDE"
|
||||
#define HELP_OVERWRITE_STR "FMCopyDirOverDialogDE"
|
||||
#define HELP_VERSION_STR "FMHelpMenuDE"
|
||||
#define STOPW_HELP_STR "FMCopyFoldWarnDialogDE"
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* Callback routines
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
help_close_callback(
|
||||
Widget widget,
|
||||
XtPointer client_data,
|
||||
XtPointer call_data)
|
||||
{
|
||||
XtUnmapWidget(XtParent(widget));
|
||||
}
|
||||
|
||||
void
|
||||
help_hyperyperlink_callback(
|
||||
Widget widget,
|
||||
XtPointer client_data,
|
||||
XtPointer call_data)
|
||||
{
|
||||
DtHelpDialogCallbackStruct *pHyper = (DtHelpDialogCallbackStruct *) call_data;
|
||||
|
||||
switch(pHyper->hyperType)
|
||||
{
|
||||
case DtHELP_LINK_JUMP_NEW:
|
||||
Display_Help(pHyper->helpVolume, pHyper->locationId);
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
help_callback(
|
||||
Widget widget,
|
||||
XtPointer client_data,
|
||||
XtPointer call_data)
|
||||
{
|
||||
char *helpVolume, *locationId;
|
||||
int topic;
|
||||
|
||||
topic = (int) client_data;
|
||||
helpVolume = HELP_VOLUME;
|
||||
|
||||
switch (topic)
|
||||
{
|
||||
case HELP_HELP_MENU:
|
||||
locationId = HELP_HELP_MENU_STR;
|
||||
break;
|
||||
case HELP_INTRODUCTION:
|
||||
locationId = HELP_INTRODUCTION_STR;
|
||||
break;
|
||||
case HELP_DIR_COPY:
|
||||
locationId = HELP_DIR_COPY_STR;
|
||||
break;
|
||||
case HELP_DIR_ERROR:
|
||||
locationId = HELP_DIR_ERROR_STR;
|
||||
break;
|
||||
case HELP_OVERWRITE:
|
||||
locationId = HELP_OVERWRITE_STR;
|
||||
break;
|
||||
case HELP_USING:
|
||||
locationId = HELP_USING_STR;
|
||||
helpVolume = HELP_USING_HELP_VOLUME;
|
||||
break;
|
||||
case HELP_VERSION:
|
||||
locationId = HELP_VERSION_STR;
|
||||
break;
|
||||
case STOPW_HELP_DIALOG:
|
||||
locationId = STOPW_HELP_STR;
|
||||
break;
|
||||
default:
|
||||
locationId = HELP_USING_STR;
|
||||
helpVolume = HELP_USING_HELP_VOLUME;
|
||||
break;
|
||||
}
|
||||
Help(helpVolume, locationId);
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* _DtChildPosition
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
_DtChildPosition(
|
||||
Widget w,
|
||||
Widget parent,
|
||||
Position *newX,
|
||||
Position *newY)
|
||||
{
|
||||
Position pY, pX;
|
||||
XmVendorShellExtObject vendorExt;
|
||||
XmWidgetExtData extData;
|
||||
int xOffset, yOffset;
|
||||
int pHeight, myHeight, sHeight;
|
||||
int pWidth, myWidth, sWidth;
|
||||
enum { posRight, posBelow, posLeft, posAbove } pos;
|
||||
int space;
|
||||
|
||||
/* get x, y offsets for the parent's window frame */
|
||||
extData = _XmGetWidgetExtData(parent, XmSHELL_EXTENSION);
|
||||
if (extData)
|
||||
{
|
||||
vendorExt = (XmVendorShellExtObject)extData->widget;
|
||||
xOffset = vendorExt->vendor.xOffset;
|
||||
yOffset = vendorExt->vendor.yOffset;
|
||||
}
|
||||
else
|
||||
xOffset = yOffset = 0;
|
||||
|
||||
/* get size/position of screen, parent, and widget */
|
||||
sHeight = HeightOfScreen(XtScreen(parent));;
|
||||
sWidth = WidthOfScreen(XtScreen(parent));
|
||||
pX = XtX(parent) - xOffset;
|
||||
pY = XtY(parent) - yOffset;
|
||||
pHeight = XtHeight(parent) + yOffset + xOffset;
|
||||
pWidth = XtWidth(parent) + 2*xOffset;
|
||||
myHeight = XtHeight(w) + yOffset + xOffset;
|
||||
myWidth = XtWidth(w) + 2*xOffset;
|
||||
|
||||
{
|
||||
XWindowAttributes attr;
|
||||
|
||||
XGetWindowAttributes(XtDisplay(parent), XtWindow(parent), &attr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine how much space would be left if the child was positioned
|
||||
* to the right, below, left, or above the parent. Choose the child
|
||||
* positioning so that the maximum space is left.
|
||||
*/
|
||||
pos = posRight;
|
||||
space = sWidth - (pX + pWidth + myWidth);
|
||||
|
||||
if (sHeight - (pY + pHeight + myHeight) > space)
|
||||
{
|
||||
pos = posBelow;
|
||||
space = sHeight - (pY + pHeight + myHeight);
|
||||
}
|
||||
|
||||
if (pX - myWidth > space)
|
||||
{
|
||||
pos = posLeft;
|
||||
space = pX - myWidth;
|
||||
}
|
||||
|
||||
if (pY - myHeight > space)
|
||||
{
|
||||
pos = posAbove;
|
||||
space = pY - myHeight;
|
||||
}
|
||||
|
||||
/* Given relative positioning, determine x, y coordinates for the child */
|
||||
|
||||
switch (pos)
|
||||
{
|
||||
case posRight:
|
||||
*newX = pX + pWidth + 5;
|
||||
*newY = pY + (pHeight - myHeight)/2;
|
||||
break;
|
||||
|
||||
case posBelow:
|
||||
*newX = pX + (pWidth - myWidth)/2;
|
||||
*newY = pY + pHeight + 5;
|
||||
break;
|
||||
|
||||
case posLeft:
|
||||
*newX = pX - myWidth - 5;
|
||||
*newY = pY + (pHeight - myHeight)/2;
|
||||
break;
|
||||
|
||||
case posAbove:
|
||||
*newX = pX + (pWidth - myWidth)/2;
|
||||
*newY = pY - myHeight - 5;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static Widget
|
||||
Get_Help_Dialog()
|
||||
{
|
||||
Widget dialog;
|
||||
Arg args[5];
|
||||
int n;
|
||||
|
||||
n = 0;
|
||||
XtSetArg(args[n], XmNtitle, GETMESSAGE(6, 5, "Directory Copy Help")); n++;
|
||||
dialog = DtCreateHelpDialog(G_toplevel, "helpDlg", args, n);
|
||||
|
||||
XtAddCallback(dialog, DtNhyperLinkCallback,
|
||||
(XtCallbackProc)help_hyperyperlink_callback, NULL);
|
||||
XtAddCallback(dialog, DtNcloseCallback,
|
||||
(XtCallbackProc)help_close_callback, NULL);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
void
|
||||
Display_Help(
|
||||
char *helpVolume,
|
||||
char *locationId)
|
||||
{
|
||||
Arg args[10];
|
||||
int n;
|
||||
|
||||
G_help_dialog = Get_Help_Dialog();
|
||||
|
||||
n = 0;
|
||||
XtSetArg(args[n], DtNhelpType, DtHELP_TYPE_TOPIC); n++;
|
||||
XtSetArg(args[n], DtNhelpVolume, helpVolume); n++;
|
||||
XtSetArg(args[n], DtNlocationId, locationId); n++;
|
||||
XtSetValues(G_help_dialog, args, n);
|
||||
|
||||
XtManageChild(G_help_dialog);
|
||||
XtMapWidget(XtParent(G_help_dialog));
|
||||
}
|
||||
|
||||
void
|
||||
Help(
|
||||
char *helpVolume,
|
||||
char *locationId)
|
||||
{
|
||||
Arg args[10];
|
||||
int n;
|
||||
|
||||
if(G_help_dialog == NULL)
|
||||
{
|
||||
n = 0;
|
||||
XtSetArg(args[n], DtNhelpType, DtHELP_TYPE_TOPIC); n++;
|
||||
XtSetArg(args[n], DtNhelpVolume, helpVolume); n++;
|
||||
XtSetArg(args[n], DtNlocationId, locationId); n++;
|
||||
XtSetArg (args[n], XmNtitle, GETMESSAGE(6, 5, "Directory Copy Help")); n++;
|
||||
|
||||
G_help_dialog = DtCreateHelpDialog(G_toplevel, "helpDlg", args, n);
|
||||
|
||||
XtAddCallback(G_help_dialog, DtNhyperLinkCallback,
|
||||
(XtCallbackProc)help_hyperyperlink_callback, NULL);
|
||||
XtAddCallback(G_help_dialog, DtNcloseCallback,
|
||||
(XtCallbackProc)help_close_callback, NULL);
|
||||
|
||||
XtManageChild(G_help_dialog);
|
||||
}
|
||||
else
|
||||
{
|
||||
n = 0;
|
||||
XtSetArg(args[n], DtNhelpType, DtHELP_TYPE_TOPIC); n++;
|
||||
XtSetArg(args[n], DtNhelpVolume, helpVolume); n++;
|
||||
XtSetArg(args[n], DtNlocationId, locationId); n++;
|
||||
XtSetValues(G_help_dialog, args, n);
|
||||
}
|
||||
|
||||
XtMapWidget(XtParent(G_help_dialog));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
*
|
||||
* Create Action Area
|
||||
*
|
||||
* Use of this function requires #include "sharedFuncs.h"
|
||||
* The source for Create_Action_Area is in dtfile/OverWrite.c and
|
||||
* dtfile/dtcopy/utils.c. Because it uses GETMESSAGE, it could not
|
||||
* be placed in dtcopy/sharedFunc.c.
|
||||
*
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
Widget
|
||||
Create_Action_Area(
|
||||
Widget parent_widget,
|
||||
ActionAreaDefn actions,
|
||||
Widget *pushbutton_array)
|
||||
{
|
||||
Widget action_area, widget;
|
||||
int i;
|
||||
int fractbase_value;
|
||||
XmString xm_string;
|
||||
|
||||
|
||||
if (actions.defaultAction < 0 || actions.defaultAction > actions.numActions-1)
|
||||
actions.defaultAction = 0;
|
||||
|
||||
fractbase_value = (TIGHTNESS * actions.numActions) - 1;
|
||||
action_area = XtVaCreateManagedWidget("action_area", xmFormWidgetClass ,parent_widget,
|
||||
XmNfractionBase, fractbase_value,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
XmNbottomAttachment, XmATTACH_FORM,
|
||||
NULL);
|
||||
|
||||
for (i=0; i < actions.numActions ;i++ )
|
||||
{
|
||||
xm_string = XmStringCreateLocalized(GETMESSAGE(actions.actionList[i].msg_set,
|
||||
actions.actionList[i].msg_num,
|
||||
actions.actionList[i].label));
|
||||
widget = XtVaCreateManagedWidget(actions.actionList[i].label,
|
||||
xmPushButtonWidgetClass, action_area,
|
||||
XmNleftAttachment, (i ? XmATTACH_POSITION: XmATTACH_FORM),
|
||||
XmNleftPosition, (TIGHTNESS * i),
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNbottomAttachment, XmATTACH_FORM,
|
||||
XmNrightAttachment,
|
||||
((i != (actions.numActions - 1)) ? XmATTACH_POSITION: XmATTACH_FORM),
|
||||
XmNrightPosition, ((TIGHTNESS*i) + (TIGHTNESS - 1)),
|
||||
XmNshowAsDefault, (i == actions.defaultAction),
|
||||
XmNdefaultButtonShadowThickness, 1,
|
||||
XmNlabelString, xm_string,
|
||||
NULL);
|
||||
XmStringFree(xm_string);
|
||||
|
||||
|
||||
|
||||
if (actions.actionList[i].callback)
|
||||
{
|
||||
XtAddCallback(widget, XmNactivateCallback,
|
||||
actions.actionList[i].callback, actions.actionList[i].data);
|
||||
}
|
||||
|
||||
if (i == actions.defaultAction)
|
||||
{
|
||||
Dimension height, h;
|
||||
XtVaGetValues (action_area, XmNmarginHeight, &h, NULL);
|
||||
XtVaGetValues (widget, XmNheight, &height, NULL);
|
||||
|
||||
height +=2 * h;
|
||||
XtVaSetValues (action_area,
|
||||
XmNdefaultButton, widget,
|
||||
XmNpaneMaximum, height,
|
||||
XmNpaneMinimum, height,
|
||||
NULL);
|
||||
|
||||
}
|
||||
|
||||
if (pushbutton_array != NULL)
|
||||
pushbutton_array[i] = widget;
|
||||
|
||||
} /* endfor */
|
||||
|
||||
XtManageChild(action_area);
|
||||
return action_area;
|
||||
|
||||
} /* end Create_Action_Area */
|
||||
|
||||
Reference in New Issue
Block a user