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>
122 #include <Dt/SharedProcs.h>
125 #include "SharedProcs.h"
130 #include "SharedMsgs.h"
132 #ifndef CDE_INSTALLATION_TOP
133 #define CDE_INSTALLATION_TOP "/usr/dt"
136 /* Local Function Definitions */
137 static char * MOVE_CMD = "/bin/mv";
138 static char * LINK_CMD = "/bin/ln";
139 static char * REMOVE_CMD = "/bin/rm";
140 static char * DTCOPY = CDE_INSTALLATION_TOP "/bin/dtfile_copy";
143 /************************************************************************
147 ************************************************************************/
157 #if defined(__hp_osf) || defined(__ultrix)
158 /*--------------------------------------------------------------------
159 * access code for __hp_osf, __ultrix
160 *------------------------------------------------------------------*/
162 setreuid(geteuid(),-1);
163 return access (fname, what);
167 /*--------------------------------------------------------------------
168 * access code for BLS
169 *------------------------------------------------------------------*/
171 setresuid(geteuid(),-1,-1);
172 return access (fname, what);
174 #else /* the rest of the OS's */
176 save_ruid = getuid();
179 setreuid(geteuid(),-1);
184 save_rgid = getgid();
187 setregid(getegid(),-1);
192 access_priv = access (fname, what);
195 setreuid(save_ruid,-1);
196 setregid(save_rgid,-1);
204 #endif /* Apollo & OSF */
208 /************************************************************************
211 * Display an error message.
213 ************************************************************************/
224 if (message2 != NULL)
226 message_buf = XtMalloc(strlen(message1) + strlen(message2) + 1);
227 (void) sprintf(message_buf,message1, message2);
231 message_buf = XtMalloc(strlen(message1) + 1);
232 (void) sprintf(message_buf, "%s", message1);
235 /* Display an error dialog */
236 tmpStr = GetSharedMessage(FILE_MANIPULATION_ERROR_TITLE);
237 title = XtNewString(tmpStr);
238 _DtMessage (w, title, message_buf, NULL, HelpRequestCB);
244 /************************************************************************
247 * Returns the file name of its argument.
248 * Keep looking thru the string until a "/" is found which still
249 * has some characters after it.
251 ************************************************************************/
254 register char *name )
263 q = DtStrchr(q, '/');
277 /************************************************************************
281 ************************************************************************/
286 register ino_t dinode,
288 void (*errorHandler)() )
291 char filename [MAX_PATH];
297 (void) strcpy (filename, spth);
299 while (sbuf.st_ino != ROOTINO)
301 if (lstat (filename, &sbuf) < 0)
305 tmpStr = (GETMESSAGE(11,33, "Cannot open %s"));
306 msg = XtNewString(tmpStr);
307 (*errorHandler) (w, msg, filename);
313 if (sbuf.st_ino == dinode)
317 if (mode == COPY_FILE)
318 tmpStr = GETMESSAGE(11,35, "Cannot copy a folder into itself.");
320 tmpStr = GETMESSAGE(11,16, "A folder cannot be moved into itself.\n%s");
321 msg = XtNewString(tmpStr);
322 if (mode == COPY_FILE)
323 (*errorHandler) (w, msg, NULL);
325 (*errorHandler) (w, msg, filename);
331 (void) strcat (filename, "/..");
338 /************************************************************************
342 ************************************************************************/
347 register char *source,
348 register char *target,
349 struct stat *sourceStatInfo,
350 void (*errorHandler)(),
354 static char *pname = "MoveDir";
357 char * targetDir; /* original target dir path */
361 struct stat s1; /* status of from file */
362 struct stat s2; /* status of to file */
366 static char buf [BUF_SIZE]; /* generic buffer */
367 char filename [MAX_PATH]; /* buffer to hold the full file name */
372 /* Copy target so we have it for an error dialog if we need it */
373 targetDir = XtNewString(target);
376 if ((val = stat (target, &s2)) < 0)
377 val = lstat(target, &s2);
379 /* Check if move to itself */
380 if( sourceStatInfo->st_dev == s2.st_dev)
382 if (Check (w, target, sourceStatInfo->st_ino, MOVE_FILE, NULL ))
386 if (val >= 0) /* target exists */
388 if ((s2.st_mode & S_IFMT) != S_IFDIR) /* target not directory */
393 tmpStr = GetSharedMessage(CANT_OVERWRITE_ERROR);
394 msg = XtNewString(tmpStr);
395 (*errorHandler) (w, msg, target);
402 (void) strcpy (buf, target);
406 DtLastChar(buf, &cptr, &len);
407 if ((len != 1) || (*cptr != '/'))
408 (void) strcat (buf, "/");
409 (void) strcat (buf, DName (source));
411 if (lstat (target, &s2) >= 0) /* new target exists */
417 tmpStr = GetSharedMessage(CANT_OVERWRITE_ERROR);
418 msg = XtNewString(tmpStr);
419 (*errorHandler) (w, msg, target);
430 /* don't rename these */
431 DtLastChar(p, &cptr, &len);
433 if (!strcmp (p, ".") || !strcmp (p, "..") ||
434 !strcmp (p, "") || ((len == 1) && (*cptr == '/')))
440 tmpStr = (GETMESSAGE(11,32, "Cannot rename %s"));
441 msg = XtNewString(tmpStr);
442 (*errorHandler) (w, msg, p);
450 /* parent doesn't exist */
451 if((val = stat (_DtPName (source), &s1)) < 0)
452 val = lstat (_DtPName (source), &s1);
454 if((val1 = stat (_DtPName (target), &s2)) < 0)
455 val1 = lstat (_DtPName (target), &s2);
457 if (val < 0 || val1 < 0)
461 tmpStr = GETMESSAGE(11, 14, "Cannot find the folders location.");
462 msg = XtNewString(tmpStr);
463 (*errorHandler) (w, msg, NULL);
471 /* check for target parent not writeable */
472 if (CheckAccess(_DtPName (target), W_OK) == -1)
478 tmpStr = GetSharedMessage(CANT_WRITE_ERROR);
479 msg = XtNewString(tmpStr);
480 (*errorHandler) (w, msg, targetDir);
488 /* check for source parent not writeable */
489 if (CheckAccess(_DtPName (source), W_OK) == -1)
495 tmpStr = GetSharedMessage(CANT_WRITE_ERROR);
496 msg = XtNewString(tmpStr);
497 (*errorHandler) (w, msg, source);
504 if (((sourceStatInfo->st_mode & S_IFMT) == S_IFDIR) &&
505 (CheckAccess(source, W_OK) != 0))
511 tmpStr=GETMESSAGE(11, 57,"You do not have permission to move the folder\n%s\nWrite permission is required.");
512 msg = XtMalloc(strlen(tmpStr) + strlen(source) + 2);
513 sprintf(msg, tmpStr, source);
514 (*errorHandler) (w, msg, source);
521 /* if parents are not on the same device, do a copy & delete */
522 if (s1.st_dev != s2.st_dev)
524 /* Determine correct Geometry Placement fo Move Dialog */
525 /* @@@ ... to be added */
532 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.");
533 msg = XtNewString(tmpStr);
534 (*errorHandler) (w, msg, NULL);
543 DBGFORK(("%s: child forked\n", pname));
545 /* pass in geometry, and other command lines params when available */
546 if(type == TRASH_DIRECTORY)
547 rc = execlp(DTCOPY, "dtfile_copy", "-move", "-confirmReplace",
548 "-confirmErrors", "-popDown","-checkPerms", source, target, 0);
550 rc = execlp(DTCOPY, "dtfile_copy", "-move", "-confirmReplace",
551 "-confirmErrors", "-popDown", source, target, 0);
553 /* call errorhandler */
554 perror ("Could not exec child process \"dtfile_copy\"");
556 DBGFORK(("%s: child exiting\n", pname));
561 DBGFORK(("%s: forked child<%d>\n", pname, child_pid));
568 link_path = _DtFollowLink(source);
571 if (s1.st_ino != s2.st_ino)
572 { /* different parent inodes */
573 (void) lstat (source, &s1); /* get source dir ino */
576 if (Check (w, _DtPName (target), s1.st_ino, MOVE_FILE, errorHandler))
577 { /* move into self */
583 /* This part of code was implemented with the idea that the links
584 to be treated differently. So, it has to be uncommented whenever
585 links are handled differently (i.e., moving a link shall move the
588 if(strcmp(link_path, source) != 0)
590 if (RunFileCommand (MOVE_CMD, link_path, target, NULL) == 0)
599 if (RunFileCommand (MOVE_CMD, source, target, NULL) == 0)
611 /************************************************************************
615 ************************************************************************/
624 void (*errorHandler)(),
625 Boolean checkForBusyDir,
628 static char *pname = "CopyDir";
631 char target [MAX_PATH]; /* buffer to hold the full file name */
632 char target_dir [MAX_PATH], target_file [MAX_PATH];
633 struct stat s2; /* status of to file */
634 int child_pid, rc, target_rc;
637 /* Check if source is readable */
638 if (CheckAccess(from, R_OK) == -1)
642 tmpStr = GetSharedMessage(CANT_READ_ERROR);
643 msg = XtNewString(tmpStr);
644 (*errorHandler) (w, msg, from);
650 /* generate target name */
651 /* "to" can be something to copy the source into (isContainer=TRUE) */
652 /* or it can be the full path of the destination (isContainer=FALSE) */
653 /* the former case is probably more common (e.g. a drag&drop copy) */
654 /* whereas the second case occurs when, for example, the menu is */
655 /* to copy directory /u/joe/a to /u/joe/b (not doable with d&d) */
656 (void) strcpy (target, to);
659 DtLastChar(to, &cptr, &len);
660 if ((len != 1) || (*cptr != '/'))
661 (void) strcat (target, "/");
662 (void) strcat (target, DName (from));
664 split_path(target, target_dir, target_file);
666 /* Check if target directory exists */
667 if ((target_rc = stat (target, &s2)) < 0)
668 target_rc = lstat(target, &s2);
673 * make sure it's a directory */
675 if ((s2.st_mode & S_IFMT) != S_IFDIR) /* target not directory */
679 tmpStr = GetSharedMessage(CANT_OVERWRITE_ERROR);
680 msg = XtNewString(tmpStr);
681 (*errorHandler) (w, msg, target);
689 /* target does not exist:
690 * make sure the "to" directory exists and is writable */
691 if ((rc = stat (target_dir, &s2)) < 0)
692 rc = lstat(target_dir, &s2);
694 if (rc < 0 || (s2.st_mode & S_IFMT) != S_IFDIR)
698 tmpStr = GETMESSAGE(11, 14, "Cannot find the folders location.");
699 msg = XtNewString(tmpStr);
700 (*errorHandler) (w, msg, NULL);
706 if (CheckAccess(target_dir, W_OK) == -1)
710 tmpStr = GetSharedMessage(CANT_WRITE_ERROR);
711 msg = XtNewString(tmpStr);
712 (*errorHandler) (w, msg, to);
719 /* Determine if we are attempting a copy into self */
720 if (s1->st_dev == s2.st_dev)
724 if (Check (w, to, s1->st_ino, COPY_FILE, errorHandler))
727 else /* destination dir does not exist, look at its proposed parent */
729 if (Check (w, target_dir, s1->st_ino, COPY_FILE, errorHandler))
734 /* Determine correct Geometry Placement fo Copy Dialog */
735 /* @@@ ... to be added */
737 /* If all the above checks have passed, then fork off the copy dialog */
744 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.");
745 msg = XtNewString(tmpStr);
746 (*errorHandler) (w, msg, NULL);
754 DBGFORK(("%s: child forked\n", pname));
756 /* pass in geometry, and other command lines params when available */
757 if (mode == MERGE_DIR)
758 /* merge source & target directories */
759 rc = execlp(DTCOPY, "dtfile_copy",
760 "-dontDelete", "-forceCopies", "-copyTop",
761 "-confirmReplace", "-confirmErrors", "-popDown",
764 /* replace target dir */
765 rc = execlp(DTCOPY, "dtfile_copy",
766 "-forceCopies", "-copyTop",
767 "-confirmErrors", "-popDown",
770 /* call errorhandler */
771 perror ("Could not exec child process \"dtfile_copy\"");
773 DBGFORK(("%s: child exiting\n", pname));
778 DBGFORK(("%s: forked child<%d>\n", pname, child_pid));
785 /************************************************************************
789 ************************************************************************/
796 Boolean isContainer, /* described in function CopyDir */
797 void (*errorHandler)(),
798 Boolean checkForBusyDir,
804 Boolean copy_dir_return;
805 Boolean move_dir_return;
812 Boolean restricted = False;
813 Boolean fileExists = False;
815 struct stat s1; /* status of from file e.g. lstat info */
816 struct stat s4; /* status of from file e.g. stat info */
817 struct stat s2; /* status of to file e.g. stat info */
818 struct stat s3; /* status of to file e.g. lstat info */
820 char buf [BLOCK_SIZE]; /* generic buffer */
821 char filename [MAX_PATH]; /* buffer to hold the full file name */
828 /* Check the <from> part of the command:
830 * Report error if <from> doesn't exist.
831 * Else error if <from> hasn't read access.
834 DPRINTF(("FileManip: mode %d type %d from \"%s\" to \"%s\"\n", mode, type, from, to));
835 if (stat (from, &s1) < 0)
837 if (lstat (from, &s1) < 0)
841 tmpStr = (GETMESSAGE(11,28, "%s cannot be found."));
842 msg = XtNewString(tmpStr);
843 (*errorHandler) (w, msg, from);
850 /* We will check if we need to initiate a copy of a directory */
851 if ((s1.st_mode & S_IFMT) == S_IFDIR) /* from is a directory */
853 if (mode == COPY_FILE || mode == MERGE_DIR)
855 oldInt = signal (SIGINT, SIG_IGN);
856 oldQuit = signal (SIGQUIT, SIG_IGN);
857 oldPipe = signal (SIGPIPE, SIG_IGN);
858 oldTerm = signal (SIGTERM, SIG_IGN);
860 copy_dir_return = CopyDir(w, mode, from, to, isContainer, &s1,
861 errorHandler, checkForBusyDir, type);
863 (void) signal (SIGINT, oldInt);
864 (void) signal (SIGQUIT, oldQuit);
865 (void) signal (SIGPIPE, oldPipe);
866 (void) signal (SIGTERM, oldTerm);
868 return (copy_dir_return);
872 /* If the directory has more than one open view or open views */
873 /* of sub directories. Then do not allow the move or rename. */
875 if (mode == MOVE_FILE)
877 if (checkForBusyDir && DirectoryBusy (from))
881 char message_buf[512];
884 message_buf[0] = '\0';
885 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."));
886 sprintf (message_buf, tmpStr, from);
887 (*errorHandler) (w, message_buf, NULL);
893 oldInt = signal (SIGINT, SIG_IGN);
894 oldQuit = signal (SIGQUIT, SIG_IGN);
895 oldPipe = signal (SIGPIPE, SIG_IGN);
896 oldTerm = signal (SIGTERM, SIG_IGN);
898 move_dir_return = MoveDir (w, from, to, &s1, errorHandler, &realTarget,type);
900 (void) signal (SIGINT, oldInt);
901 (void) signal (SIGQUIT, oldQuit);
902 (void) signal (SIGPIPE, oldPipe);
903 (void) signal (SIGTERM, oldTerm);
905 return (move_dir_return);
908 if (mode == LINK_FILE)
910 /* Need to append the directory name on */
911 (void) strcpy(filename, to);
916 tmp = (char *)XtMalloc(strlen(filename) + 1);
917 strcpy(tmp, filename);
918 /* get the workspace number first */
919 ptr = strrchr(tmp, '/');
921 /* now get the Desktop */
922 ptr = strrchr(tmp, '/');
924 /* if we don't get "/Desktop" then there is another filename
925 attached to the end of the to name passed in */
926 if(strcmp(ptr, "/Desktop") != 0)
931 if( (!restricted && type != TRASH_DIRECTORY) && isContainer)
933 DtLastChar(to, &cptr, &len);
934 if ((len != 1) || (*cptr != '/'))
935 (void) strcat(filename, "/");
938 if(strcmp(from, "/.") == 0 || strcmp(from, "/") == 0)
940 (void) strcat(filename, home_host_name);
941 (void) strcat(filename, ":");
942 (void) strcat(filename, root_title);
944 else if ( (!restricted && type != TRASH_DIRECTORY) && isContainer)
945 (void) strcat(filename, DName(from));
949 if (((link_result = symlink(from, to)) != 0) && errorHandler)
951 if(type == NOT_DESKTOP || errno != EEXIST )
955 tmpStr = GetSharedMessage(CANT_CREATE_ERROR);
956 msg = XtNewString(tmpStr);
957 (*errorHandler) (w, msg, to);
962 return(link_result == 0 ? True : False);
966 if (CheckAccess(from, R_OK) == -1)
969 * A move operation does not require read permission, but a copy does.
971 if (mode == COPY_FILE)
977 tmpStr = GetSharedMessage(CANT_READ_ERROR);
978 msg = XtNewString(tmpStr);
979 (*errorHandler) (w, msg, from);
987 /* Here <from> is a file (not a directory).
988 * Check the <to> part of the command:
990 * <To> can either be an existing file,
991 * an existing directory,
992 * or a new file in an existing directory.
995 if (lstat (to, &s2) >= 0) /* <to> exists */
997 if ((stat (to, &s3) >= 0) &&
998 #if defined(__hp_osf) || (__ultrix) || defined(__osf__) || defined(linux) || \
1000 (((s3.st_mode & S_IFMT) == S_IFDIR) /* if is a directory */
1001 || ((s3.st_mode & S_IFMT) == S_IFSOCK)) ) /* or a net special */
1003 #if defined(SVR4) || defined(_AIX) || defined(sco)
1004 ((s3.st_mode & S_IFMT) == S_IFDIR) ) /* if is a directory */
1005 #else /* (__hpux) */
1006 (((s3.st_mode & S_IFMT) == S_IFDIR) /* if is a directory */
1007 || ((s3.st_mode & S_IFMT) == S_IFNWK)) ) /* or a net special */
1010 { /* then get file name */
1011 (void) strcpy (filename, to);
1013 DtLastChar(to, &cptr, &len);
1014 if ((len != 1) || (*cptr != '/'))
1015 (void) strcat (filename, "/");
1017 (void) strcat (filename, DName (from));
1022 if (lstat (to, &s2) >= 0) /* reverify <to> exists */
1024 if ((stat (to, &s3) >= 0) &&
1025 ((s3.st_mode & S_IFMT) == S_IFDIR)) /* if is a directory */
1031 tmpStr = GetSharedMessage(CANT_OVERWRITE_ERROR);
1032 msg = XtNewString(tmpStr);
1033 (*errorHandler) (w, msg, to);
1040 /* <from> = <to> NOOP. */
1042 if (s1.st_dev == s2.st_dev && s1.st_ino == s2.st_ino)
1046 /* no write permission */
1047 if (CheckAccess(to, W_OK) == -1)
1051 link_path = _DtFollowLink(to);
1052 if(strcmp(to,link_path) == 0)
1058 tmpStr = GetSharedMessage(CANT_OVERWRITE_ERROR);
1059 msg = XtNewString(tmpStr);
1060 (*errorHandler) (w, msg, to);
1070 if (unlink (to) < 0)
1076 tmpStr = GetSharedMessage(CANT_OVERWRITE_ERROR);
1077 msg = XtNewString(tmpStr);
1078 (*errorHandler) (w, msg, to);
1088 /* Here <from> is a file and <to> doesn't exist.
1090 * If not a copy, link the files. If the link succeeds, unlink
1091 * <from> and return.
1092 * Copy <from> to <to>.
1093 * If the copy cmd is not specified, unlink <from>.
1096 if (mode != COPY_FILE)
1098 /* Try to maintain symbolic links, except when we're doing a link! */
1099 if (((s1.st_mode & S_IFMT) == S_IFLNK) && (mode != LINK_FILE))
1101 char link_path[MAX_PATH + 1];
1104 if ((link_len = readlink(from, link_path, MAX_PATH)) > 0)
1106 link_path[link_len] = '\0';
1107 link_result = symlink(link_path, to);
1111 /* Fail-safe; do it the hard way */
1112 if (mode == MOVE_FILE)
1113 if (RunFileCommand(MOVE_CMD, from, to, NULL) == 0)
1116 if (RunFileCommand(LINK_CMD, "-s", from, to) == 0)
1124 if (mode == LINK_FILE)
1125 link_result = symlink(from, to);
1130 link_path = _DtFollowLink(from);
1132 if(strcmp(link_path, from) != 0)
1133 link_result = symlink(link_path, to);
1135 link_result = link (from, to);
1139 /* If this was a link, then time to bail out */
1140 if (mode == LINK_FILE)
1142 if ((link_result != 0) && errorHandler)
1146 tmpStr = GetSharedMessage(CANT_CREATE_ERROR);
1147 msg = XtNewString(tmpStr);
1148 (*errorHandler) (w, msg, to);
1152 return(link_result == 0 ? True : False);
1155 /* Unlink source only if this was a move request */
1156 if ((mode == MOVE_FILE) && (link_result >= 0))
1158 if (unlink (from) < 0)
1164 tmpStr = GetSharedMessage(CANT_DELETE_ERROR);
1165 msg = XtNewString(tmpStr);
1166 (*errorHandler) (w, msg, from);
1177 /* unable to read <from> */
1179 if ((fold = open (from, O_RDONLY)) < 0)
1185 tmpStr = GetSharedMessage(CANT_READ_ERROR);
1186 msg = XtNewString(tmpStr);
1187 (*errorHandler) (w, msg, from);
1194 /* unable create <to> */
1197 /* We use the stat buffer info not lstat info */
1198 (void) stat (from, &s4);
1200 if ((fnew = creat (to, (int) s4.st_mode)) < 0)
1206 tmpStr = GetSharedMessage(CANT_CREATE_ERROR);
1207 msg = XtNewString(tmpStr);
1208 (*errorHandler) (w, msg, to);
1211 (void) close (fold);
1218 while (n = read (fold, buf, BLOCK_SIZE))
1226 tmpStr = (GETMESSAGE(11,31, "Error while reading %s"));
1227 msg = XtNewString(tmpStr);
1228 (*errorHandler) (w, msg, to);
1231 (void) close (fold);
1232 (void) close (fnew);
1237 result = write(fnew, buf, n);
1240 (void) close (fold);
1241 (void) close (fnew);
1244 char * strerrormsg = NULL;
1245 char * catmsg = NULL;
1246 char * samsg = NULL;
1248 Boolean unknown = False;
1256 if(mode == COPY_FILE)
1257 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."));
1259 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."));
1260 catmsg = XtNewString(tmpStr);
1266 if(mode == COPY_FILE)
1267 tmpStr = (GETMESSAGE(11,42, "No space available on the\ndevice you are copying to.\n\n"));
1269 tmpStr = (GETMESSAGE(11,43, "No space available on the\ndevice you are moving to.\n"));
1270 catmsg = XtNewString(tmpStr);
1274 sprintf(errnoMsg, "EAGAIN: ");
1275 strerrormsg = strerror(errno);
1278 sprintf(errnoMsg, "EBADF: ");
1279 strerrormsg = strerror(errno);
1282 sprintf(errnoMsg, "EDEADLK: ");
1283 strerrormsg = strerror(errno);
1286 sprintf(errnoMsg, "EINTR: ");
1287 strerrormsg = strerror(errno);
1290 sprintf(errnoMsg, "EIO: ");
1291 strerrormsg = strerror(errno);
1294 sprintf(errnoMsg, "ENOLCK: ");
1295 strerrormsg = strerror(errno);
1298 sprintf(errnoMsg, "EPIPE: ");
1299 strerrormsg = strerror(errno);
1303 sprintf(errnoMsg, "%s", GETMESSAGE(11,56, "(Unknown):"));
1304 strerrormsg = strerror(errno);
1308 /* If catmsg is NULL then one of the miscellanous error's occured.
1309 * Set up a generic error message which will output the internal
1314 if(mode == COPY_FILE)
1315 tmpStr = (GETMESSAGE(11,53, "The copy of the file/folder failed\ndue to some internal error. The internal\nerror given is:"));
1317 tmpStr = (GETMESSAGE(11,54, "The move of the file/folder failed\ndue to some internal error. The internal\nerror given is:"));
1318 catmsg = XtNewString(tmpStr);
1319 tmpStr = (GETMESSAGE(11,55, "Please see your System Adminstrator"));
1320 samsg = XtNewString(tmpStr);
1323 /* Build a concatination of the possible message parts */
1324 bufLen = (strerrormsg ? strlen(strerrormsg) +
1325 strlen(errnoMsg) + strlen(samsg) : 0) +
1326 strlen(catmsg) + 10;
1327 msg = XtMalloc(bufLen);
1328 strcpy (msg, catmsg);
1331 strcat (msg, "\n\n");
1332 strcat (msg, errnoMsg);
1335 strcat (msg, strerrormsg);
1336 strcat (msg, "\n\n");
1337 strcat (msg, samsg);
1340 (*errorHandler) (w, msg, to);
1349 (void) close (fold);
1350 (void) close (fnew);
1353 /* unlink <from> if not copy */
1355 if (mode == MOVE_FILE)
1357 if (unlink (from) < 0)
1364 ptr = strrchr(from, '/') + 1;
1365 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."));
1366 msg = XtNewString(tmpStr);
1367 (*errorHandler) (w, msg, ptr);
1377 * WARNING: this is different from how the shell behaves. If you use
1378 * a shell to copy over an existing file, the file keeps its
1379 * original owner and group; for some historical reason,
1380 * dtfile does it differently.
1381 * UPDATE: This is no longer the case as of 10/31/94, we change the
1382 * file to the original owner and group now. This is to fix
1384 * Also, this call originally occurred after we opened/created
1385 * the file, but before we closed it. This caused problems
1386 * if the user was running as root, and was copying across
1387 * an nfs link, since root access is not typically carried
1388 * across an nfs mount. The result was that we were able to
1389 * create the file, copy to it, but when we tried to close it,
1390 * because the file was now owned by root on the other system,
1391 * we could not close the file; thus, the file ended up empty!
1394 if (mode == COPY_FILE && fileExists)
1397 (void) chmod (to, s3.st_mode);
1398 (void) chown (to, s3.st_uid, s3.st_gid);
1403 (void) chown (to, getuid(), getgid());