2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $TOG: FileManip.c /main/10 1999/12/09 13:06:10 mgreess $ */
24 /************************************<+>*************************************
25 ****************************************************************************
29 * COMPONENT_NAME: Desktop File Manager (dtfile)
31 * Description: This module does the copy, move and rename commands.
32 * Included are functions to control command execution,
33 * move a directory, get the directory portion of a pathname,
34 * get the file name portion of a pathname, and check if a
35 * folder is to be moved within itself.
46 * (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
47 * (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
48 * (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
49 * (c) Copyright 1993, 1994, 1995 Novell, Inc.
51 ****************************************************************************
52 ************************************<+>*************************************/
55 # include <sys/fs/ufs_fs.h>
56 # define ROOTINO UFSROOTINO
58 # if defined(linux) || defined(CSRG_BASED)
61 # include <sys/param.h>
64 #include <sys/types.h>
72 /** The following ifdefs need to be straightened out
97 #include <Xm/MwmUtil.h>
99 #include <Dt/DtP.h> /* required for DtDirPaths type */
100 #include <Dt/Connect.h>
101 #include <Dt/DtNlUtils.h>
102 #include <Dt/SharedProcs.h>
105 #include "SharedProcs.h"
110 #include "SharedMsgs.h"
112 #ifndef CDE_INSTALLATION_TOP
113 #define CDE_INSTALLATION_TOP "/usr/dt"
116 /* Local Function Definitions */
117 static char * MOVE_CMD = "/bin/mv";
118 static char * LINK_CMD = "/bin/ln";
119 static char * REMOVE_CMD = "/bin/rm";
120 static char * DTCOPY = CDE_INSTALLATION_TOP "/bin/dtfile_copy";
123 /************************************************************************
127 ************************************************************************/
137 #if defined(__ultrix)
138 /*--------------------------------------------------------------------
139 * access code for __ultrix
140 *------------------------------------------------------------------*/
142 setreuid(geteuid(),-1);
143 return access (fname, what);
147 /*--------------------------------------------------------------------
148 * access code for BLS
149 *------------------------------------------------------------------*/
151 setresuid(geteuid(),-1,-1);
152 return access (fname, what);
154 #else /* the rest of the OS's */
156 save_ruid = getuid();
159 setreuid(geteuid(),-1);
164 save_rgid = getgid();
167 setregid(getegid(),-1);
172 access_priv = access (fname, what);
175 setreuid(save_ruid,-1);
176 setregid(save_rgid,-1);
188 /************************************************************************
191 * Display an error message.
193 ************************************************************************/
204 if (message2 != NULL)
206 message_buf = XtMalloc(strlen(message1) + strlen(message2) + 1);
207 (void) sprintf(message_buf,message1, message2);
211 message_buf = XtMalloc(strlen(message1) + 1);
212 (void) sprintf(message_buf, "%s", message1);
215 /* Display an error dialog */
216 tmpStr = GetSharedMessage(FILE_MANIPULATION_ERROR_TITLE);
217 title = XtNewString(tmpStr);
218 _DtMessage (w, title, message_buf, NULL, HelpRequestCB);
224 /************************************************************************
227 * Returns the file name of its argument.
228 * Keep looking thru the string until a "/" is found which still
229 * has some characters after it.
231 ************************************************************************/
234 register char *name )
243 q = DtStrchr(q, '/');
257 /************************************************************************
261 ************************************************************************/
266 register ino_t dinode,
268 void (*errorHandler)() )
271 char filename [MAX_PATH];
277 (void) strcpy (filename, spth);
279 while (sbuf.st_ino != ROOTINO)
281 if (lstat (filename, &sbuf) < 0)
285 tmpStr = (GETMESSAGE(11,33, "Cannot open %s"));
286 msg = XtNewString(tmpStr);
287 (*errorHandler) (w, msg, filename);
293 if (sbuf.st_ino == dinode)
297 if (mode == COPY_FILE)
298 tmpStr = GETMESSAGE(11,35, "Cannot copy a folder into itself.");
300 tmpStr = GETMESSAGE(11,16, "A folder cannot be moved into itself.\n%s");
301 msg = XtNewString(tmpStr);
302 if (mode == COPY_FILE)
303 (*errorHandler) (w, msg, NULL);
305 (*errorHandler) (w, msg, filename);
311 (void) strcat (filename, "/..");
318 /************************************************************************
322 ************************************************************************/
327 register char *source,
328 register char *target,
329 struct stat *sourceStatInfo,
330 void (*errorHandler)(),
334 static char *pname = "MoveDir";
337 char * targetDir; /* original target dir path */
341 struct stat s1; /* status of from file */
342 struct stat s2; /* status of to file */
346 static char buf [BUF_SIZE]; /* generic buffer */
347 char filename [MAX_PATH]; /* buffer to hold the full file name */
352 /* Copy target so we have it for an error dialog if we need it */
353 targetDir = XtNewString(target);
356 if ((val = stat (target, &s2)) < 0)
357 val = lstat(target, &s2);
359 /* Check if move to itself */
360 if( sourceStatInfo->st_dev == s2.st_dev)
362 if (Check (w, target, sourceStatInfo->st_ino, MOVE_FILE, NULL ))
366 if (val >= 0) /* target exists */
368 if ((s2.st_mode & S_IFMT) != S_IFDIR) /* target not directory */
373 tmpStr = GetSharedMessage(CANT_OVERWRITE_ERROR);
374 msg = XtNewString(tmpStr);
375 (*errorHandler) (w, msg, target);
382 (void) strcpy (buf, target);
386 DtLastChar(buf, &cptr, &len);
387 if ((len != 1) || (*cptr != '/'))
388 (void) strcat (buf, "/");
389 (void) strcat (buf, DName (source));
391 if (lstat (target, &s2) >= 0) /* new target exists */
397 tmpStr = GetSharedMessage(CANT_OVERWRITE_ERROR);
398 msg = XtNewString(tmpStr);
399 (*errorHandler) (w, msg, target);
410 /* don't rename these */
411 DtLastChar(p, &cptr, &len);
413 if (!strcmp (p, ".") || !strcmp (p, "..") ||
414 !strcmp (p, "") || ((len == 1) && (*cptr == '/')))
420 tmpStr = (GETMESSAGE(11,32, "Cannot rename %s"));
421 msg = XtNewString(tmpStr);
422 (*errorHandler) (w, msg, p);
430 /* parent doesn't exist */
431 if((val = stat (_DtPName (source), &s1)) < 0)
432 val = lstat (_DtPName (source), &s1);
434 if((val1 = stat (_DtPName (target), &s2)) < 0)
435 val1 = lstat (_DtPName (target), &s2);
437 if (val < 0 || val1 < 0)
441 tmpStr = GETMESSAGE(11, 14, "Cannot find the folders location.");
442 msg = XtNewString(tmpStr);
443 (*errorHandler) (w, msg, NULL);
451 /* check for target parent not writeable */
452 if (CheckAccess(_DtPName (target), W_OK) == -1)
458 tmpStr = GetSharedMessage(CANT_WRITE_ERROR);
459 msg = XtNewString(tmpStr);
460 (*errorHandler) (w, msg, targetDir);
468 /* check for source parent not writeable */
469 if (CheckAccess(_DtPName (source), W_OK) == -1)
475 tmpStr = GetSharedMessage(CANT_WRITE_ERROR);
476 msg = XtNewString(tmpStr);
477 (*errorHandler) (w, msg, source);
484 if (((sourceStatInfo->st_mode & S_IFMT) == S_IFDIR) &&
485 (CheckAccess(source, W_OK) != 0))
491 tmpStr=GETMESSAGE(11, 57,"You do not have permission to move the folder\n%s\nWrite permission is required.");
492 msg = XtMalloc(strlen(tmpStr) + strlen(source) + 2);
493 sprintf(msg, tmpStr, source);
494 (*errorHandler) (w, msg, source);
501 /* if parents are not on the same device, do a copy & delete */
502 if (s1.st_dev != s2.st_dev)
504 /* Determine correct Geometry Placement fo Move Dialog */
505 /* @@@ ... to be added */
512 tmpStr = GETMESSAGE(11, 39, "Cannot create child process.\nThe maximum number of processes for this system has been reached.\nStop some of the processes or programs that are currently\nrunning and then retry this function.");
513 msg = XtNewString(tmpStr);
514 (*errorHandler) (w, msg, NULL);
523 DBGFORK(("%s: child forked\n", pname));
525 /* pass in geometry, and other command lines params when available */
526 if(type == TRASH_DIRECTORY)
527 rc = execlp(DTCOPY, "dtfile_copy", "-move", "-confirmReplace",
528 "-confirmErrors", "-popDown","-checkPerms", source, target, NULL);
530 rc = execlp(DTCOPY, "dtfile_copy", "-move", "-confirmReplace",
531 "-confirmErrors", "-popDown", source, target, NULL);
533 /* call errorhandler */
534 perror ("Could not exec child process \"dtfile_copy\"");
536 DBGFORK(("%s: child exiting\n", pname));
541 DBGFORK(("%s: forked child<%d>\n", pname, child_pid));
548 link_path = _DtFollowLink(source);
551 if (s1.st_ino != s2.st_ino)
552 { /* different parent inodes */
553 (void) lstat (source, &s1); /* get source dir ino */
556 if (Check (w, _DtPName (target), s1.st_ino, MOVE_FILE, errorHandler))
557 { /* move into self */
563 /* This part of code was implemented with the idea that the links
564 to be treated differently. So, it has to be uncommented whenever
565 links are handled differently (i.e., moving a link shall move the
568 if(strcmp(link_path, source) != 0)
570 if (RunFileCommand (MOVE_CMD, link_path, target, NULL) == 0)
579 if (RunFileCommand (MOVE_CMD, source, target, NULL) == 0)
591 /************************************************************************
595 ************************************************************************/
604 void (*errorHandler)(),
605 Boolean checkForBusyDir,
608 static char *pname = "CopyDir";
611 char target [MAX_PATH]; /* buffer to hold the full file name */
612 char target_dir [MAX_PATH], target_file [MAX_PATH];
613 struct stat s2; /* status of to file */
614 int child_pid, rc, target_rc;
617 /* Check if source is readable */
618 if (CheckAccess(from, R_OK) == -1)
622 tmpStr = GetSharedMessage(CANT_READ_ERROR);
623 msg = XtNewString(tmpStr);
624 (*errorHandler) (w, msg, from);
630 /* generate target name */
631 /* "to" can be something to copy the source into (isContainer=TRUE) */
632 /* or it can be the full path of the destination (isContainer=FALSE) */
633 /* the former case is probably more common (e.g. a drag&drop copy) */
634 /* whereas the second case occurs when, for example, the menu is */
635 /* to copy directory /u/joe/a to /u/joe/b (not doable with d&d) */
636 (void) strcpy (target, to);
639 DtLastChar(to, &cptr, &len);
640 if ((len != 1) || (*cptr != '/'))
641 (void) strcat (target, "/");
642 (void) strcat (target, DName (from));
644 split_path(target, target_dir, target_file);
646 /* Check if target directory exists */
647 if ((target_rc = stat (target, &s2)) < 0)
648 target_rc = lstat(target, &s2);
653 * make sure it's a directory */
655 if ((s2.st_mode & S_IFMT) != S_IFDIR) /* target not directory */
659 tmpStr = GetSharedMessage(CANT_OVERWRITE_ERROR);
660 msg = XtNewString(tmpStr);
661 (*errorHandler) (w, msg, target);
669 /* target does not exist:
670 * make sure the "to" directory exists and is writable */
671 if ((rc = stat (target_dir, &s2)) < 0)
672 rc = lstat(target_dir, &s2);
674 if (rc < 0 || (s2.st_mode & S_IFMT) != S_IFDIR)
678 tmpStr = GETMESSAGE(11, 14, "Cannot find the folders location.");
679 msg = XtNewString(tmpStr);
680 (*errorHandler) (w, msg, NULL);
686 if (CheckAccess(target_dir, W_OK) == -1)
690 tmpStr = GetSharedMessage(CANT_WRITE_ERROR);
691 msg = XtNewString(tmpStr);
692 (*errorHandler) (w, msg, to);
699 /* Determine if we are attempting a copy into self */
700 if (s1->st_dev == s2.st_dev)
704 if (Check (w, to, s1->st_ino, COPY_FILE, errorHandler))
707 else /* destination dir does not exist, look at its proposed parent */
709 if (Check (w, target_dir, s1->st_ino, COPY_FILE, errorHandler))
714 /* Determine correct Geometry Placement fo Copy Dialog */
715 /* @@@ ... to be added */
717 /* If all the above checks have passed, then fork off the copy dialog */
724 tmpStr = GETMESSAGE(11, 39, "Cannot create child process.\nThe maximum number of processes for this system has been reached.\nStop some of the processes or programs that are currently\nrunning and then retry this function.");
725 msg = XtNewString(tmpStr);
726 (*errorHandler) (w, msg, NULL);
734 DBGFORK(("%s: child forked\n", pname));
736 /* pass in geometry, and other command lines params when available */
737 if (mode == MERGE_DIR)
738 /* merge source & target directories */
739 rc = execlp(DTCOPY, "dtfile_copy",
740 "-dontDelete", "-forceCopies", "-copyTop",
741 "-confirmReplace", "-confirmErrors", "-popDown",
744 /* replace target dir */
745 rc = execlp(DTCOPY, "dtfile_copy",
746 "-forceCopies", "-copyTop",
747 "-confirmErrors", "-popDown",
750 /* call errorhandler */
751 perror ("Could not exec child process \"dtfile_copy\"");
753 DBGFORK(("%s: child exiting\n", pname));
758 DBGFORK(("%s: forked child<%d>\n", pname, child_pid));
765 /************************************************************************
769 ************************************************************************/
776 Boolean isContainer, /* described in function CopyDir */
777 void (*errorHandler)(),
778 Boolean checkForBusyDir,
784 Boolean copy_dir_return;
785 Boolean move_dir_return;
792 Boolean restricted = False;
793 Boolean fileExists = False;
795 struct stat s1; /* status of from file e.g. lstat info */
796 struct stat s4; /* status of from file e.g. stat info */
797 struct stat s2; /* status of to file e.g. stat info */
798 struct stat s3; /* status of to file e.g. lstat info */
800 char buf [BLOCK_SIZE]; /* generic buffer */
801 char filename [MAX_PATH]; /* buffer to hold the full file name */
808 /* Check the <from> part of the command:
810 * Report error if <from> doesn't exist.
811 * Else error if <from> hasn't read access.
814 DPRINTF(("FileManip: mode %d type %d from \"%s\" to \"%s\"\n", mode, type, from, to));
815 if (stat (from, &s1) < 0)
817 if (lstat (from, &s1) < 0)
821 tmpStr = (GETMESSAGE(11,28, "%s cannot be found."));
822 msg = XtNewString(tmpStr);
823 (*errorHandler) (w, msg, from);
830 /* We will check if we need to initiate a copy of a directory */
831 if ((s1.st_mode & S_IFMT) == S_IFDIR) /* from is a directory */
833 if (mode == COPY_FILE || mode == MERGE_DIR)
835 oldInt = signal (SIGINT, SIG_IGN);
836 oldQuit = signal (SIGQUIT, SIG_IGN);
837 oldPipe = signal (SIGPIPE, SIG_IGN);
838 oldTerm = signal (SIGTERM, SIG_IGN);
840 copy_dir_return = CopyDir(w, mode, from, to, isContainer, &s1,
841 errorHandler, checkForBusyDir, type);
843 (void) signal (SIGINT, oldInt);
844 (void) signal (SIGQUIT, oldQuit);
845 (void) signal (SIGPIPE, oldPipe);
846 (void) signal (SIGTERM, oldTerm);
848 return (copy_dir_return);
852 /* If the directory has more than one open view or open views */
853 /* of sub directories. Then do not allow the move or rename. */
855 if (mode == MOVE_FILE)
857 if (checkForBusyDir && DirectoryBusy (from))
861 char message_buf[512];
864 message_buf[0] = '\0';
865 tmpStr = (GETMESSAGE(11,30, "Cannot move or rename the folder %s.\nAll File Manager views displayed for a folder or its sub-folders\nmust be closed before a folder can be moved or renamed."));
866 sprintf (message_buf, tmpStr, from);
867 (*errorHandler) (w, message_buf, NULL);
873 oldInt = signal (SIGINT, SIG_IGN);
874 oldQuit = signal (SIGQUIT, SIG_IGN);
875 oldPipe = signal (SIGPIPE, SIG_IGN);
876 oldTerm = signal (SIGTERM, SIG_IGN);
878 move_dir_return = MoveDir (w, from, to, &s1, errorHandler, &realTarget,type);
880 (void) signal (SIGINT, oldInt);
881 (void) signal (SIGQUIT, oldQuit);
882 (void) signal (SIGPIPE, oldPipe);
883 (void) signal (SIGTERM, oldTerm);
885 return (move_dir_return);
888 if (mode == LINK_FILE)
890 /* Need to append the directory name on */
891 (void) strcpy(filename, to);
896 tmp = (char *)XtMalloc(strlen(filename) + 1);
897 strcpy(tmp, filename);
898 /* get the workspace number first */
899 ptr = strrchr(tmp, '/');
901 /* now get the Desktop */
902 ptr = strrchr(tmp, '/');
904 /* if we don't get "/Desktop" then there is another filename
905 attached to the end of the to name passed in */
906 if(strcmp(ptr, "/Desktop") != 0)
911 if( (!restricted && type != TRASH_DIRECTORY) && isContainer)
913 DtLastChar(to, &cptr, &len);
914 if ((len != 1) || (*cptr != '/'))
915 (void) strcat(filename, "/");
918 if(strcmp(from, "/.") == 0 || strcmp(from, "/") == 0)
920 (void) strcat(filename, home_host_name);
921 (void) strcat(filename, ":");
922 (void) strcat(filename, root_title);
924 else if ( (!restricted && type != TRASH_DIRECTORY) && isContainer)
925 (void) strcat(filename, DName(from));
929 if (((link_result = symlink(from, to)) != 0) && errorHandler)
931 if(type == NOT_DESKTOP || errno != EEXIST )
935 tmpStr = GetSharedMessage(CANT_CREATE_ERROR);
936 msg = XtNewString(tmpStr);
937 (*errorHandler) (w, msg, to);
942 return(link_result == 0 ? True : False);
946 if (CheckAccess(from, R_OK) == -1)
949 * A move operation does not require read permission, but a copy does.
951 if (mode == COPY_FILE)
957 tmpStr = GetSharedMessage(CANT_READ_ERROR);
958 msg = XtNewString(tmpStr);
959 (*errorHandler) (w, msg, from);
967 /* Here <from> is a file (not a directory).
968 * Check the <to> part of the command:
970 * <To> can either be an existing file,
971 * an existing directory,
972 * or a new file in an existing directory.
975 if (lstat (to, &s2) >= 0) /* <to> exists */
977 if ((stat (to, &s3) >= 0) &&
978 #if defined(__ultrix) || defined(linux) || \
980 (((s3.st_mode & S_IFMT) == S_IFDIR) /* if is a directory */
981 || ((s3.st_mode & S_IFMT) == S_IFSOCK)) ) /* or a net special */
983 #if defined(SVR4) || defined(_AIX)
984 ((s3.st_mode & S_IFMT) == S_IFDIR) ) /* if is a directory */
986 (((s3.st_mode & S_IFMT) == S_IFDIR) /* if is a directory */
987 || ((s3.st_mode & S_IFMT) == S_IFNWK)) ) /* or a net special */
990 { /* then get file name */
991 (void) strcpy (filename, to);
993 DtLastChar(to, &cptr, &len);
994 if ((len != 1) || (*cptr != '/'))
995 (void) strcat (filename, "/");
997 (void) strcat (filename, DName (from));
1002 if (lstat (to, &s2) >= 0) /* reverify <to> exists */
1004 if ((stat (to, &s3) >= 0) &&
1005 ((s3.st_mode & S_IFMT) == S_IFDIR)) /* if is a directory */
1011 tmpStr = GetSharedMessage(CANT_OVERWRITE_ERROR);
1012 msg = XtNewString(tmpStr);
1013 (*errorHandler) (w, msg, to);
1020 /* <from> = <to> NOOP. */
1022 if (s1.st_dev == s2.st_dev && s1.st_ino == s2.st_ino)
1026 /* no write permission */
1027 if (CheckAccess(to, W_OK) == -1)
1031 link_path = _DtFollowLink(to);
1032 if(strcmp(to,link_path) == 0)
1038 tmpStr = GetSharedMessage(CANT_OVERWRITE_ERROR);
1039 msg = XtNewString(tmpStr);
1040 (*errorHandler) (w, msg, to);
1050 if (unlink (to) < 0)
1056 tmpStr = GetSharedMessage(CANT_OVERWRITE_ERROR);
1057 msg = XtNewString(tmpStr);
1058 (*errorHandler) (w, msg, to);
1068 /* Here <from> is a file and <to> doesn't exist.
1070 * If not a copy, link the files. If the link succeeds, unlink
1071 * <from> and return.
1072 * Copy <from> to <to>.
1073 * If the copy cmd is not specified, unlink <from>.
1076 if (mode != COPY_FILE)
1078 /* Try to maintain symbolic links, except when we're doing a link! */
1079 if (((s1.st_mode & S_IFMT) == S_IFLNK) && (mode != LINK_FILE))
1081 char link_path[MAX_PATH + 1];
1084 if ((link_len = readlink(from, link_path, MAX_PATH)) > 0)
1086 link_path[link_len] = '\0';
1087 link_result = symlink(link_path, to);
1091 /* Fail-safe; do it the hard way */
1092 if (mode == MOVE_FILE)
1093 if (RunFileCommand(MOVE_CMD, from, to, NULL) == 0)
1096 if (RunFileCommand(LINK_CMD, "-s", from, to) == 0)
1104 if (mode == LINK_FILE)
1105 link_result = symlink(from, to);
1110 link_path = _DtFollowLink(from);
1112 if(strcmp(link_path, from) != 0)
1113 link_result = symlink(link_path, to);
1115 link_result = link (from, to);
1119 /* If this was a link, then time to bail out */
1120 if (mode == LINK_FILE)
1122 if ((link_result != 0) && errorHandler)
1126 tmpStr = GetSharedMessage(CANT_CREATE_ERROR);
1127 msg = XtNewString(tmpStr);
1128 (*errorHandler) (w, msg, to);
1132 return(link_result == 0 ? True : False);
1135 /* Unlink source only if this was a move request */
1136 if ((mode == MOVE_FILE) && (link_result >= 0))
1138 if (unlink (from) < 0)
1144 tmpStr = GetSharedMessage(CANT_DELETE_ERROR);
1145 msg = XtNewString(tmpStr);
1146 (*errorHandler) (w, msg, from);
1157 /* unable to read <from> */
1159 if ((fold = open (from, O_RDONLY)) < 0)
1165 tmpStr = GetSharedMessage(CANT_READ_ERROR);
1166 msg = XtNewString(tmpStr);
1167 (*errorHandler) (w, msg, from);
1174 /* unable create <to> */
1177 /* We use the stat buffer info not lstat info */
1178 (void) stat (from, &s4);
1180 if ((fnew = creat (to, (int) s4.st_mode)) < 0)
1186 tmpStr = GetSharedMessage(CANT_CREATE_ERROR);
1187 msg = XtNewString(tmpStr);
1188 (*errorHandler) (w, msg, to);
1191 (void) close (fold);
1198 while (n = read (fold, buf, BLOCK_SIZE))
1206 tmpStr = (GETMESSAGE(11,31, "Error while reading %s"));
1207 msg = XtNewString(tmpStr);
1208 (*errorHandler) (w, msg, to);
1211 (void) close (fold);
1212 (void) close (fnew);
1217 result = write(fnew, buf, n);
1220 (void) close (fold);
1221 (void) close (fnew);
1224 char * strerrormsg = NULL;
1225 char * catmsg = NULL;
1226 char * samsg = NULL;
1228 Boolean unknown = False;
1236 if(mode == COPY_FILE)
1237 tmpStr = (GETMESSAGE(11,51, "Unable to copy the file/folder because\nthe disk quota will be exceeded on the disk\nyou are copying it to."));
1239 tmpStr = (GETMESSAGE(11,52, "Unable to move the file/folder because\nthe disk quota will be exceeded on the disk\nyou are moving it to."));
1240 catmsg = XtNewString(tmpStr);
1246 if(mode == COPY_FILE)
1247 tmpStr = (GETMESSAGE(11,42, "No space available on the\ndevice you are copying to.\n\n"));
1249 tmpStr = (GETMESSAGE(11,43, "No space available on the\ndevice you are moving to.\n"));
1250 catmsg = XtNewString(tmpStr);
1254 sprintf(errnoMsg, "EAGAIN: ");
1255 strerrormsg = strerror(errno);
1258 sprintf(errnoMsg, "EBADF: ");
1259 strerrormsg = strerror(errno);
1262 sprintf(errnoMsg, "EDEADLK: ");
1263 strerrormsg = strerror(errno);
1266 sprintf(errnoMsg, "EINTR: ");
1267 strerrormsg = strerror(errno);
1270 sprintf(errnoMsg, "EIO: ");
1271 strerrormsg = strerror(errno);
1274 sprintf(errnoMsg, "ENOLCK: ");
1275 strerrormsg = strerror(errno);
1278 sprintf(errnoMsg, "EPIPE: ");
1279 strerrormsg = strerror(errno);
1283 sprintf(errnoMsg, "%s", GETMESSAGE(11,56, "(Unknown):"));
1284 strerrormsg = strerror(errno);
1288 /* If catmsg is NULL then one of the miscellanous error's occurred.
1289 * Set up a generic error message which will output the internal
1294 if(mode == COPY_FILE)
1295 tmpStr = (GETMESSAGE(11,53, "The copy of the file/folder failed\ndue to some internal error. The internal\nerror given is:"));
1297 tmpStr = (GETMESSAGE(11,54, "The move of the file/folder failed\ndue to some internal error. The internal\nerror given is:"));
1298 catmsg = XtNewString(tmpStr);
1299 tmpStr = (GETMESSAGE(11,55, "Please see your System Adminstrator"));
1300 samsg = XtNewString(tmpStr);
1303 /* Build a concatination of the possible message parts */
1304 bufLen = (strerrormsg ? strlen(strerrormsg) +
1305 strlen(errnoMsg) + strlen(samsg) : 0) +
1306 strlen(catmsg) + 10;
1307 msg = XtMalloc(bufLen);
1308 strcpy (msg, catmsg);
1311 strcat (msg, "\n\n");
1312 strcat (msg, errnoMsg);
1315 strcat (msg, strerrormsg);
1316 strcat (msg, "\n\n");
1317 strcat (msg, samsg);
1320 (*errorHandler) (w, msg, to);
1329 (void) close (fold);
1330 (void) close (fnew);
1333 /* unlink <from> if not copy */
1335 if (mode == MOVE_FILE)
1337 if (unlink (from) < 0)
1344 ptr = strrchr(from, '/') + 1;
1345 tmpStr = (GETMESSAGE(11,38, "You do not have permission to move %s\nHowever, you can copy the object.\nTo copy an object:\n - press and hold the <Ctrl> key, and\n - drag the object with your mouse.\nOr\n - use 'Copy To' in the 'Selected' menu popup of the menu bar."));
1346 msg = XtNewString(tmpStr);
1347 (*errorHandler) (w, msg, ptr);
1357 * WARNING: this is different from how the shell behaves. If you use
1358 * a shell to copy over an existing file, the file keeps its
1359 * original owner and group; for some historical reason,
1360 * dtfile does it differently.
1361 * UPDATE: This is no longer the case as of 10/31/94, we change the
1362 * file to the original owner and group now. This is to fix
1364 * Also, this call originally occurred after we opened/created
1365 * the file, but before we closed it. This caused problems
1366 * if the user was running as root, and was copying across
1367 * an nfs link, since root access is not typically carried
1368 * across an nfs mount. The result was that we were able to
1369 * create the file, copy to it, but when we tried to close it,
1370 * because the file was now owned by root on the other system,
1371 * we could not close the file; thus, the file ended up empty!
1374 if (mode == COPY_FILE && fileExists)
1377 (void) chmod (to, s3.st_mode);
1378 (void) chown (to, s3.st_uid, s3.st_gid);
1383 (void) chown (to, getuid(), getgid());