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
86 #include <sys/access.h>
108 #include <Xm/MwmUtil.h>
110 #include <Dt/DtP.h> /* required for DtDirPaths type */
111 #include <Dt/Connect.h>
112 #include <Dt/DtNlUtils.h>
113 #include <Dt/SharedProcs.h>
116 #include "SharedProcs.h"
121 #include "SharedMsgs.h"
123 #ifndef CDE_INSTALLATION_TOP
124 #define CDE_INSTALLATION_TOP "/usr/dt"
127 /* Local Function Definitions */
128 static char * MOVE_CMD = "/bin/mv";
129 static char * LINK_CMD = "/bin/ln";
130 static char * REMOVE_CMD = "/bin/rm";
131 static char * DTCOPY = CDE_INSTALLATION_TOP "/bin/dtfile_copy";
134 /************************************************************************
138 ************************************************************************/
148 #if defined(__hp_osf) || defined(__ultrix)
149 /*--------------------------------------------------------------------
150 * access code for __hp_osf, __ultrix
151 *------------------------------------------------------------------*/
153 setreuid(geteuid(),-1);
154 return access (fname, what);
158 /*--------------------------------------------------------------------
159 * access code for BLS
160 *------------------------------------------------------------------*/
162 setresuid(geteuid(),-1,-1);
163 return access (fname, what);
165 #else /* the rest of the OS's */
167 save_ruid = getuid();
170 setreuid(geteuid(),-1);
175 save_rgid = getgid();
178 setregid(getegid(),-1);
183 access_priv = access (fname, what);
186 setreuid(save_ruid,-1);
187 setregid(save_rgid,-1);
195 #endif /* Apollo & OSF */
199 /************************************************************************
202 * Display an error message.
204 ************************************************************************/
215 if (message2 != NULL)
217 message_buf = XtMalloc(strlen(message1) + strlen(message2) + 1);
218 (void) sprintf(message_buf,message1, message2);
222 message_buf = XtMalloc(strlen(message1) + 1);
223 (void) sprintf(message_buf, "%s", message1);
226 /* Display an error dialog */
227 tmpStr = GetSharedMessage(FILE_MANIPULATION_ERROR_TITLE);
228 title = XtNewString(tmpStr);
229 _DtMessage (w, title, message_buf, NULL, HelpRequestCB);
235 /************************************************************************
238 * Returns the file name of its argument.
239 * Keep looking thru the string until a "/" is found which still
240 * has some characters after it.
242 ************************************************************************/
245 register char *name )
254 q = DtStrchr(q, '/');
268 /************************************************************************
272 ************************************************************************/
277 register ino_t dinode,
279 void (*errorHandler)() )
282 char filename [MAX_PATH];
288 (void) strcpy (filename, spth);
290 while (sbuf.st_ino != ROOTINO)
292 if (lstat (filename, &sbuf) < 0)
296 tmpStr = (GETMESSAGE(11,33, "Cannot open %s"));
297 msg = XtNewString(tmpStr);
298 (*errorHandler) (w, msg, filename);
304 if (sbuf.st_ino == dinode)
308 if (mode == COPY_FILE)
309 tmpStr = GETMESSAGE(11,35, "Cannot copy a folder into itself.");
311 tmpStr = GETMESSAGE(11,16, "A folder cannot be moved into itself.\n%s");
312 msg = XtNewString(tmpStr);
313 if (mode == COPY_FILE)
314 (*errorHandler) (w, msg, NULL);
316 (*errorHandler) (w, msg, filename);
322 (void) strcat (filename, "/..");
329 /************************************************************************
333 ************************************************************************/
338 register char *source,
339 register char *target,
340 struct stat *sourceStatInfo,
341 void (*errorHandler)(),
345 static char *pname = "MoveDir";
348 char * targetDir; /* original target dir path */
352 struct stat s1; /* status of from file */
353 struct stat s2; /* status of to file */
357 static char buf [BUF_SIZE]; /* generic buffer */
358 char filename [MAX_PATH]; /* buffer to hold the full file name */
363 /* Copy target so we have it for an error dialog if we need it */
364 targetDir = XtNewString(target);
367 if ((val = stat (target, &s2)) < 0)
368 val = lstat(target, &s2);
370 /* Check if move to itself */
371 if( sourceStatInfo->st_dev == s2.st_dev)
373 if (Check (w, target, sourceStatInfo->st_ino, MOVE_FILE, NULL ))
377 if (val >= 0) /* target exists */
379 if ((s2.st_mode & S_IFMT) != S_IFDIR) /* target not directory */
384 tmpStr = GetSharedMessage(CANT_OVERWRITE_ERROR);
385 msg = XtNewString(tmpStr);
386 (*errorHandler) (w, msg, target);
393 (void) strcpy (buf, target);
397 DtLastChar(buf, &cptr, &len);
398 if ((len != 1) || (*cptr != '/'))
399 (void) strcat (buf, "/");
400 (void) strcat (buf, DName (source));
402 if (lstat (target, &s2) >= 0) /* new target exists */
408 tmpStr = GetSharedMessage(CANT_OVERWRITE_ERROR);
409 msg = XtNewString(tmpStr);
410 (*errorHandler) (w, msg, target);
421 /* don't rename these */
422 DtLastChar(p, &cptr, &len);
424 if (!strcmp (p, ".") || !strcmp (p, "..") ||
425 !strcmp (p, "") || ((len == 1) && (*cptr == '/')))
431 tmpStr = (GETMESSAGE(11,32, "Cannot rename %s"));
432 msg = XtNewString(tmpStr);
433 (*errorHandler) (w, msg, p);
441 /* parent doesn't exist */
442 if((val = stat (_DtPName (source), &s1)) < 0)
443 val = lstat (_DtPName (source), &s1);
445 if((val1 = stat (_DtPName (target), &s2)) < 0)
446 val1 = lstat (_DtPName (target), &s2);
448 if (val < 0 || val1 < 0)
452 tmpStr = GETMESSAGE(11, 14, "Cannot find the folders location.");
453 msg = XtNewString(tmpStr);
454 (*errorHandler) (w, msg, NULL);
462 /* check for target parent not writeable */
463 if (CheckAccess(_DtPName (target), W_OK) == -1)
469 tmpStr = GetSharedMessage(CANT_WRITE_ERROR);
470 msg = XtNewString(tmpStr);
471 (*errorHandler) (w, msg, targetDir);
479 /* check for source parent not writeable */
480 if (CheckAccess(_DtPName (source), W_OK) == -1)
486 tmpStr = GetSharedMessage(CANT_WRITE_ERROR);
487 msg = XtNewString(tmpStr);
488 (*errorHandler) (w, msg, source);
495 if (((sourceStatInfo->st_mode & S_IFMT) == S_IFDIR) &&
496 (CheckAccess(source, W_OK) != 0))
502 tmpStr=GETMESSAGE(11, 57,"You do not have permission to move the folder\n%s\nWrite permission is required.");
503 msg = XtMalloc(strlen(tmpStr) + strlen(source) + 2);
504 sprintf(msg, tmpStr, source);
505 (*errorHandler) (w, msg, source);
512 /* if parents are not on the same device, do a copy & delete */
513 if (s1.st_dev != s2.st_dev)
515 /* Determine correct Geometry Placement fo Move Dialog */
516 /* @@@ ... to be added */
523 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.");
524 msg = XtNewString(tmpStr);
525 (*errorHandler) (w, msg, NULL);
534 DBGFORK(("%s: child forked\n", pname));
536 /* pass in geometry, and other command lines params when available */
537 if(type == TRASH_DIRECTORY)
538 rc = execlp(DTCOPY, "dtfile_copy", "-move", "-confirmReplace",
539 "-confirmErrors", "-popDown","-checkPerms", source, target, NULL);
541 rc = execlp(DTCOPY, "dtfile_copy", "-move", "-confirmReplace",
542 "-confirmErrors", "-popDown", source, target, NULL);
544 /* call errorhandler */
545 perror ("Could not exec child process \"dtfile_copy\"");
547 DBGFORK(("%s: child exiting\n", pname));
552 DBGFORK(("%s: forked child<%d>\n", pname, child_pid));
559 link_path = _DtFollowLink(source);
562 if (s1.st_ino != s2.st_ino)
563 { /* different parent inodes */
564 (void) lstat (source, &s1); /* get source dir ino */
567 if (Check (w, _DtPName (target), s1.st_ino, MOVE_FILE, errorHandler))
568 { /* move into self */
574 /* This part of code was implemented with the idea that the links
575 to be treated differently. So, it has to be uncommented whenever
576 links are handled differently (i.e., moving a link shall move the
579 if(strcmp(link_path, source) != 0)
581 if (RunFileCommand (MOVE_CMD, link_path, target, NULL) == 0)
590 if (RunFileCommand (MOVE_CMD, source, target, NULL) == 0)
602 /************************************************************************
606 ************************************************************************/
615 void (*errorHandler)(),
616 Boolean checkForBusyDir,
619 static char *pname = "CopyDir";
622 char target [MAX_PATH]; /* buffer to hold the full file name */
623 char target_dir [MAX_PATH], target_file [MAX_PATH];
624 struct stat s2; /* status of to file */
625 int child_pid, rc, target_rc;
628 /* Check if source is readable */
629 if (CheckAccess(from, R_OK) == -1)
633 tmpStr = GetSharedMessage(CANT_READ_ERROR);
634 msg = XtNewString(tmpStr);
635 (*errorHandler) (w, msg, from);
641 /* generate target name */
642 /* "to" can be something to copy the source into (isContainer=TRUE) */
643 /* or it can be the full path of the destination (isContainer=FALSE) */
644 /* the former case is probably more common (e.g. a drag&drop copy) */
645 /* whereas the second case occurs when, for example, the menu is */
646 /* to copy directory /u/joe/a to /u/joe/b (not doable with d&d) */
647 (void) strcpy (target, to);
650 DtLastChar(to, &cptr, &len);
651 if ((len != 1) || (*cptr != '/'))
652 (void) strcat (target, "/");
653 (void) strcat (target, DName (from));
655 split_path(target, target_dir, target_file);
657 /* Check if target directory exists */
658 if ((target_rc = stat (target, &s2)) < 0)
659 target_rc = lstat(target, &s2);
664 * make sure it's a directory */
666 if ((s2.st_mode & S_IFMT) != S_IFDIR) /* target not directory */
670 tmpStr = GetSharedMessage(CANT_OVERWRITE_ERROR);
671 msg = XtNewString(tmpStr);
672 (*errorHandler) (w, msg, target);
680 /* target does not exist:
681 * make sure the "to" directory exists and is writable */
682 if ((rc = stat (target_dir, &s2)) < 0)
683 rc = lstat(target_dir, &s2);
685 if (rc < 0 || (s2.st_mode & S_IFMT) != S_IFDIR)
689 tmpStr = GETMESSAGE(11, 14, "Cannot find the folders location.");
690 msg = XtNewString(tmpStr);
691 (*errorHandler) (w, msg, NULL);
697 if (CheckAccess(target_dir, W_OK) == -1)
701 tmpStr = GetSharedMessage(CANT_WRITE_ERROR);
702 msg = XtNewString(tmpStr);
703 (*errorHandler) (w, msg, to);
710 /* Determine if we are attempting a copy into self */
711 if (s1->st_dev == s2.st_dev)
715 if (Check (w, to, s1->st_ino, COPY_FILE, errorHandler))
718 else /* destination dir does not exist, look at its proposed parent */
720 if (Check (w, target_dir, s1->st_ino, COPY_FILE, errorHandler))
725 /* Determine correct Geometry Placement fo Copy Dialog */
726 /* @@@ ... to be added */
728 /* If all the above checks have passed, then fork off the copy dialog */
735 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.");
736 msg = XtNewString(tmpStr);
737 (*errorHandler) (w, msg, NULL);
745 DBGFORK(("%s: child forked\n", pname));
747 /* pass in geometry, and other command lines params when available */
748 if (mode == MERGE_DIR)
749 /* merge source & target directories */
750 rc = execlp(DTCOPY, "dtfile_copy",
751 "-dontDelete", "-forceCopies", "-copyTop",
752 "-confirmReplace", "-confirmErrors", "-popDown",
755 /* replace target dir */
756 rc = execlp(DTCOPY, "dtfile_copy",
757 "-forceCopies", "-copyTop",
758 "-confirmErrors", "-popDown",
761 /* call errorhandler */
762 perror ("Could not exec child process \"dtfile_copy\"");
764 DBGFORK(("%s: child exiting\n", pname));
769 DBGFORK(("%s: forked child<%d>\n", pname, child_pid));
776 /************************************************************************
780 ************************************************************************/
787 Boolean isContainer, /* described in function CopyDir */
788 void (*errorHandler)(),
789 Boolean checkForBusyDir,
795 Boolean copy_dir_return;
796 Boolean move_dir_return;
803 Boolean restricted = False;
804 Boolean fileExists = False;
806 struct stat s1; /* status of from file e.g. lstat info */
807 struct stat s4; /* status of from file e.g. stat info */
808 struct stat s2; /* status of to file e.g. stat info */
809 struct stat s3; /* status of to file e.g. lstat info */
811 char buf [BLOCK_SIZE]; /* generic buffer */
812 char filename [MAX_PATH]; /* buffer to hold the full file name */
819 /* Check the <from> part of the command:
821 * Report error if <from> doesn't exist.
822 * Else error if <from> hasn't read access.
825 DPRINTF(("FileManip: mode %d type %d from \"%s\" to \"%s\"\n", mode, type, from, to));
826 if (stat (from, &s1) < 0)
828 if (lstat (from, &s1) < 0)
832 tmpStr = (GETMESSAGE(11,28, "%s cannot be found."));
833 msg = XtNewString(tmpStr);
834 (*errorHandler) (w, msg, from);
841 /* We will check if we need to initiate a copy of a directory */
842 if ((s1.st_mode & S_IFMT) == S_IFDIR) /* from is a directory */
844 if (mode == COPY_FILE || mode == MERGE_DIR)
846 oldInt = signal (SIGINT, SIG_IGN);
847 oldQuit = signal (SIGQUIT, SIG_IGN);
848 oldPipe = signal (SIGPIPE, SIG_IGN);
849 oldTerm = signal (SIGTERM, SIG_IGN);
851 copy_dir_return = CopyDir(w, mode, from, to, isContainer, &s1,
852 errorHandler, checkForBusyDir, type);
854 (void) signal (SIGINT, oldInt);
855 (void) signal (SIGQUIT, oldQuit);
856 (void) signal (SIGPIPE, oldPipe);
857 (void) signal (SIGTERM, oldTerm);
859 return (copy_dir_return);
863 /* If the directory has more than one open view or open views */
864 /* of sub directories. Then do not allow the move or rename. */
866 if (mode == MOVE_FILE)
868 if (checkForBusyDir && DirectoryBusy (from))
872 char message_buf[512];
875 message_buf[0] = '\0';
876 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."));
877 sprintf (message_buf, tmpStr, from);
878 (*errorHandler) (w, message_buf, NULL);
884 oldInt = signal (SIGINT, SIG_IGN);
885 oldQuit = signal (SIGQUIT, SIG_IGN);
886 oldPipe = signal (SIGPIPE, SIG_IGN);
887 oldTerm = signal (SIGTERM, SIG_IGN);
889 move_dir_return = MoveDir (w, from, to, &s1, errorHandler, &realTarget,type);
891 (void) signal (SIGINT, oldInt);
892 (void) signal (SIGQUIT, oldQuit);
893 (void) signal (SIGPIPE, oldPipe);
894 (void) signal (SIGTERM, oldTerm);
896 return (move_dir_return);
899 if (mode == LINK_FILE)
901 /* Need to append the directory name on */
902 (void) strcpy(filename, to);
907 tmp = (char *)XtMalloc(strlen(filename) + 1);
908 strcpy(tmp, filename);
909 /* get the workspace number first */
910 ptr = strrchr(tmp, '/');
912 /* now get the Desktop */
913 ptr = strrchr(tmp, '/');
915 /* if we don't get "/Desktop" then there is another filename
916 attached to the end of the to name passed in */
917 if(strcmp(ptr, "/Desktop") != 0)
922 if( (!restricted && type != TRASH_DIRECTORY) && isContainer)
924 DtLastChar(to, &cptr, &len);
925 if ((len != 1) || (*cptr != '/'))
926 (void) strcat(filename, "/");
929 if(strcmp(from, "/.") == 0 || strcmp(from, "/") == 0)
931 (void) strcat(filename, home_host_name);
932 (void) strcat(filename, ":");
933 (void) strcat(filename, root_title);
935 else if ( (!restricted && type != TRASH_DIRECTORY) && isContainer)
936 (void) strcat(filename, DName(from));
940 if (((link_result = symlink(from, to)) != 0) && errorHandler)
942 if(type == NOT_DESKTOP || errno != EEXIST )
946 tmpStr = GetSharedMessage(CANT_CREATE_ERROR);
947 msg = XtNewString(tmpStr);
948 (*errorHandler) (w, msg, to);
953 return(link_result == 0 ? True : False);
957 if (CheckAccess(from, R_OK) == -1)
960 * A move operation does not require read permission, but a copy does.
962 if (mode == COPY_FILE)
968 tmpStr = GetSharedMessage(CANT_READ_ERROR);
969 msg = XtNewString(tmpStr);
970 (*errorHandler) (w, msg, from);
978 /* Here <from> is a file (not a directory).
979 * Check the <to> part of the command:
981 * <To> can either be an existing file,
982 * an existing directory,
983 * or a new file in an existing directory.
986 if (lstat (to, &s2) >= 0) /* <to> exists */
988 if ((stat (to, &s3) >= 0) &&
989 #if defined(__hp_osf) || (__ultrix) || defined(__osf__) || defined(linux) || \
991 (((s3.st_mode & S_IFMT) == S_IFDIR) /* if is a directory */
992 || ((s3.st_mode & S_IFMT) == S_IFSOCK)) ) /* or a net special */
994 #if defined(SVR4) || defined(_AIX)
995 ((s3.st_mode & S_IFMT) == S_IFDIR) ) /* if is a directory */
997 (((s3.st_mode & S_IFMT) == S_IFDIR) /* if is a directory */
998 || ((s3.st_mode & S_IFMT) == S_IFNWK)) ) /* or a net special */
1001 { /* then get file name */
1002 (void) strcpy (filename, to);
1004 DtLastChar(to, &cptr, &len);
1005 if ((len != 1) || (*cptr != '/'))
1006 (void) strcat (filename, "/");
1008 (void) strcat (filename, DName (from));
1013 if (lstat (to, &s2) >= 0) /* reverify <to> exists */
1015 if ((stat (to, &s3) >= 0) &&
1016 ((s3.st_mode & S_IFMT) == S_IFDIR)) /* if is a directory */
1022 tmpStr = GetSharedMessage(CANT_OVERWRITE_ERROR);
1023 msg = XtNewString(tmpStr);
1024 (*errorHandler) (w, msg, to);
1031 /* <from> = <to> NOOP. */
1033 if (s1.st_dev == s2.st_dev && s1.st_ino == s2.st_ino)
1037 /* no write permission */
1038 if (CheckAccess(to, W_OK) == -1)
1042 link_path = _DtFollowLink(to);
1043 if(strcmp(to,link_path) == 0)
1049 tmpStr = GetSharedMessage(CANT_OVERWRITE_ERROR);
1050 msg = XtNewString(tmpStr);
1051 (*errorHandler) (w, msg, to);
1061 if (unlink (to) < 0)
1067 tmpStr = GetSharedMessage(CANT_OVERWRITE_ERROR);
1068 msg = XtNewString(tmpStr);
1069 (*errorHandler) (w, msg, to);
1079 /* Here <from> is a file and <to> doesn't exist.
1081 * If not a copy, link the files. If the link succeeds, unlink
1082 * <from> and return.
1083 * Copy <from> to <to>.
1084 * If the copy cmd is not specified, unlink <from>.
1087 if (mode != COPY_FILE)
1089 /* Try to maintain symbolic links, except when we're doing a link! */
1090 if (((s1.st_mode & S_IFMT) == S_IFLNK) && (mode != LINK_FILE))
1092 char link_path[MAX_PATH + 1];
1095 if ((link_len = readlink(from, link_path, MAX_PATH)) > 0)
1097 link_path[link_len] = '\0';
1098 link_result = symlink(link_path, to);
1102 /* Fail-safe; do it the hard way */
1103 if (mode == MOVE_FILE)
1104 if (RunFileCommand(MOVE_CMD, from, to, NULL) == 0)
1107 if (RunFileCommand(LINK_CMD, "-s", from, to) == 0)
1115 if (mode == LINK_FILE)
1116 link_result = symlink(from, to);
1121 link_path = _DtFollowLink(from);
1123 if(strcmp(link_path, from) != 0)
1124 link_result = symlink(link_path, to);
1126 link_result = link (from, to);
1130 /* If this was a link, then time to bail out */
1131 if (mode == LINK_FILE)
1133 if ((link_result != 0) && errorHandler)
1137 tmpStr = GetSharedMessage(CANT_CREATE_ERROR);
1138 msg = XtNewString(tmpStr);
1139 (*errorHandler) (w, msg, to);
1143 return(link_result == 0 ? True : False);
1146 /* Unlink source only if this was a move request */
1147 if ((mode == MOVE_FILE) && (link_result >= 0))
1149 if (unlink (from) < 0)
1155 tmpStr = GetSharedMessage(CANT_DELETE_ERROR);
1156 msg = XtNewString(tmpStr);
1157 (*errorHandler) (w, msg, from);
1168 /* unable to read <from> */
1170 if ((fold = open (from, O_RDONLY)) < 0)
1176 tmpStr = GetSharedMessage(CANT_READ_ERROR);
1177 msg = XtNewString(tmpStr);
1178 (*errorHandler) (w, msg, from);
1185 /* unable create <to> */
1188 /* We use the stat buffer info not lstat info */
1189 (void) stat (from, &s4);
1191 if ((fnew = creat (to, (int) s4.st_mode)) < 0)
1197 tmpStr = GetSharedMessage(CANT_CREATE_ERROR);
1198 msg = XtNewString(tmpStr);
1199 (*errorHandler) (w, msg, to);
1202 (void) close (fold);
1209 while (n = read (fold, buf, BLOCK_SIZE))
1217 tmpStr = (GETMESSAGE(11,31, "Error while reading %s"));
1218 msg = XtNewString(tmpStr);
1219 (*errorHandler) (w, msg, to);
1222 (void) close (fold);
1223 (void) close (fnew);
1228 result = write(fnew, buf, n);
1231 (void) close (fold);
1232 (void) close (fnew);
1235 char * strerrormsg = NULL;
1236 char * catmsg = NULL;
1237 char * samsg = NULL;
1239 Boolean unknown = False;
1247 if(mode == COPY_FILE)
1248 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."));
1250 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."));
1251 catmsg = XtNewString(tmpStr);
1257 if(mode == COPY_FILE)
1258 tmpStr = (GETMESSAGE(11,42, "No space available on the\ndevice you are copying to.\n\n"));
1260 tmpStr = (GETMESSAGE(11,43, "No space available on the\ndevice you are moving to.\n"));
1261 catmsg = XtNewString(tmpStr);
1265 sprintf(errnoMsg, "EAGAIN: ");
1266 strerrormsg = strerror(errno);
1269 sprintf(errnoMsg, "EBADF: ");
1270 strerrormsg = strerror(errno);
1273 sprintf(errnoMsg, "EDEADLK: ");
1274 strerrormsg = strerror(errno);
1277 sprintf(errnoMsg, "EINTR: ");
1278 strerrormsg = strerror(errno);
1281 sprintf(errnoMsg, "EIO: ");
1282 strerrormsg = strerror(errno);
1285 sprintf(errnoMsg, "ENOLCK: ");
1286 strerrormsg = strerror(errno);
1289 sprintf(errnoMsg, "EPIPE: ");
1290 strerrormsg = strerror(errno);
1294 sprintf(errnoMsg, "%s", GETMESSAGE(11,56, "(Unknown):"));
1295 strerrormsg = strerror(errno);
1299 /* If catmsg is NULL then one of the miscellanous error's occurred.
1300 * Set up a generic error message which will output the internal
1305 if(mode == COPY_FILE)
1306 tmpStr = (GETMESSAGE(11,53, "The copy of the file/folder failed\ndue to some internal error. The internal\nerror given is:"));
1308 tmpStr = (GETMESSAGE(11,54, "The move of the file/folder failed\ndue to some internal error. The internal\nerror given is:"));
1309 catmsg = XtNewString(tmpStr);
1310 tmpStr = (GETMESSAGE(11,55, "Please see your System Adminstrator"));
1311 samsg = XtNewString(tmpStr);
1314 /* Build a concatination of the possible message parts */
1315 bufLen = (strerrormsg ? strlen(strerrormsg) +
1316 strlen(errnoMsg) + strlen(samsg) : 0) +
1317 strlen(catmsg) + 10;
1318 msg = XtMalloc(bufLen);
1319 strcpy (msg, catmsg);
1322 strcat (msg, "\n\n");
1323 strcat (msg, errnoMsg);
1326 strcat (msg, strerrormsg);
1327 strcat (msg, "\n\n");
1328 strcat (msg, samsg);
1331 (*errorHandler) (w, msg, to);
1340 (void) close (fold);
1341 (void) close (fnew);
1344 /* unlink <from> if not copy */
1346 if (mode == MOVE_FILE)
1348 if (unlink (from) < 0)
1355 ptr = strrchr(from, '/') + 1;
1356 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."));
1357 msg = XtNewString(tmpStr);
1358 (*errorHandler) (w, msg, ptr);
1368 * WARNING: this is different from how the shell behaves. If you use
1369 * a shell to copy over an existing file, the file keeps its
1370 * original owner and group; for some historical reason,
1371 * dtfile does it differently.
1372 * UPDATE: This is no longer the case as of 10/31/94, we change the
1373 * file to the original owner and group now. This is to fix
1375 * Also, this call originally occurred after we opened/created
1376 * the file, but before we closed it. This caused problems
1377 * if the user was running as root, and was copying across
1378 * an nfs link, since root access is not typically carried
1379 * across an nfs mount. The result was that we were able to
1380 * create the file, copy to it, but when we tried to close it,
1381 * because the file was now owned by root on the other system,
1382 * we could not close the file; thus, the file ended up empty!
1385 if (mode == COPY_FILE && fileExists)
1388 (void) chmod (to, s3.st_mode);
1389 (void) chown (to, s3.st_uid, s3.st_gid);
1394 (void) chown (to, getuid(), getgid());