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
67 # if defined(linux) || defined(CSRG_BASED)
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, "%s", 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] = '\0';
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) || \
999 (((s3.st_mode & S_IFMT) == S_IFDIR) /* if is a directory */
1000 || ((s3.st_mode & S_IFMT) == S_IFSOCK)) ) /* or a net special */
1002 #if defined(SVR4) || defined(_AIX) || defined(sco)
1003 ((s3.st_mode & S_IFMT) == S_IFDIR) ) /* if is a directory */
1004 #else /* (__hpux) */
1005 (((s3.st_mode & S_IFMT) == S_IFDIR) /* if is a directory */
1006 || ((s3.st_mode & S_IFMT) == S_IFNWK)) ) /* or a net special */
1009 { /* then get file name */
1010 (void) strcpy (filename, to);
1012 DtLastChar(to, &cptr, &len);
1013 if ((len != 1) || (*cptr != '/'))
1014 (void) strcat (filename, "/");
1016 (void) strcat (filename, DName (from));
1021 if (lstat (to, &s2) >= 0) /* reverify <to> exists */
1023 if ((stat (to, &s3) >= 0) &&
1024 ((s3.st_mode & S_IFMT) == S_IFDIR)) /* if is a directory */
1030 tmpStr = GetSharedMessage(CANT_OVERWRITE_ERROR);
1031 msg = XtNewString(tmpStr);
1032 (*errorHandler) (w, msg, to);
1039 /* <from> = <to> NOOP. */
1041 if (s1.st_dev == s2.st_dev && s1.st_ino == s2.st_ino)
1045 /* no write permission */
1046 if (CheckAccess(to, W_OK) == -1)
1050 link_path = _DtFollowLink(to);
1051 if(strcmp(to,link_path) == 0)
1057 tmpStr = GetSharedMessage(CANT_OVERWRITE_ERROR);
1058 msg = XtNewString(tmpStr);
1059 (*errorHandler) (w, msg, to);
1069 if (unlink (to) < 0)
1075 tmpStr = GetSharedMessage(CANT_OVERWRITE_ERROR);
1076 msg = XtNewString(tmpStr);
1077 (*errorHandler) (w, msg, to);
1087 /* Here <from> is a file and <to> doesn't exist.
1089 * If not a copy, link the files. If the link succeeds, unlink
1090 * <from> and return.
1091 * Copy <from> to <to>.
1092 * If the copy cmd is not specified, unlink <from>.
1095 if (mode != COPY_FILE)
1097 /* Try to maintain symbolic links, except when we're doing a link! */
1098 if (((s1.st_mode & S_IFMT) == S_IFLNK) && (mode != LINK_FILE))
1100 char link_path[MAX_PATH + 1];
1103 if ((link_len = readlink(from, link_path, MAX_PATH)) > 0)
1105 link_path[link_len] = '\0';
1106 link_result = symlink(link_path, to);
1110 /* Fail-safe; do it the hard way */
1111 if (mode == MOVE_FILE)
1112 if (RunFileCommand(MOVE_CMD, from, to, NULL) == 0)
1115 if (RunFileCommand(LINK_CMD, "-s", from, to) == 0)
1123 if (mode == LINK_FILE)
1124 link_result = symlink(from, to);
1129 link_path = _DtFollowLink(from);
1131 if(strcmp(link_path, from) != 0)
1132 link_result = symlink(link_path, to);
1134 link_result = link (from, to);
1138 /* If this was a link, then time to bail out */
1139 if (mode == LINK_FILE)
1141 if ((link_result != 0) && errorHandler)
1145 tmpStr = GetSharedMessage(CANT_CREATE_ERROR);
1146 msg = XtNewString(tmpStr);
1147 (*errorHandler) (w, msg, to);
1151 return(link_result == 0 ? True : False);
1154 /* Unlink source only if this was a move request */
1155 if ((mode == MOVE_FILE) && (link_result >= 0))
1157 if (unlink (from) < 0)
1163 tmpStr = GetSharedMessage(CANT_DELETE_ERROR);
1164 msg = XtNewString(tmpStr);
1165 (*errorHandler) (w, msg, from);
1176 /* unable to read <from> */
1178 if ((fold = open (from, O_RDONLY)) < 0)
1184 tmpStr = GetSharedMessage(CANT_READ_ERROR);
1185 msg = XtNewString(tmpStr);
1186 (*errorHandler) (w, msg, from);
1193 /* unable create <to> */
1196 /* We use the stat buffer info not lstat info */
1197 (void) stat (from, &s4);
1199 if ((fnew = creat (to, (int) s4.st_mode)) < 0)
1205 tmpStr = GetSharedMessage(CANT_CREATE_ERROR);
1206 msg = XtNewString(tmpStr);
1207 (*errorHandler) (w, msg, to);
1210 (void) close (fold);
1217 while (n = read (fold, buf, BLOCK_SIZE))
1225 tmpStr = (GETMESSAGE(11,31, "Error while reading %s"));
1226 msg = XtNewString(tmpStr);
1227 (*errorHandler) (w, msg, to);
1230 (void) close (fold);
1231 (void) close (fnew);
1236 result = write(fnew, buf, n);
1239 (void) close (fold);
1240 (void) close (fnew);
1243 char * strerrormsg = NULL;
1244 char * catmsg = NULL;
1245 char * samsg = NULL;
1247 Boolean unknown = False;
1255 if(mode == COPY_FILE)
1256 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."));
1258 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."));
1259 catmsg = XtNewString(tmpStr);
1265 if(mode == COPY_FILE)
1266 tmpStr = (GETMESSAGE(11,42, "No space available on the\ndevice you are copying to.\n\n"));
1268 tmpStr = (GETMESSAGE(11,43, "No space available on the\ndevice you are moving to.\n"));
1269 catmsg = XtNewString(tmpStr);
1273 sprintf(errnoMsg, "EAGAIN: ");
1274 strerrormsg = strerror(errno);
1277 sprintf(errnoMsg, "EBADF: ");
1278 strerrormsg = strerror(errno);
1281 sprintf(errnoMsg, "EDEADLK: ");
1282 strerrormsg = strerror(errno);
1285 sprintf(errnoMsg, "EINTR: ");
1286 strerrormsg = strerror(errno);
1289 sprintf(errnoMsg, "EIO: ");
1290 strerrormsg = strerror(errno);
1293 sprintf(errnoMsg, "ENOLCK: ");
1294 strerrormsg = strerror(errno);
1297 sprintf(errnoMsg, "EPIPE: ");
1298 strerrormsg = strerror(errno);
1302 sprintf(errnoMsg, "%s", GETMESSAGE(11,56, "(Unknown):"));
1303 strerrormsg = strerror(errno);
1307 /* If catmsg is NULL then one of the miscellanous error's occured.
1308 * Set up a generic error message which will output the internal
1313 if(mode == COPY_FILE)
1314 tmpStr = (GETMESSAGE(11,53, "The copy of the file/folder failed\ndue to some internal error. The internal\nerror given is:"));
1316 tmpStr = (GETMESSAGE(11,54, "The move of the file/folder failed\ndue to some internal error. The internal\nerror given is:"));
1317 catmsg = XtNewString(tmpStr);
1318 tmpStr = (GETMESSAGE(11,55, "Please see your System Adminstrator"));
1319 samsg = XtNewString(tmpStr);
1322 /* Build a concatination of the possible message parts */
1323 bufLen = (strerrormsg ? strlen(strerrormsg) +
1324 strlen(errnoMsg) + strlen(samsg) : 0) +
1325 strlen(catmsg) + 10;
1326 msg = XtMalloc(bufLen);
1327 strcpy (msg, catmsg);
1330 strcat (msg, "\n\n");
1331 strcat (msg, errnoMsg);
1334 strcat (msg, strerrormsg);
1335 strcat (msg, "\n\n");
1336 strcat (msg, samsg);
1339 (*errorHandler) (w, msg, to);
1348 (void) close (fold);
1349 (void) close (fnew);
1352 /* unlink <from> if not copy */
1354 if (mode == MOVE_FILE)
1356 if (unlink (from) < 0)
1363 ptr = strrchr(from, '/') + 1;
1364 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."));
1365 msg = XtNewString(tmpStr);
1366 (*errorHandler) (w, msg, ptr);
1376 * WARNING: this is different from how the shell behaves. If you use
1377 * a shell to copy over an existing file, the file keeps its
1378 * original owner and group; for some historical reason,
1379 * dtfile does it differently.
1380 * UPDATE: This is no longer the case as of 10/31/94, we change the
1381 * file to the original owner and group now. This is to fix
1383 * Also, this call originally occurred after we opened/created
1384 * the file, but before we closed it. This caused problems
1385 * if the user was running as root, and was copying across
1386 * an nfs link, since root access is not typically carried
1387 * across an nfs mount. The result was that we were able to
1388 * create the file, copy to it, but when we tried to close it,
1389 * because the file was now owned by root on the other system,
1390 * we could not close the file; thus, the file ended up empty!
1393 if (mode == COPY_FILE && fileExists)
1396 (void) chmod (to, s3.st_mode);
1397 (void) chown (to, s3.st_uid, s3.st_gid);
1402 (void) chown (to, getuid(), getgid());