Initial import of the CDE 2.1.30 sources from the Open Group.

This commit is contained in:
Peter Howkins
2012-03-10 18:21:40 +00:00
commit 83b6996daa
18978 changed files with 3945623 additions and 0 deletions

View 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)

View 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;
}

View 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);
}

View 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 */

View 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

View 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

View 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;
}

View 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);
}

View 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 */

View 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);
}

View File

@@ -0,0 +1,2 @@
/* $XConsortium: nmrtns.h /main/3 1995/11/02 14:48:07 rswiston $ */
#error "obsolete file"

View 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 */

View 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);
}

View 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 */

View 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 */