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: sharedFuncs.c /main/9 1998/04/06 13:15:57 mgreess $ */
24 /************************************<+>*************************************
25 ****************************************************************************
30 * DESCRIPTION: Common functions for both dtfile and dtfile_copy
32 * FUNCTIONS: CreateDefaultImage
39 * (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
40 * (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
41 * (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
42 * (c) Copyright 1993, 1994, 1995 Novell, Inc.
44 ****************************************************************************
45 ************************************<+>*************************************/
47 #if defined(SVR4) || defined(sco)
49 #if defined(USL) || defined(sco)
50 # include <sys/param.h>
51 # include <sys/types.h>
54 # include <sys/fs/s5param.h>
55 # define ROOTINO S5ROOTINO
57 # include <sys/fs/ufs_fs.h>
58 # define ROOTINO UFSROOTINO
60 #endif /* SVR4 || sco */
63 # include <rpc/key_prot.h>
64 # define ROOTINO PROOT
67 #if defined(linux) || defined(CSRG_BASED)
68 # include <sys/param.h>
77 #include <sys/types.h>
78 #include <sys/mount.h>
81 #if !defined(CSRG_BASED)
92 #include <Dt/Connect.h>
93 #include <Dt/DtNlUtils.h>
94 #include <Dt/SharedProcs.h>
96 #include "sharedFuncs.h"
101 /************************************************************************
102 * Bitmap Data for Default Symbol
103 **********************************<->***********************************/
105 static unsigned char errorBits[] = {
106 0x00, 0x00, 0x00, 0xc0, 0x0f, 0x00, 0xf0, 0x3a, 0x00, 0x58, 0x55, 0x00,
107 0x2c, 0xa0, 0x00, 0x56, 0x40, 0x01, 0xaa, 0x80, 0x02, 0x46, 0x81, 0x01,
108 0x8a, 0x82, 0x02, 0x06, 0x85, 0x01, 0x0a, 0x8a, 0x02, 0x06, 0x94, 0x01,
109 0x0a, 0xe8, 0x02, 0x14, 0x50, 0x01, 0x28, 0xb0, 0x00, 0xd0, 0x5f, 0x00,
110 0xa0, 0x2a, 0x00, 0x40, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
112 static unsigned char infoBits[] = {
113 0x00, 0x00, 0x78, 0x00, 0x54, 0x00, 0x2c, 0x00, 0x54, 0x00, 0x28, 0x00,
114 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x2a, 0x00, 0x5c, 0x00, 0x28, 0x00,
115 0x58, 0x00, 0x28, 0x00, 0x58, 0x00, 0x28, 0x00, 0x58, 0x00, 0x28, 0x00,
116 0x58, 0x00, 0xae, 0x01, 0x56, 0x01, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00};
118 static unsigned char questionBits[] = {
119 0xf0, 0x3f, 0x00, 0x58, 0x55, 0x00, 0xac, 0xaa, 0x00, 0xd6, 0x5f, 0x01,
120 0xea, 0xbf, 0x02, 0xf6, 0x7f, 0x01, 0xea, 0xba, 0x02, 0xf6, 0x7d, 0x05,
121 0xea, 0xba, 0x0a, 0x56, 0x7d, 0x15, 0xaa, 0xbe, 0x1e, 0x56, 0x5f, 0x01,
122 0xac, 0xaf, 0x02, 0x58, 0x57, 0x01, 0xb0, 0xaf, 0x00, 0x60, 0x55, 0x01,
123 0xa0, 0xaa, 0x00, 0x60, 0x17, 0x00, 0xa0, 0x2f, 0x00, 0x60, 0x17, 0x00,
124 0xb0, 0x2a, 0x00, 0x50, 0x55, 0x00};
126 static unsigned char warningBits[] = {
127 0x00, 0x00, 0x18, 0x00, 0x2c, 0x00, 0x56, 0x00, 0x2a, 0x00, 0x56, 0x00,
128 0x2a, 0x00, 0x56, 0x00, 0x2c, 0x00, 0x14, 0x00, 0x2c, 0x00, 0x14, 0x00,
129 0x2c, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x14, 0x00,
130 0x2c, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00};
132 static unsigned char workingBits[] = {
133 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0xaa, 0xaa, 0x0a, 0x44, 0x55, 0x06,
134 0xcc, 0x2a, 0x02, 0x44, 0x55, 0x06, 0xcc, 0x2a, 0x02, 0x84, 0x15, 0x06,
135 0x8c, 0x2a, 0x02, 0x04, 0x15, 0x06, 0x0c, 0x0a, 0x02, 0x04, 0x06, 0x06,
136 0x0c, 0x0b, 0x02, 0x84, 0x15, 0x06, 0xcc, 0x2a, 0x02, 0x44, 0x55, 0x06,
137 0xcc, 0x2a, 0x02, 0x44, 0x55, 0x06, 0xcc, 0x2a, 0x02, 0x44, 0x55, 0x06,
138 0xfe, 0xff, 0x0f, 0x56, 0x55, 0x05, 0x00, 0x00, 0x00};
141 int G_dialog_closed = FALSE;
143 /*----------------------------------------------------------
147 * Given a path, return a pointer to the directory (folder)
148 * and file (object). On error, both will be set to empty
151 * The calling routine is responsible for allocating space
152 * for object and folder.
154 * This function simply searches for the last slash (/) in
155 * the path and returns the characters preceding the slash
156 * as folder and the characters after the last slash as
157 * object. Thus, object could be a directory/folder or a
160 * There is a complimentary function, build_path, to put
161 * object and folder back together to form a path.
163 *-----------------------------------------------------------*/
166 split_path(const String path, String folder, String object)
172 if ( (lastSlash = strrchr(path,'/')) != NULL)
174 strcpy(object,lastSlash+1);
175 if(lastSlash == path) /* Must be root Folder */
186 folder[0] = object[0] = '\0';
188 } /* end split_path */
193 char *rpath, tmppath[MAX_PATH];
194 char * _DtCopyPathFromInput();
195 if (!getcwd(tmppath,MAX_PATH))
197 rpath = _DtCopyPathFromInput(path,tmppath);
201 /*-----------------------------------------------------------------
205 * Given a directory (folder) and file (object), build a string
206 * with the complete path and return it.
208 * The calling routine is responsible for freeing storage used
209 * for the returned string.
211 * There is a complimentary function, split_path, to take
212 * path apart to form folder and object
214 *-----------------------------------------------------------------*/
217 build_path(const String folder, const String object)
223 strncpy(s, folder, MAX_PATH);
224 strncat(s, "/", MAX_PATH-strlen(s));
225 strncat(s, object, MAX_PATH-strlen(s));
226 path = (String) malloc(strlen(s)+1);
231 } /* end build_path */
235 /*--------------------------------------------------------------
239 * Given a path, generate a new file name and rename the file.
241 * The rc from the system call is returned and errno is set.
243 *--------------------------------------------------------------*/
246 auto_rename(const String path)
249 char newPath[MAX_PATH];
251 generate_NewPath(newPath,path);
253 return (rename(path,newPath));
255 } /* end auto_rename */
258 /*-----------------------------------------------------------------------
262 * Given a path (and a complete path is required), append a
263 * sequence number to generate a new file name. The new file
264 * will not exist. The sequence number consists of a one-character
265 * delimiter and an integer. The function will start with
266 * 1, if the file with 1 exists it will continue to 2, etc.
267 * newPath and oldPath can point to the same area. The sequence number
268 * is appended to the end of the name unless it contains a
269 * dot, in which case the sequence number precedes the dot. For example,
270 * /cde/dtfile/dtcopy/overwrtdialog.c becomes
271 * /cde/dtfile/dtcopy/overwrtdialog~1.c. However, if the dot
272 * is the first character in the file name, the sequence number is
273 * appended, (e.g. .profile --> .profile~1).
275 *-----------------------------------------------------------------------*/
278 generate_NewPath(String newPath, String oldPath)
282 const char delim = '_';
285 String lastDot, lastSlash;
286 char firstPart[MAX_PATH], lastPart[MAX_PATH];
291 lastDot = strrchr(oldPath,'.');
292 lastSlash = strrchr(oldPath,'/');
293 if (lastSlash == NULL)
294 lastSlash = oldPath - 1; /* allows for no path and first char is dot */
295 len = lastDot - oldPath;
296 if ( lastDot != NULL && /* no dot */
297 lastDot > lastSlash+1 && /* dot is in filename, not directory name */
298 len != strlen(oldPath)-1 ) /* dot is not last character of filename */
300 /* sequence number will be inserted before filename suffix */
301 memcpy(firstPart,oldPath,len);
302 firstPart[len] = '\0';
303 strcpy(lastPart,lastDot);
307 /* sequence number will be appended to filename */
308 strcpy(firstPart,oldPath);
316 sprintf(newPath,"%s%c%d%s",firstPart,delim,i,lastPart);
317 } while (lstat(newPath,&buf) == 0);
322 } /* end generate_NewPath */
325 /****************************************************************
326 * Create a default images for symbol... used in ClassInitialize.
334 unsigned int height )
338 image = XCreateImage(display,
339 DefaultVisual(display, DefaultScreen(display)),
340 1, XYBitmap, 0, bits, width, height, 8,
342 image->byte_order = LSBFirst;
343 image->bitmap_unit = 8;
344 image->bitmap_bit_order = LSBFirst;
347 } /* end CreateDefaultImage */
352 ImageInitialize( Display *display )
356 /* create and install the default images for the symbol */
358 image = CreateDefaultImage (display, (char *)errorBits, 20, 20);
359 XmInstallImage (image, "default_xm_error");
361 image = CreateDefaultImage (display, (char *)infoBits, 11, 24);
362 XmInstallImage (image, "default_xm_information");
364 image = CreateDefaultImage (display, (char *)questionBits, 22, 22);
365 XmInstallImage (image, "default_xm_question");
367 image = CreateDefaultImage (display, (char *)warningBits, 9, 22);
368 XmInstallImage (image, "default_xm_warning");
370 image = CreateDefaultImage (display, (char *)workingBits, 21, 23);
371 XmInstallImage (image, "default_xm_working");
374 } /* end ImageInitialize */
376 #if !defined(CSRG_BASED)
382 if(ustat(dev,&u1) < 0)
389 CopyCheckDeletePermissionRecur(
390 char *destinationPath)
398 DPRINTF(("CheckDeletePermissionRecur(\"%s\")\n", destinationPath));
400 if (lstat(destinationPath, &statbuf) < 0)
401 return -1; /* probably does not exist */
403 if (! S_ISDIR(statbuf.st_mode))
405 if(access(destinationPath,04) < 0)
407 return 0; /* no need to check anything more */
410 dirp = opendir (destinationPath);
412 return -1; /* could not read directory */
417 while (dp = readdir (dirp))
419 if (strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0)
423 /* check for write permission in this directory */
424 if (access(destinationPath, 04|02|01) < 0)
430 /* append a '/' to the end of directory name */
431 fnamep = destinationPath + strlen(destinationPath);
437 /* append file name to end of directory name */
438 strcpy(fnamep, dp->d_name);
440 /* recursively check permission on this file */
441 if (CopyCheckDeletePermissionRecur(destinationPath))
454 CopyCheckDeletePermission(
456 char *destinationPath)
458 #if defined(__FreeBSD__) || defined(__OpenBSD__)
459 struct statfs statbuf;
460 #elif defined(__NetBSD__)
461 struct statvfs statbuf;
465 char fname[PATH_MAX];
467 #if defined(__FreeBSD__) || defined(__OpenBSD__)
468 if (statfs(parentdir,&statbuf) < 0) /* does not exist */
469 #elif defined(__NetBSD__)
470 if (statvfs(parentdir,&statbuf) < 0) /* does not exist */
472 if (lstat(parentdir,&statbuf) < 0) /* does not exist */
476 /* check if we are root */
479 /* if NFS, need to check if server trusts root */
480 #if defined(CSRG_BASED)
481 if (!strcmp(statbuf.f_fstypename, "nfs")) /* Root user and nfs */
483 if (CopyFileSysType(statbuf.st_dev) < 0) /* Root user and nfs */
488 tmpfile = tempnam(parentdir,"dtfile");
491 /* Create a temporary file */
492 if ( (rv = creat(tmpfile,O_RDONLY)) < 0)
498 /* Delete the created file */
499 if (remove(tmpfile) < 0)
511 /* root user can delete anything */
515 /* check for read/write and execute permission on parent dir */
516 if (access(parentdir, R_OK | W_OK | X_OK) < 0)
519 /* copy destinationPath to tmp buffer */
520 strcpy(fname, destinationPath);
522 return CopyCheckDeletePermissionRecur(fname);
531 XtDestroyWidget((Widget)G_toplevel);
537 XtAppContext app_context,
543 if(checkPerms && move)
545 char title[200],*msg,*tmpmsg;
546 char *tmpstring = strdup(source_name),*tmpptr;
551 tmpptr = strrchr(tmpstring,'/');
552 if(!tmpstring || !tmpptr) /* Error */
556 if(tmpptr == tmpstring)
563 perm_status = CopyCheckDeletePermission(tmpptr,source_name);
567 if(!perm_status) /* Everything is fine just return */
574 strcpy(title,GETMESSAGE(4,7,"Object Trash - Error"));
575 tmpmsg = GETMESSAGE(4,8,"You do not have permission to put the object \n\n%s\n\ninto trash.\n\nUse the Change Permissions choice from the object's\npopup menu or from the Selected menu to turn on your\nRead permission on the object.\n\nNote: If this object is a folder, you must also have\nRead permission for each of the objects inside the\nfolder before you can put the folder in the trash.");
577 msg = XtMalloc(strlen(tmpmsg)+strlen(source_name)+2);
578 sprintf(msg,tmpmsg,source_name);
579 _DtMessageDialog (G_toplevel, title, msg, 0, FALSE, NULL,
580 CloseTopLevel, NULL, NULL, False, ERROR_DIALOG);
582 XtAppAddTimeOut(app_context, delay, TimeoutHandler, NULL);
585 /* wait for user to close the dialog before exiting */
587 while (!G_dialog_closed)
589 XtAppNextEvent(app_context, &event);
590 XtDispatchEvent(&event);
596 TimeoutHandler(XtPointer client_data, XtIntervalId *id)
602 * This is a generic function for resolving a cannonical path from user input.
606 _DtCopyPathFromInput(char *input_string, char *current_dir)
609 char *tmp_path = NULL;
611 char *_DtCopyChangeTildeToHome();
613 /* find relative path */
615 tmp_path = path = XtNewString(input_string);
618 /* Strip any spaces from name -- input is overwritten */
619 path = (char *) _DtStripSpaces(path);
621 /* Resolve, if there're any, environement variables */
624 char command[MAX_PATH];
626 sprintf(command,"echo %s",path);
627 if((pfp=popen(command,"r")) == NULL)
633 if (fscanf(pfp,"%s",command) >= 1)
636 path = XtNewString(command);
648 /* Resolve '~' -- new memory is allocated, old memory is freed */
650 path = _DtCopyChangeTildeToHome(path);
652 /* If current dir provided, check for relative path */
653 if (path && current_dir)
657 /* file is relative path i.e. xyz/abc */
658 if (strcmp(current_dir, "/") == 0)
660 tmp_path = (char *)XtMalloc(strlen(current_dir) + strlen(path) + 1);
661 sprintf(tmp_path, "%s%s", current_dir, path);
665 tmp_path = (char *)XtMalloc(strlen(current_dir) + strlen(path) + 2);
666 sprintf(tmp_path, "%s/%s", current_dir, path);
680 /* Resolve '.' or '..' -- input is overwritten, output may be NULL! */
681 /* Save pointer to path to free if output is NULL. */
683 path = (char *) XeEliminateDots(path);
685 /* Strip off trailing '/' */
686 dir_len = strlen(path);
687 if (dir_len > 1 && *(path + dir_len - 1) == '/')
688 *(path + dir_len - 1) = '\0';
693 _DtCopyChangeTildeToHome (input_string)
696 _DtCopyChangeTildeToHome (
702 struct passwd * pwInfo;
703 char * homedir = (char *) XtNewString(getenv("HOME"));
705 if ((input_string[1] != '/'))
709 /* ~user or ~user/path format */
711 /* is there a path? */
712 path = (char *) DtStrchr(input_string, '/');
717 if ((pwInfo = getpwnam(input_string + 1)) == NULL)
719 /* user doesn't exist */
727 /* ~user/path format */
731 if (strcmp(pwInfo->pw_dir, "/") == 0)
733 /* We don't want to end up with double '/' in the path */
734 full_path = (char *) XtMalloc(strlen(path) + 1);
735 strcpy(full_path, path);
739 full_path = (char *) XtMalloc(strlen(pwInfo->pw_dir) +
741 sprintf(full_path, "%s%s", pwInfo->pw_dir, path);
748 full_path = XtMalloc(strlen(pwInfo->pw_dir) + 1);
749 strcpy(full_path, pwInfo->pw_dir);
752 else if (input_string[1])
756 /* NOTE: users_home_dir has trailing '/' */
757 full_path = (char *) XtMalloc(strlen(homedir) + strlen(input_string+2) + 1);
758 sprintf(full_path, "%s%s", homedir, (input_string + 2));
765 full_path = XtMalloc(strlen(homedir) + 1);
766 strcpy(full_path, homedir);
770 XtFree(input_string);
775 Check(char *spth, char *dpth, int mode)
777 struct stat sbuf, dbuf;
778 char filename [MAX_PATH];
784 if (lstat (spth, &sbuf) < 0)
786 tmpStr = (GETMESSAGE(4,9, "Cannot open %s"));
787 msg = XtMalloc(strlen(tmpStr)+strlen(filename)+1);
788 sprintf(msg,tmpStr,filename);
789 _DtMessageDialog (G_toplevel, title, msg, 0, FALSE, NULL,
790 CloseTopLevel, NULL, NULL, False, ERROR_DIALOG);
794 (void) strcpy (filename, dpth);
796 strcpy(title,GETMESSAGE(4,5,"Object Move - Error"));
798 strcpy(title,GETMESSAGE(4,6,"Object Copy - Error"));
801 while (dbuf.st_ino != ROOTINO)
803 /* Destination may not be available, in which case we need to
804 create it, so just return as successful and the remaining
805 code takes care of everything */
807 if (lstat (filename, &dbuf) < 0)
810 if (dbuf.st_ino == sbuf.st_ino)
813 tmpStr = GETMESSAGE(3,19,"Cannot move folder into itself. %s");
815 tmpStr = GETMESSAGE(3,20,"Cannot copy folder into itself. %s");
816 msg = XtMalloc(strlen(tmpStr)+strlen(dpth)+1);
817 sprintf(msg,tmpStr,dpth);
818 _DtMessageDialog (G_toplevel, title, msg, 0, FALSE, NULL,
819 CloseTopLevel, NULL, NULL, False, ERROR_DIALOG);
825 (void) strcat (filename, "/..");