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 librararies 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 ************************************<+>*************************************/
54 #if defined(SVR4) || defined(sco)
55 # if defined(USL) || defined(sco) || defined(__uxp__)
56 # include <sys/param.h>
57 # include <sys/types.h>
60 # include <sys/fs/s5param.h>
61 # define ROOTINO S5ROOTINO
63 # include <sys/fs/ufs_fs.h>
64 # define ROOTINO UFSROOTINO
70 # include <sys/param.h>
71 #endif /* SVR4 || sco */
73 #include <sys/types.h>
81 /** The following ifdefs need to be straightened out
95 #include <sys/access.h>
107 #endif /* __ultrix */
108 #endif /* __hp_osf */
117 #include <Xm/MwmUtil.h>
119 #include <Dt/DtP.h> /* required for DtDirPaths type */
120 #include <Dt/Connect.h>
121 #include <Dt/DtNlUtils.h>
124 #include "SharedProcs.h"
129 #include "SharedMsgs.h"
131 #ifndef CDE_INSTALLATION_TOP
132 #define CDE_INSTALLATION_TOP "/usr/dt"
135 /* Local Function Definitions */
136 static char * MOVE_CMD = "/bin/mv";
137 static char * LINK_CMD = "/bin/ln";
138 static char * REMOVE_CMD = "/bin/rm";
139 static char * DTCOPY = CDE_INSTALLATION_TOP "/bin/dtfile_copy";
142 /************************************************************************
146 ************************************************************************/
156 #if defined(__hp_osf) || defined(__ultrix)
157 /*--------------------------------------------------------------------
158 * access code for __hp_osf, __ultrix
159 *------------------------------------------------------------------*/
161 setreuid(geteuid(),-1);
162 return access (fname, what);
166 /*--------------------------------------------------------------------
167 * access code for BLS
168 *------------------------------------------------------------------*/
170 setresuid(geteuid(),-1,-1);
171 return access (fname, what);
173 #else /* the rest of the OS's */
175 save_ruid = getuid();
178 setreuid(geteuid(),-1);
183 save_rgid = getgid();
186 setregid(getegid(),-1);
191 access_priv = access (fname, what);
194 setreuid(save_ruid,-1);
195 setregid(save_rgid,-1);
203 #endif /* Apollo & OSF */
207 /************************************************************************
210 * Display an error message.
212 ************************************************************************/
223 if (message2 != NULL)
225 message_buf = XtMalloc(strlen(message1) + strlen(message2) + 1);
226 (void) sprintf(message_buf,message1, message2);
230 message_buf = XtMalloc(strlen(message1) + 1);
231 (void) sprintf(message_buf,message1);
234 /* Display an error dialog */
235 tmpStr = GetSharedMessage(FILE_MANIPULATION_ERROR_TITLE);
236 title = XtNewString(tmpStr);
237 _DtMessage (w, title, message_buf, NULL, HelpRequestCB);
243 /************************************************************************
246 * Returns the file name of its argument.
247 * Keep looking thru the string until a "/" is found which still
248 * has some characters after it.
250 ************************************************************************/
253 register char *name )
262 q = DtStrchr(q, '/');
276 /************************************************************************
280 ************************************************************************/
285 register ino_t dinode,
287 void (*errorHandler)() )
290 char filename [MAX_PATH];
296 (void) strcpy (filename, spth);
298 while (sbuf.st_ino != ROOTINO)
300 if (lstat (filename, &sbuf) < 0)
304 tmpStr = (GETMESSAGE(11,33, "Cannot open %s"));
305 msg = XtNewString(tmpStr);
306 (*errorHandler) (w, msg, filename);
312 if (sbuf.st_ino == dinode)
316 if (mode == COPY_FILE)
317 tmpStr = GETMESSAGE(11,35, "Cannot copy a folder into itself.");
319 tmpStr = GETMESSAGE(11,16, "A folder cannot be moved into itself.\n%s");
320 msg = XtNewString(tmpStr);
321 if (mode == COPY_FILE)
322 (*errorHandler) (w, msg, NULL);
324 (*errorHandler) (w, msg, filename);
330 (void) strcat (filename, "/..");
337 /************************************************************************
341 ************************************************************************/
346 register char *source,
347 register char *target,
348 struct stat *sourceStatInfo,
349 void (*errorHandler)(),
353 static char *pname = "MoveDir";
356 char * targetDir; /* original target dir path */
360 struct stat s1; /* status of from file */
361 struct stat s2; /* status of to file */
365 static char buf [BUF_SIZE]; /* generic buffer */
366 char filename [MAX_PATH]; /* buffer to hold the full file name */
371 /* Copy target so we have it for an error dialog if we need it */
372 targetDir = XtNewString(target);
375 if ((val = stat (target, &s2)) < 0)
376 val = lstat(target, &s2);
378 /* Check if move to itself */
379 if( sourceStatInfo->st_dev == s2.st_dev)
381 if (Check (w, target, sourceStatInfo->st_ino, MOVE_FILE, NULL ))
385 if (val >= 0) /* target exists */
387 if ((s2.st_mode & S_IFMT) != S_IFDIR) /* target not directory */
392 tmpStr = GetSharedMessage(CANT_OVERWRITE_ERROR);
393 msg = XtNewString(tmpStr);
394 (*errorHandler) (w, msg, target);
401 (void) strcpy (buf, target);
405 DtLastChar(buf, &cptr, &len);
406 if ((len != 1) || (*cptr != '/'))
407 (void) strcat (buf, "/");
408 (void) strcat (buf, DName (source));
410 if (lstat (target, &s2) >= 0) /* new target exists */
416 tmpStr = GetSharedMessage(CANT_OVERWRITE_ERROR);
417 msg = XtNewString(tmpStr);
418 (*errorHandler) (w, msg, target);
429 /* don't rename these */
430 DtLastChar(p, &cptr, &len);
432 if (!strcmp (p, ".") || !strcmp (p, "..") ||
433 !strcmp (p, "") || ((len == 1) && (*cptr == '/')))
439 tmpStr = (GETMESSAGE(11,32, "Cannot rename %s"));
440 msg = XtNewString(tmpStr);
441 (*errorHandler) (w, msg, p);
449 /* parent doesn't exist */
450 if((val = stat (_DtPName (source), &s1)) < 0)
451 val = lstat (_DtPName (source), &s1);
453 if((val1 = stat (_DtPName (target), &s2)) < 0)
454 val1 = lstat (_DtPName (target), &s2);
456 if (val < 0 || val1 < 0)
460 tmpStr = GETMESSAGE(11, 14, "Cannot find the folders location.");
461 msg = XtNewString(tmpStr);
462 (*errorHandler) (w, msg, NULL);
470 /* check for target parent not writeable */
471 if (CheckAccess(_DtPName (target), W_OK) == -1)
477 tmpStr = GetSharedMessage(CANT_WRITE_ERROR);
478 msg = XtNewString(tmpStr);
479 (*errorHandler) (w, msg, targetDir);
487 /* check for source parent not writeable */
488 if (CheckAccess(_DtPName (source), W_OK) == -1)
494 tmpStr = GetSharedMessage(CANT_WRITE_ERROR);
495 msg = XtNewString(tmpStr);
496 (*errorHandler) (w, msg, source);
503 if (((sourceStatInfo->st_mode & S_IFMT) == S_IFDIR) &&
504 (CheckAccess(source, W_OK) != 0))
510 tmpStr=GETMESSAGE(11, 57,"You do not have permission to move the folder\n%s\nWrite permission is required.");
511 msg = XtMalloc(strlen(tmpStr) + strlen(source) + 2);
512 sprintf(msg, tmpStr, source);
513 (*errorHandler) (w, msg, source);
520 /* if parents are not on the same device, do a copy & delete */
521 if (s1.st_dev != s2.st_dev)
523 /* Determine correct Geometry Placement fo Move Dialog */
524 /* @@@ ... to be added */
531 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.");
532 msg = XtNewString(tmpStr);
533 (*errorHandler) (w, msg, NULL);
542 DBGFORK(("%s: child forked\n", pname));
544 /* pass in geometry, and other command lines params when available */
545 if(type == TRASH_DIRECTORY)
546 rc = execlp(DTCOPY, "dtfile_copy", "-move", "-confirmReplace",
547 "-confirmErrors", "-popDown","-checkPerms", source, target, 0);
549 rc = execlp(DTCOPY, "dtfile_copy", "-move", "-confirmReplace",
550 "-confirmErrors", "-popDown", source, target, 0);
552 /* call errorhandler */
553 perror ("Could not exec child process \"dtfile_copy\"");
555 DBGFORK(("%s: child exiting\n", pname));
560 DBGFORK(("%s: forked child<%d>\n", pname, child_pid));
567 link_path = _DtFollowLink(source);
570 if (s1.st_ino != s2.st_ino)
571 { /* different parent inodes */
572 (void) lstat (source, &s1); /* get source dir ino */
575 if (Check (w, _DtPName (target), s1.st_ino, MOVE_FILE, errorHandler))
576 { /* move into self */
582 /* This part of code was implemented with the idea that the links
583 to be treated differently. So, it has to be uncommented whenever
584 links are handled differently (i.e., moving a link shall move the
587 if(strcmp(link_path, source) != 0)
589 if (RunFileCommand (MOVE_CMD, link_path, target, NULL) == 0)
598 if (RunFileCommand (MOVE_CMD, source, target, NULL) == 0)
610 /************************************************************************
614 ************************************************************************/
623 void (*errorHandler)(),
624 Boolean checkForBusyDir,
627 static char *pname = "CopyDir";
630 char target [MAX_PATH]; /* buffer to hold the full file name */
631 char target_dir [MAX_PATH], target_file [MAX_PATH];
632 struct stat s2; /* status of to file */
633 int child_pid, rc, target_rc;
636 /* Check if source is readable */
637 if (CheckAccess(from, R_OK) == -1)
641 tmpStr = GetSharedMessage(CANT_READ_ERROR);
642 msg = XtNewString(tmpStr);
643 (*errorHandler) (w, msg, from);
649 /* generate target name */
650 /* "to" can be something to copy the source into (isContainer=TRUE) */
651 /* or it can be the full path of the destination (isContainer=FALSE) */
652 /* the former case is probably more common (e.g. a drag&drop copy) */
653 /* whereas the second case occurs when, for example, the menu is */
654 /* to copy directory /u/joe/a to /u/joe/b (not doable with d&d) */
655 (void) strcpy (target, to);
658 DtLastChar(to, &cptr, &len);
659 if ((len != 1) || (*cptr != '/'))
660 (void) strcat (target, "/");
661 (void) strcat (target, DName (from));
663 split_path(target, target_dir, target_file);
665 /* Check if target directory exists */
666 if ((target_rc = stat (target, &s2)) < 0)
667 target_rc = lstat(target, &s2);
672 * make sure it's a directory */
674 if ((s2.st_mode & S_IFMT) != S_IFDIR) /* target not directory */
678 tmpStr = GetSharedMessage(CANT_OVERWRITE_ERROR);
679 msg = XtNewString(tmpStr);
680 (*errorHandler) (w, msg, target);
688 /* target does not exist:
689 * make sure the "to" directory exists and is writable */
690 if ((rc = stat (target_dir, &s2)) < 0)
691 rc = lstat(target_dir, &s2);
693 if (rc < 0 || (s2.st_mode & S_IFMT) != S_IFDIR)
697 tmpStr = GETMESSAGE(11, 14, "Cannot find the folders location.");
698 msg = XtNewString(tmpStr);
699 (*errorHandler) (w, msg, NULL);
705 if (CheckAccess(target_dir, W_OK) == -1)
709 tmpStr = GetSharedMessage(CANT_WRITE_ERROR);
710 msg = XtNewString(tmpStr);
711 (*errorHandler) (w, msg, to);
718 /* Determine if we are attempting a copy into self */
719 if (s1->st_dev == s2.st_dev)
723 if (Check (w, to, s1->st_ino, COPY_FILE, errorHandler))
726 else /* destination dir does not exist, look at its proposed parent */
728 if (Check (w, target_dir, s1->st_ino, COPY_FILE, errorHandler))
733 /* Determine correct Geometry Placement fo Copy Dialog */
734 /* @@@ ... to be added */
736 /* If all the above checks have passed, then fork off the copy dialog */
743 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.");
744 msg = XtNewString(tmpStr);
745 (*errorHandler) (w, msg, NULL);
753 DBGFORK(("%s: child forked\n", pname));
755 /* pass in geometry, and other command lines params when available */
756 if (mode == MERGE_DIR)
757 /* merge source & target directories */
758 rc = execlp(DTCOPY, "dtfile_copy",
759 "-dontDelete", "-forceCopies", "-copyTop",
760 "-confirmReplace", "-confirmErrors", "-popDown",
763 /* replace target dir */
764 rc = execlp(DTCOPY, "dtfile_copy",
765 "-forceCopies", "-copyTop",
766 "-confirmErrors", "-popDown",
769 /* call errorhandler */
770 perror ("Could not exec child process \"dtfile_copy\"");
772 DBGFORK(("%s: child exiting\n", pname));
777 DBGFORK(("%s: forked child<%d>\n", pname, child_pid));
784 /************************************************************************
788 ************************************************************************/
795 Boolean isContainer, /* described in function CopyDir */
796 void (*errorHandler)(),
797 Boolean checkForBusyDir,
803 Boolean copy_dir_return;
804 Boolean move_dir_return;
811 Boolean restricted = False;
812 Boolean fileExists = False;
814 struct stat s1; /* status of from file e.g. lstat info */
815 struct stat s4; /* status of from file e.g. stat info */
816 struct stat s2; /* status of to file e.g. stat info */
817 struct stat s3; /* status of to file e.g. lstat info */
819 char buf [BLOCK_SIZE]; /* generic buffer */
820 char filename [MAX_PATH]; /* buffer to hold the full file name */
827 /* Check the <from> part of the command:
829 * Report error if <from> doesn't exist.
830 * Else error if <from> hasn't read access.
833 DPRINTF(("FileManip: mode %d type %d from \"%s\" to \"%s\"\n", mode, type, from, to));
834 if (stat (from, &s1) < 0)
836 if (lstat (from, &s1) < 0)
840 tmpStr = (GETMESSAGE(11,28, "%s cannot be found."));
841 msg = XtNewString(tmpStr);
842 (*errorHandler) (w, msg, from);
849 /* We will check if we need to initiate a copy of a directory */
850 if ((s1.st_mode & S_IFMT) == S_IFDIR) /* from is a directory */
852 if (mode == COPY_FILE || mode == MERGE_DIR)
854 oldInt = signal (SIGINT, SIG_IGN);
855 oldQuit = signal (SIGQUIT, SIG_IGN);
856 oldPipe = signal (SIGPIPE, SIG_IGN);
857 oldTerm = signal (SIGTERM, SIG_IGN);
859 copy_dir_return = CopyDir(w, mode, from, to, isContainer, &s1,
860 errorHandler, checkForBusyDir, type);
862 (void) signal (SIGINT, oldInt);
863 (void) signal (SIGQUIT, oldQuit);
864 (void) signal (SIGPIPE, oldPipe);
865 (void) signal (SIGTERM, oldTerm);
867 return (copy_dir_return);
871 /* If the directory has more than one open view or open views */
872 /* of sub directories. Then do not allow the move or rename. */
874 if (mode == MOVE_FILE)
876 if (checkForBusyDir && DirectoryBusy (from))
880 char message_buf[512];
883 message_buf[0] = NULL;
884 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."));
885 sprintf (message_buf, tmpStr, from);
886 (*errorHandler) (w, message_buf, NULL);
892 oldInt = signal (SIGINT, SIG_IGN);
893 oldQuit = signal (SIGQUIT, SIG_IGN);
894 oldPipe = signal (SIGPIPE, SIG_IGN);
895 oldTerm = signal (SIGTERM, SIG_IGN);
897 move_dir_return = MoveDir (w, from, to, &s1, errorHandler, &realTarget,type);
899 (void) signal (SIGINT, oldInt);
900 (void) signal (SIGQUIT, oldQuit);
901 (void) signal (SIGPIPE, oldPipe);
902 (void) signal (SIGTERM, oldTerm);
904 return (move_dir_return);
907 if (mode == LINK_FILE)
909 /* Need to append the directory name on */
910 (void) strcpy(filename, to);
915 tmp = (char *)XtMalloc(strlen(filename) + 1);
916 strcpy(tmp, filename);
917 /* get the workspace number first */
918 ptr = strrchr(tmp, '/');
920 /* now get the Desktop */
921 ptr = strrchr(tmp, '/');
923 /* if we don't get "/Desktop" then there is another filename
924 attached to the end of the to name passed in */
925 if(strcmp(ptr, "/Desktop") != 0)
930 if( (!restricted && type != TRASH_DIRECTORY) && isContainer)
932 DtLastChar(to, &cptr, &len);
933 if ((len != 1) || (*cptr != '/'))
934 (void) strcat(filename, "/");
937 if(strcmp(from, "/.") == 0 || strcmp(from, "/") == 0)
939 (void) strcat(filename, home_host_name);
940 (void) strcat(filename, ":");
941 (void) strcat(filename, root_title);
943 else if ( (!restricted && type != TRASH_DIRECTORY) && isContainer)
944 (void) strcat(filename, DName(from));
948 if (((link_result = symlink(from, to)) != 0) && errorHandler)
950 if(type == NOT_DESKTOP || errno != EEXIST )
954 tmpStr = GetSharedMessage(CANT_CREATE_ERROR);
955 msg = XtNewString(tmpStr);
956 (*errorHandler) (w, msg, to);
961 return(link_result == 0 ? True : False);
965 if (CheckAccess(from, R_OK) == -1)
968 * A move operation does not require read permission, but a copy does.
970 if (mode == COPY_FILE)
976 tmpStr = GetSharedMessage(CANT_READ_ERROR);
977 msg = XtNewString(tmpStr);
978 (*errorHandler) (w, msg, from);
986 /* Here <from> is a file (not a directory).
987 * Check the <to> part of the command:
989 * <To> can either be an existing file,
990 * an existing directory,
991 * or a new file in an existing directory.
994 if (lstat (to, &s2) >= 0) /* <to> exists */
996 if ((stat (to, &s3) >= 0) &&
997 #if defined(__hp_osf) || (__ultrix) || defined(__osf__) || defined(linux)
998 (((s3.st_mode & S_IFMT) == S_IFDIR) /* if is a directory */
999 || ((s3.st_mode & S_IFMT) == S_IFSOCK)) ) /* or a net special */
1001 #if defined(SVR4) || defined(_AIX) || defined(sco)
1002 ((s3.st_mode & S_IFMT) == S_IFDIR) ) /* if is a directory */
1003 #else /* (__hpux) */
1004 (((s3.st_mode & S_IFMT) == S_IFDIR) /* if is a directory */
1005 || ((s3.st_mode & S_IFMT) == S_IFNWK)) ) /* or a net special */
1008 { /* then get file name */
1009 (void) strcpy (filename, to);
1011 DtLastChar(to, &cptr, &len);
1012 if ((len != 1) || (*cptr != '/'))
1013 (void) strcat (filename, "/");
1015 (void) strcat (filename, DName (from));
1020 if (lstat (to, &s2) >= 0) /* reverify <to> exists */
1022 if ((stat (to, &s3) >= 0) &&
1023 ((s3.st_mode & S_IFMT) == S_IFDIR)) /* if is a directory */
1029 tmpStr = GetSharedMessage(CANT_OVERWRITE_ERROR);
1030 msg = XtNewString(tmpStr);
1031 (*errorHandler) (w, msg, to);
1038 /* <from> = <to> NOOP. */
1040 if (s1.st_dev == s2.st_dev && s1.st_ino == s2.st_ino)
1044 /* no write permission */
1045 if (CheckAccess(to, W_OK) == -1)
1049 link_path = _DtFollowLink(to);
1050 if(strcmp(to,link_path) == 0)
1056 tmpStr = GetSharedMessage(CANT_OVERWRITE_ERROR);
1057 msg = XtNewString(tmpStr);
1058 (*errorHandler) (w, msg, to);
1068 if (unlink (to) < 0)
1074 tmpStr = GetSharedMessage(CANT_OVERWRITE_ERROR);
1075 msg = XtNewString(tmpStr);
1076 (*errorHandler) (w, msg, to);
1086 /* Here <from> is a file and <to> doesn't exist.
1088 * If not a copy, link the files. If the link succeeds, unlink
1089 * <from> and return.
1090 * Copy <from> to <to>.
1091 * If the copy cmd is not specified, unlink <from>.
1094 if (mode != COPY_FILE)
1096 /* Try to maintain symbolic links, except when we're doing a link! */
1097 if (((s1.st_mode & S_IFMT) == S_IFLNK) && (mode != LINK_FILE))
1099 char link_path[MAX_PATH + 1];
1102 if ((link_len = readlink(from, link_path, MAX_PATH)) > 0)
1104 link_path[link_len] = '\0';
1105 link_result = symlink(link_path, to);
1109 /* Fail-safe; do it the hard way */
1110 if (mode == MOVE_FILE)
1111 if (RunFileCommand(MOVE_CMD, from, to, NULL) == 0)
1114 if (RunFileCommand(LINK_CMD, "-s", from, to) == 0)
1122 if (mode == LINK_FILE)
1123 link_result = symlink(from, to);
1128 link_path = _DtFollowLink(from);
1130 if(strcmp(link_path, from) != 0)
1131 link_result = symlink(link_path, to);
1133 link_result = link (from, to);
1137 /* If this was a link, then time to bail out */
1138 if (mode == LINK_FILE)
1140 if ((link_result != 0) && errorHandler)
1144 tmpStr = GetSharedMessage(CANT_CREATE_ERROR);
1145 msg = XtNewString(tmpStr);
1146 (*errorHandler) (w, msg, to);
1150 return(link_result == 0 ? True : False);
1153 /* Unlink source only if this was a move request */
1154 if ((mode == MOVE_FILE) && (link_result >= 0))
1156 if (unlink (from) < 0)
1162 tmpStr = GetSharedMessage(CANT_DELETE_ERROR);
1163 msg = XtNewString(tmpStr);
1164 (*errorHandler) (w, msg, from);
1175 /* unable to read <from> */
1177 if ((fold = open (from, O_RDONLY)) < 0)
1183 tmpStr = GetSharedMessage(CANT_READ_ERROR);
1184 msg = XtNewString(tmpStr);
1185 (*errorHandler) (w, msg, from);
1192 /* unable create <to> */
1195 /* We use the stat buffer info not lstat info */
1196 (void) stat (from, &s4);
1198 if ((fnew = creat (to, (int) s4.st_mode)) < 0)
1204 tmpStr = GetSharedMessage(CANT_CREATE_ERROR);
1205 msg = XtNewString(tmpStr);
1206 (*errorHandler) (w, msg, to);
1209 (void) close (fold);
1216 while (n = read (fold, buf, BLOCK_SIZE))
1224 tmpStr = (GETMESSAGE(11,31, "Error while reading %s"));
1225 msg = XtNewString(tmpStr);
1226 (*errorHandler) (w, msg, to);
1229 (void) close (fold);
1230 (void) close (fnew);
1235 result = write(fnew, buf, n);
1238 (void) close (fold);
1239 (void) close (fnew);
1242 char * strerrormsg = NULL;
1243 char * catmsg = NULL;
1244 char * samsg = NULL;
1246 Boolean unknown = False;
1254 if(mode == COPY_FILE)
1255 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."));
1257 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."));
1258 catmsg = XtNewString(tmpStr);
1264 if(mode == COPY_FILE)
1265 tmpStr = (GETMESSAGE(11,42, "No space available on the\ndevice you are copying to.\n\n"));
1267 tmpStr = (GETMESSAGE(11,43, "No space available on the\ndevice you are moving to.\n"));
1268 catmsg = XtNewString(tmpStr);
1272 sprintf(errnoMsg, "EAGAIN: ");
1273 strerrormsg = strerror(errno);
1276 sprintf(errnoMsg, "EBADF: ");
1277 strerrormsg = strerror(errno);
1280 sprintf(errnoMsg, "EDEADLK: ");
1281 strerrormsg = strerror(errno);
1284 sprintf(errnoMsg, "EINTR: ");
1285 strerrormsg = strerror(errno);
1288 sprintf(errnoMsg, "EIO: ");
1289 strerrormsg = strerror(errno);
1292 sprintf(errnoMsg, "ENOLCK: ");
1293 strerrormsg = strerror(errno);
1296 sprintf(errnoMsg, "EPIPE: ");
1297 strerrormsg = strerror(errno);
1301 sprintf(errnoMsg, GETMESSAGE(11,56, "(Unknown):"));
1302 strerrormsg = strerror(errno);
1306 /* If catmsg is NULL then one of the miscellanous error's occured.
1307 * Set up a generic error message which will output the internal
1312 if(mode == COPY_FILE)
1313 tmpStr = (GETMESSAGE(11,53, "The copy of the file/folder failed\ndue to some internal error. The internal\nerror given is:"));
1315 tmpStr = (GETMESSAGE(11,54, "The move of the file/folder failed\ndue to some internal error. The internal\nerror given is:"));
1316 catmsg = XtNewString(tmpStr);
1317 tmpStr = (GETMESSAGE(11,55, "Please see your System Adminstrator"));
1318 samsg = XtNewString(tmpStr);
1321 /* Build a concatination of the possible message parts */
1322 bufLen = (strerrormsg ? strlen(strerrormsg) +
1323 strlen(errnoMsg) + strlen(samsg) : 0) +
1324 strlen(catmsg) + 10;
1325 msg = XtMalloc(bufLen);
1326 strcpy (msg, catmsg);
1329 strcat (msg, "\n\n");
1330 strcat (msg, errnoMsg);
1333 strcat (msg, strerrormsg);
1334 strcat (msg, "\n\n");
1335 strcat (msg, samsg);
1338 (*errorHandler) (w, msg, to);
1347 (void) close (fold);
1348 (void) close (fnew);
1351 /* unlink <from> if not copy */
1353 if (mode == MOVE_FILE)
1355 if (unlink (from) < 0)
1362 ptr = strrchr(from, '/') + 1;
1363 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."));
1364 msg = XtNewString(tmpStr);
1365 (*errorHandler) (w, msg, ptr);
1375 * WARNING: this is different from how the shell behaves. If you use
1376 * a shell to copy over an existing file, the file keeps its
1377 * original owner and group; for some historical reason,
1378 * dtfile does it differently.
1379 * UPDATE: This is no longer the case as of 10/31/94, we change the
1380 * file to the original owner and group now. This is to fix
1382 * Also, this call originally occurred after we opened/created
1383 * the file, but before we closed it. This caused problems
1384 * if the user was running as root, and was copying across
1385 * an nfs link, since root access is not typically carried
1386 * across an nfs mount. The result was that we were able to
1387 * create the file, copy to it, but when we tried to close it,
1388 * because the file was now owned by root on the other system,
1389 * we could not close the file; thus, the file ended up empty!
1392 if (mode == COPY_FILE && fileExists)
1395 (void) chmod (to, s3.st_mode);
1396 (void) chown (to, s3.st_uid, s3.st_gid);
1401 (void) chown (to, getuid(), getgid());