1 /* $TOG: FileManip.c /main/10 1999/12/09 13:06:10 mgreess $ */
2 /************************************<+>*************************************
3 ****************************************************************************
7 * COMPONENT_NAME: Desktop File Manager (dtfile)
9 * Description: This module does the copy, move and rename commands.
10 * Included are functions to control command execution,
11 * move a directory, get the directory portion of a pathname,
12 * get the file name portion of a pathname, and check if a
13 * folder is to be moved within itself.
24 * (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
25 * (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
26 * (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
27 * (c) Copyright 1993, 1994, 1995 Novell, Inc.
29 ****************************************************************************
30 ************************************<+>*************************************/
32 #if defined(SVR4) || defined(sco)
33 # if defined(USL) || defined(sco) || defined(__uxp__)
34 # include <sys/param.h>
35 # include <sys/types.h>
38 # include <sys/fs/s5param.h>
39 # define ROOTINO S5ROOTINO
41 # include <sys/fs/ufs_fs.h>
42 # define ROOTINO UFSROOTINO
48 # include <sys/param.h>
49 #endif /* SVR4 || sco */
51 #include <sys/types.h>
59 /** The following ifdefs need to be straightened out
73 #include <sys/access.h>
95 #include <Xm/MwmUtil.h>
97 #include <Dt/DtP.h> /* required for DtDirPaths type */
98 #include <Dt/Connect.h>
99 #include <Dt/DtNlUtils.h>
102 #include "SharedProcs.h"
107 #include "SharedMsgs.h"
109 #ifndef CDE_INSTALLATION_TOP
110 #define CDE_INSTALLATION_TOP "/usr/dt"
113 /* Local Function Definitions */
114 static char * MOVE_CMD = "/bin/mv";
115 static char * LINK_CMD = "/bin/ln";
116 static char * REMOVE_CMD = "/bin/rm";
117 static char * DTCOPY = CDE_INSTALLATION_TOP "/bin/dtfile_copy";
120 /************************************************************************
124 ************************************************************************/
134 #if defined(__hp_osf) || defined(__ultrix)
135 /*--------------------------------------------------------------------
136 * access code for __hp_osf, __ultrix
137 *------------------------------------------------------------------*/
139 setreuid(geteuid(),-1);
140 return access (fname, what);
144 /*--------------------------------------------------------------------
145 * access code for BLS
146 *------------------------------------------------------------------*/
148 setresuid(geteuid(),-1,-1);
149 return access (fname, what);
151 #else /* the rest of the OS's */
153 save_ruid = getuid();
156 setreuid(geteuid(),-1);
161 save_rgid = getgid();
164 setregid(getegid(),-1);
169 access_priv = access (fname, what);
172 setreuid(save_ruid,-1);
173 setregid(save_rgid,-1);
181 #endif /* Apollo & OSF */
185 /************************************************************************
188 * Display an error message.
190 ************************************************************************/
201 if (message2 != NULL)
203 message_buf = XtMalloc(strlen(message1) + strlen(message2) + 1);
204 (void) sprintf(message_buf,message1, message2);
208 message_buf = XtMalloc(strlen(message1) + 1);
209 (void) sprintf(message_buf,message1);
212 /* Display an error dialog */
213 tmpStr = GetSharedMessage(FILE_MANIPULATION_ERROR_TITLE);
214 title = XtNewString(tmpStr);
215 _DtMessage (w, title, message_buf, NULL, HelpRequestCB);
221 /************************************************************************
224 * Returns the file name of its argument.
225 * Keep looking thru the string until a "/" is found which still
226 * has some characters after it.
228 ************************************************************************/
231 register char *name )
240 q = DtStrchr(q, '/');
254 /************************************************************************
258 ************************************************************************/
263 register ino_t dinode,
265 void (*errorHandler)() )
268 char filename [MAX_PATH];
274 (void) strcpy (filename, spth);
276 while (sbuf.st_ino != ROOTINO)
278 if (lstat (filename, &sbuf) < 0)
282 tmpStr = (GETMESSAGE(11,33, "Cannot open %s"));
283 msg = XtNewString(tmpStr);
284 (*errorHandler) (w, msg, filename);
290 if (sbuf.st_ino == dinode)
294 if (mode == COPY_FILE)
295 tmpStr = GETMESSAGE(11,35, "Cannot copy a folder into itself.");
297 tmpStr = GETMESSAGE(11,16, "A folder cannot be moved into itself.\n%s");
298 msg = XtNewString(tmpStr);
299 if (mode == COPY_FILE)
300 (*errorHandler) (w, msg, NULL);
302 (*errorHandler) (w, msg, filename);
308 (void) strcat (filename, "/..");
315 /************************************************************************
319 ************************************************************************/
324 register char *source,
325 register char *target,
326 struct stat *sourceStatInfo,
327 void (*errorHandler)(),
331 static char *pname = "MoveDir";
334 char * targetDir; /* original target dir path */
338 struct stat s1; /* status of from file */
339 struct stat s2; /* status of to file */
343 static char buf [BUF_SIZE]; /* generic buffer */
344 char filename [MAX_PATH]; /* buffer to hold the full file name */
349 /* Copy target so we have it for an error dialog if we need it */
350 targetDir = XtNewString(target);
353 if ((val = stat (target, &s2)) < 0)
354 val = lstat(target, &s2);
356 /* Check if move to itself */
357 if( sourceStatInfo->st_dev == s2.st_dev)
359 if (Check (w, target, sourceStatInfo->st_ino, MOVE_FILE, NULL ))
363 if (val >= 0) /* target exists */
365 if ((s2.st_mode & S_IFMT) != S_IFDIR) /* target not directory */
370 tmpStr = GetSharedMessage(CANT_OVERWRITE_ERROR);
371 msg = XtNewString(tmpStr);
372 (*errorHandler) (w, msg, target);
379 (void) strcpy (buf, target);
383 DtLastChar(buf, &cptr, &len);
384 if ((len != 1) || (*cptr != '/'))
385 (void) strcat (buf, "/");
386 (void) strcat (buf, DName (source));
388 if (lstat (target, &s2) >= 0) /* new target exists */
394 tmpStr = GetSharedMessage(CANT_OVERWRITE_ERROR);
395 msg = XtNewString(tmpStr);
396 (*errorHandler) (w, msg, target);
407 /* don't rename these */
408 DtLastChar(p, &cptr, &len);
410 if (!strcmp (p, ".") || !strcmp (p, "..") ||
411 !strcmp (p, "") || ((len == 1) && (*cptr == '/')))
417 tmpStr = (GETMESSAGE(11,32, "Cannot rename %s"));
418 msg = XtNewString(tmpStr);
419 (*errorHandler) (w, msg, p);
427 /* parent doesn't exist */
428 if((val = stat (_DtPName (source), &s1)) < 0)
429 val = lstat (_DtPName (source), &s1);
431 if((val1 = stat (_DtPName (target), &s2)) < 0)
432 val1 = lstat (_DtPName (target), &s2);
434 if (val < 0 || val1 < 0)
438 tmpStr = GETMESSAGE(11, 14, "Cannot find the folders location.");
439 msg = XtNewString(tmpStr);
440 (*errorHandler) (w, msg, NULL);
448 /* check for target parent not writeable */
449 if (CheckAccess(_DtPName (target), W_OK) == -1)
455 tmpStr = GetSharedMessage(CANT_WRITE_ERROR);
456 msg = XtNewString(tmpStr);
457 (*errorHandler) (w, msg, targetDir);
465 /* check for source parent not writeable */
466 if (CheckAccess(_DtPName (source), W_OK) == -1)
472 tmpStr = GetSharedMessage(CANT_WRITE_ERROR);
473 msg = XtNewString(tmpStr);
474 (*errorHandler) (w, msg, source);
481 if (((sourceStatInfo->st_mode & S_IFMT) == S_IFDIR) &&
482 (CheckAccess(source, W_OK) != 0))
488 tmpStr=GETMESSAGE(11, 57,"You do not have permission to move the folder\n%s\nWrite permission is required.");
489 msg = XtMalloc(strlen(tmpStr) + strlen(source) + 2);
490 sprintf(msg, tmpStr, source);
491 (*errorHandler) (w, msg, source);
498 /* if parents are not on the same device, do a copy & delete */
499 if (s1.st_dev != s2.st_dev)
501 /* Determine correct Geometry Placement fo Move Dialog */
502 /* @@@ ... to be added */
509 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.");
510 msg = XtNewString(tmpStr);
511 (*errorHandler) (w, msg, NULL);
520 DBGFORK(("%s: child forked\n", pname));
522 /* pass in geometry, and other command lines params when available */
523 if(type == TRASH_DIRECTORY)
524 rc = execlp(DTCOPY, "dtfile_copy", "-move", "-confirmReplace",
525 "-confirmErrors", "-popDown","-checkPerms", source, target, 0);
527 rc = execlp(DTCOPY, "dtfile_copy", "-move", "-confirmReplace",
528 "-confirmErrors", "-popDown", source, target, 0);
530 /* call errorhandler */
531 perror ("Could not exec child process \"dtfile_copy\"");
533 DBGFORK(("%s: child exiting\n", pname));
538 DBGFORK(("%s: forked child<%d>\n", pname, child_pid));
545 link_path = _DtFollowLink(source);
548 if (s1.st_ino != s2.st_ino)
549 { /* different parent inodes */
550 (void) lstat (source, &s1); /* get source dir ino */
553 if (Check (w, _DtPName (target), s1.st_ino, MOVE_FILE, errorHandler))
554 { /* move into self */
560 /* This part of code was implemented with the idea that the links
561 to be treated differently. So, it has to be uncommented whenever
562 links are handled differently (i.e., moving a link shall move the
565 if(strcmp(link_path, source) != 0)
567 if (RunFileCommand (MOVE_CMD, link_path, target, NULL) == 0)
576 if (RunFileCommand (MOVE_CMD, source, target, NULL) == 0)
588 /************************************************************************
592 ************************************************************************/
601 void (*errorHandler)(),
602 Boolean checkForBusyDir,
605 static char *pname = "CopyDir";
608 char target [MAX_PATH]; /* buffer to hold the full file name */
609 char target_dir [MAX_PATH], target_file [MAX_PATH];
610 struct stat s2; /* status of to file */
611 int child_pid, rc, target_rc;
614 /* Check if source is readable */
615 if (CheckAccess(from, R_OK) == -1)
619 tmpStr = GetSharedMessage(CANT_READ_ERROR);
620 msg = XtNewString(tmpStr);
621 (*errorHandler) (w, msg, from);
627 /* generate target name */
628 /* "to" can be something to copy the source into (isContainer=TRUE) */
629 /* or it can be the full path of the destination (isContainer=FALSE) */
630 /* the former case is probably more common (e.g. a drag&drop copy) */
631 /* whereas the second case occurs when, for example, the menu is */
632 /* to copy directory /u/joe/a to /u/joe/b (not doable with d&d) */
633 (void) strcpy (target, to);
636 DtLastChar(to, &cptr, &len);
637 if ((len != 1) || (*cptr != '/'))
638 (void) strcat (target, "/");
639 (void) strcat (target, DName (from));
641 split_path(target, target_dir, target_file);
643 /* Check if target directory exists */
644 if ((target_rc = stat (target, &s2)) < 0)
645 target_rc = lstat(target, &s2);
650 * make sure it's a directory */
652 if ((s2.st_mode & S_IFMT) != S_IFDIR) /* target not directory */
656 tmpStr = GetSharedMessage(CANT_OVERWRITE_ERROR);
657 msg = XtNewString(tmpStr);
658 (*errorHandler) (w, msg, target);
666 /* target does not exist:
667 * make sure the "to" directory exists and is writable */
668 if ((rc = stat (target_dir, &s2)) < 0)
669 rc = lstat(target_dir, &s2);
671 if (rc < 0 || (s2.st_mode & S_IFMT) != S_IFDIR)
675 tmpStr = GETMESSAGE(11, 14, "Cannot find the folders location.");
676 msg = XtNewString(tmpStr);
677 (*errorHandler) (w, msg, NULL);
683 if (CheckAccess(target_dir, W_OK) == -1)
687 tmpStr = GetSharedMessage(CANT_WRITE_ERROR);
688 msg = XtNewString(tmpStr);
689 (*errorHandler) (w, msg, to);
696 /* Determine if we are attempting a copy into self */
697 if (s1->st_dev == s2.st_dev)
701 if (Check (w, to, s1->st_ino, COPY_FILE, errorHandler))
704 else /* destination dir does not exist, look at its proposed parent */
706 if (Check (w, target_dir, s1->st_ino, COPY_FILE, errorHandler))
711 /* Determine correct Geometry Placement fo Copy Dialog */
712 /* @@@ ... to be added */
714 /* If all the above checks have passed, then fork off the copy dialog */
721 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.");
722 msg = XtNewString(tmpStr);
723 (*errorHandler) (w, msg, NULL);
731 DBGFORK(("%s: child forked\n", pname));
733 /* pass in geometry, and other command lines params when available */
734 if (mode == MERGE_DIR)
735 /* merge source & target directories */
736 rc = execlp(DTCOPY, "dtfile_copy",
737 "-dontDelete", "-forceCopies", "-copyTop",
738 "-confirmReplace", "-confirmErrors", "-popDown",
741 /* replace target dir */
742 rc = execlp(DTCOPY, "dtfile_copy",
743 "-forceCopies", "-copyTop",
744 "-confirmErrors", "-popDown",
747 /* call errorhandler */
748 perror ("Could not exec child process \"dtfile_copy\"");
750 DBGFORK(("%s: child exiting\n", pname));
755 DBGFORK(("%s: forked child<%d>\n", pname, child_pid));
762 /************************************************************************
766 ************************************************************************/
773 Boolean isContainer, /* described in function CopyDir */
774 void (*errorHandler)(),
775 Boolean checkForBusyDir,
781 Boolean copy_dir_return;
782 Boolean move_dir_return;
789 Boolean restricted = False;
790 Boolean fileExists = False;
792 struct stat s1; /* status of from file e.g. lstat info */
793 struct stat s4; /* status of from file e.g. stat info */
794 struct stat s2; /* status of to file e.g. stat info */
795 struct stat s3; /* status of to file e.g. lstat info */
797 char buf [BLOCK_SIZE]; /* generic buffer */
798 char filename [MAX_PATH]; /* buffer to hold the full file name */
805 /* Check the <from> part of the command:
807 * Report error if <from> doesn't exist.
808 * Else error if <from> hasn't read access.
811 DPRINTF(("FileManip: mode %d type %d from \"%s\" to \"%s\"\n", mode, type, from, to));
812 if (stat (from, &s1) < 0)
814 if (lstat (from, &s1) < 0)
818 tmpStr = (GETMESSAGE(11,28, "%s cannot be found."));
819 msg = XtNewString(tmpStr);
820 (*errorHandler) (w, msg, from);
827 /* We will check if we need to initiate a copy of a directory */
828 if ((s1.st_mode & S_IFMT) == S_IFDIR) /* from is a directory */
830 if (mode == COPY_FILE || mode == MERGE_DIR)
832 oldInt = signal (SIGINT, SIG_IGN);
833 oldQuit = signal (SIGQUIT, SIG_IGN);
834 oldPipe = signal (SIGPIPE, SIG_IGN);
835 oldTerm = signal (SIGTERM, SIG_IGN);
837 copy_dir_return = CopyDir(w, mode, from, to, isContainer, &s1,
838 errorHandler, checkForBusyDir, type);
840 (void) signal (SIGINT, oldInt);
841 (void) signal (SIGQUIT, oldQuit);
842 (void) signal (SIGPIPE, oldPipe);
843 (void) signal (SIGTERM, oldTerm);
845 return (copy_dir_return);
849 /* If the directory has more than one open view or open views */
850 /* of sub directories. Then do not allow the move or rename. */
852 if (mode == MOVE_FILE)
854 if (checkForBusyDir && DirectoryBusy (from))
858 char message_buf[512];
861 message_buf[0] = NULL;
862 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."));
863 sprintf (message_buf, tmpStr, from);
864 (*errorHandler) (w, message_buf, NULL);
870 oldInt = signal (SIGINT, SIG_IGN);
871 oldQuit = signal (SIGQUIT, SIG_IGN);
872 oldPipe = signal (SIGPIPE, SIG_IGN);
873 oldTerm = signal (SIGTERM, SIG_IGN);
875 move_dir_return = MoveDir (w, from, to, &s1, errorHandler, &realTarget,type);
877 (void) signal (SIGINT, oldInt);
878 (void) signal (SIGQUIT, oldQuit);
879 (void) signal (SIGPIPE, oldPipe);
880 (void) signal (SIGTERM, oldTerm);
882 return (move_dir_return);
885 if (mode == LINK_FILE)
887 /* Need to append the directory name on */
888 (void) strcpy(filename, to);
893 tmp = (char *)XtMalloc(strlen(filename) + 1);
894 strcpy(tmp, filename);
895 /* get the workspace number first */
896 ptr = strrchr(tmp, '/');
898 /* now get the Desktop */
899 ptr = strrchr(tmp, '/');
901 /* if we don't get "/Desktop" then there is another filename
902 attached to the end of the to name passed in */
903 if(strcmp(ptr, "/Desktop") != 0)
908 if( (!restricted && type != TRASH_DIRECTORY) && isContainer)
910 DtLastChar(to, &cptr, &len);
911 if ((len != 1) || (*cptr != '/'))
912 (void) strcat(filename, "/");
915 if(strcmp(from, "/.") == 0 || strcmp(from, "/") == 0)
917 (void) strcat(filename, home_host_name);
918 (void) strcat(filename, ":");
919 (void) strcat(filename, root_title);
921 else if ( (!restricted && type != TRASH_DIRECTORY) && isContainer)
922 (void) strcat(filename, DName(from));
926 if (((link_result = symlink(from, to)) != 0) && errorHandler)
928 if(type == NOT_DESKTOP || errno != EEXIST )
932 tmpStr = GetSharedMessage(CANT_CREATE_ERROR);
933 msg = XtNewString(tmpStr);
934 (*errorHandler) (w, msg, to);
939 return(link_result == 0 ? True : False);
943 if (CheckAccess(from, R_OK) == -1)
946 * A move operation does not require read permission, but a copy does.
948 if (mode == COPY_FILE)
954 tmpStr = GetSharedMessage(CANT_READ_ERROR);
955 msg = XtNewString(tmpStr);
956 (*errorHandler) (w, msg, from);
964 /* Here <from> is a file (not a directory).
965 * Check the <to> part of the command:
967 * <To> can either be an existing file,
968 * an existing directory,
969 * or a new file in an existing directory.
972 if (lstat (to, &s2) >= 0) /* <to> exists */
974 if ((stat (to, &s3) >= 0) &&
975 #if defined(__hp_osf) || (__ultrix) || defined(__osf__) || defined(linux)
976 (((s3.st_mode & S_IFMT) == S_IFDIR) /* if is a directory */
977 || ((s3.st_mode & S_IFMT) == S_IFSOCK)) ) /* or a net special */
979 #if defined(SVR4) || defined(_AIX) || defined(sco)
980 ((s3.st_mode & S_IFMT) == S_IFDIR) ) /* if is a directory */
982 (((s3.st_mode & S_IFMT) == S_IFDIR) /* if is a directory */
983 || ((s3.st_mode & S_IFMT) == S_IFNWK)) ) /* or a net special */
986 { /* then get file name */
987 (void) strcpy (filename, to);
989 DtLastChar(to, &cptr, &len);
990 if ((len != 1) || (*cptr != '/'))
991 (void) strcat (filename, "/");
993 (void) strcat (filename, DName (from));
998 if (lstat (to, &s2) >= 0) /* reverify <to> exists */
1000 if ((stat (to, &s3) >= 0) &&
1001 ((s3.st_mode & S_IFMT) == S_IFDIR)) /* if is a directory */
1007 tmpStr = GetSharedMessage(CANT_OVERWRITE_ERROR);
1008 msg = XtNewString(tmpStr);
1009 (*errorHandler) (w, msg, to);
1016 /* <from> = <to> NOOP. */
1018 if (s1.st_dev == s2.st_dev && s1.st_ino == s2.st_ino)
1022 /* no write permission */
1023 if (CheckAccess(to, W_OK) == -1)
1027 link_path = _DtFollowLink(to);
1028 if(strcmp(to,link_path) == 0)
1034 tmpStr = GetSharedMessage(CANT_OVERWRITE_ERROR);
1035 msg = XtNewString(tmpStr);
1036 (*errorHandler) (w, msg, to);
1046 if (unlink (to) < 0)
1052 tmpStr = GetSharedMessage(CANT_OVERWRITE_ERROR);
1053 msg = XtNewString(tmpStr);
1054 (*errorHandler) (w, msg, to);
1064 /* Here <from> is a file and <to> doesn't exist.
1066 * If not a copy, link the files. If the link succeeds, unlink
1067 * <from> and return.
1068 * Copy <from> to <to>.
1069 * If the copy cmd is not specified, unlink <from>.
1072 if (mode != COPY_FILE)
1074 /* Try to maintain symbolic links, except when we're doing a link! */
1075 if (((s1.st_mode & S_IFMT) == S_IFLNK) && (mode != LINK_FILE))
1077 char link_path[MAX_PATH + 1];
1080 if ((link_len = readlink(from, link_path, MAX_PATH)) > 0)
1082 link_path[link_len] = '\0';
1083 link_result = symlink(link_path, to);
1087 /* Fail-safe; do it the hard way */
1088 if (mode == MOVE_FILE)
1089 if (RunFileCommand(MOVE_CMD, from, to, NULL) == 0)
1092 if (RunFileCommand(LINK_CMD, "-s", from, to) == 0)
1100 if (mode == LINK_FILE)
1101 link_result = symlink(from, to);
1106 link_path = _DtFollowLink(from);
1108 if(strcmp(link_path, from) != 0)
1109 link_result = symlink(link_path, to);
1111 link_result = link (from, to);
1115 /* If this was a link, then time to bail out */
1116 if (mode == LINK_FILE)
1118 if ((link_result != 0) && errorHandler)
1122 tmpStr = GetSharedMessage(CANT_CREATE_ERROR);
1123 msg = XtNewString(tmpStr);
1124 (*errorHandler) (w, msg, to);
1128 return(link_result == 0 ? True : False);
1131 /* Unlink source only if this was a move request */
1132 if ((mode == MOVE_FILE) && (link_result >= 0))
1134 if (unlink (from) < 0)
1140 tmpStr = GetSharedMessage(CANT_DELETE_ERROR);
1141 msg = XtNewString(tmpStr);
1142 (*errorHandler) (w, msg, from);
1153 /* unable to read <from> */
1155 if ((fold = open (from, O_RDONLY)) < 0)
1161 tmpStr = GetSharedMessage(CANT_READ_ERROR);
1162 msg = XtNewString(tmpStr);
1163 (*errorHandler) (w, msg, from);
1170 /* unable create <to> */
1173 /* We use the stat buffer info not lstat info */
1174 (void) stat (from, &s4);
1176 if ((fnew = creat (to, (int) s4.st_mode)) < 0)
1182 tmpStr = GetSharedMessage(CANT_CREATE_ERROR);
1183 msg = XtNewString(tmpStr);
1184 (*errorHandler) (w, msg, to);
1187 (void) close (fold);
1194 while (n = read (fold, buf, BLOCK_SIZE))
1202 tmpStr = (GETMESSAGE(11,31, "Error while reading %s"));
1203 msg = XtNewString(tmpStr);
1204 (*errorHandler) (w, msg, to);
1207 (void) close (fold);
1208 (void) close (fnew);
1213 result = write(fnew, buf, n);
1216 (void) close (fold);
1217 (void) close (fnew);
1220 char * strerrormsg = NULL;
1221 char * catmsg = NULL;
1222 char * samsg = NULL;
1224 Boolean unknown = False;
1232 if(mode == COPY_FILE)
1233 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."));
1235 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."));
1236 catmsg = XtNewString(tmpStr);
1242 if(mode == COPY_FILE)
1243 tmpStr = (GETMESSAGE(11,42, "No space available on the\ndevice you are copying to.\n\n"));
1245 tmpStr = (GETMESSAGE(11,43, "No space available on the\ndevice you are moving to.\n"));
1246 catmsg = XtNewString(tmpStr);
1250 sprintf(errnoMsg, "EAGAIN: ");
1251 strerrormsg = strerror(errno);
1254 sprintf(errnoMsg, "EBADF: ");
1255 strerrormsg = strerror(errno);
1258 sprintf(errnoMsg, "EDEADLK: ");
1259 strerrormsg = strerror(errno);
1262 sprintf(errnoMsg, "EINTR: ");
1263 strerrormsg = strerror(errno);
1266 sprintf(errnoMsg, "EIO: ");
1267 strerrormsg = strerror(errno);
1270 sprintf(errnoMsg, "ENOLCK: ");
1271 strerrormsg = strerror(errno);
1274 sprintf(errnoMsg, "EPIPE: ");
1275 strerrormsg = strerror(errno);
1279 sprintf(errnoMsg, GETMESSAGE(11,56, "(Unknown):"));
1280 strerrormsg = strerror(errno);
1284 /* If catmsg is NULL then one of the miscellanous error's occured.
1285 * Set up a generic error message which will output the internal
1290 if(mode == COPY_FILE)
1291 tmpStr = (GETMESSAGE(11,53, "The copy of the file/folder failed\ndue to some internal error. The internal\nerror given is:"));
1293 tmpStr = (GETMESSAGE(11,54, "The move of the file/folder failed\ndue to some internal error. The internal\nerror given is:"));
1294 catmsg = XtNewString(tmpStr);
1295 tmpStr = (GETMESSAGE(11,55, "Please see your System Adminstrator"));
1296 samsg = XtNewString(tmpStr);
1299 /* Build a concatination of the possible message parts */
1300 bufLen = (strerrormsg ? strlen(strerrormsg) +
1301 strlen(errnoMsg) + strlen(samsg) : 0) +
1302 strlen(catmsg) + 10;
1303 msg = XtMalloc(bufLen);
1304 strcpy (msg, catmsg);
1307 strcat (msg, "\n\n");
1308 strcat (msg, errnoMsg);
1311 strcat (msg, strerrormsg);
1312 strcat (msg, "\n\n");
1313 strcat (msg, samsg);
1316 (*errorHandler) (w, msg, to);
1325 (void) close (fold);
1326 (void) close (fnew);
1329 /* unlink <from> if not copy */
1331 if (mode == MOVE_FILE)
1333 if (unlink (from) < 0)
1340 ptr = strrchr(from, '/') + 1;
1341 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."));
1342 msg = XtNewString(tmpStr);
1343 (*errorHandler) (w, msg, ptr);
1353 * WARNING: this is different from how the shell behaves. If you use
1354 * a shell to copy over an existing file, the file keeps its
1355 * original owner and group; for some historical reason,
1356 * dtfile does it differently.
1357 * UPDATE: This is no longer the case as of 10/31/94, we change the
1358 * file to the original owner and group now. This is to fix
1360 * Also, this call originally occurred after we opened/created
1361 * the file, but before we closed it. This caused problems
1362 * if the user was running as root, and was copying across
1363 * an nfs link, since root access is not typically carried
1364 * across an nfs mount. The result was that we were able to
1365 * create the file, copy to it, but when we tried to close it,
1366 * because the file was now owned by root on the other system,
1367 * we could not close the file; thus, the file ended up empty!
1370 if (mode == COPY_FILE && fileExists)
1373 (void) chmod (to, s3.st_mode);
1374 (void) chown (to, s3.st_uid, s3.st_gid);
1379 (void) chown (to, getuid(), getgid());