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) || defined(__uxp__)
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
68 # include <sys/fs/ufs_fs.h>
69 # define ROOTINO UFSROOTINO
72 #if defined(linux) || defined(CSRG_BASED)
73 # include <sys/param.h>
82 #include <sys/types.h>
83 #include <sys/mount.h>
86 #if !defined(CSRG_BASED)
97 #include <Dt/Connect.h>
98 #include <Dt/DtNlUtils.h>
99 #include <Dt/SharedProcs.h>
101 #include "sharedFuncs.h"
106 /************************************************************************
107 * Bitmap Data for Default Symbol
108 **********************************<->***********************************/
110 static unsigned char errorBits[] = {
111 0x00, 0x00, 0x00, 0xc0, 0x0f, 0x00, 0xf0, 0x3a, 0x00, 0x58, 0x55, 0x00,
112 0x2c, 0xa0, 0x00, 0x56, 0x40, 0x01, 0xaa, 0x80, 0x02, 0x46, 0x81, 0x01,
113 0x8a, 0x82, 0x02, 0x06, 0x85, 0x01, 0x0a, 0x8a, 0x02, 0x06, 0x94, 0x01,
114 0x0a, 0xe8, 0x02, 0x14, 0x50, 0x01, 0x28, 0xb0, 0x00, 0xd0, 0x5f, 0x00,
115 0xa0, 0x2a, 0x00, 0x40, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
117 static unsigned char infoBits[] = {
118 0x00, 0x00, 0x78, 0x00, 0x54, 0x00, 0x2c, 0x00, 0x54, 0x00, 0x28, 0x00,
119 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x2a, 0x00, 0x5c, 0x00, 0x28, 0x00,
120 0x58, 0x00, 0x28, 0x00, 0x58, 0x00, 0x28, 0x00, 0x58, 0x00, 0x28, 0x00,
121 0x58, 0x00, 0xae, 0x01, 0x56, 0x01, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00};
123 static unsigned char questionBits[] = {
124 0xf0, 0x3f, 0x00, 0x58, 0x55, 0x00, 0xac, 0xaa, 0x00, 0xd6, 0x5f, 0x01,
125 0xea, 0xbf, 0x02, 0xf6, 0x7f, 0x01, 0xea, 0xba, 0x02, 0xf6, 0x7d, 0x05,
126 0xea, 0xba, 0x0a, 0x56, 0x7d, 0x15, 0xaa, 0xbe, 0x1e, 0x56, 0x5f, 0x01,
127 0xac, 0xaf, 0x02, 0x58, 0x57, 0x01, 0xb0, 0xaf, 0x00, 0x60, 0x55, 0x01,
128 0xa0, 0xaa, 0x00, 0x60, 0x17, 0x00, 0xa0, 0x2f, 0x00, 0x60, 0x17, 0x00,
129 0xb0, 0x2a, 0x00, 0x50, 0x55, 0x00};
131 static unsigned char warningBits[] = {
132 0x00, 0x00, 0x18, 0x00, 0x2c, 0x00, 0x56, 0x00, 0x2a, 0x00, 0x56, 0x00,
133 0x2a, 0x00, 0x56, 0x00, 0x2c, 0x00, 0x14, 0x00, 0x2c, 0x00, 0x14, 0x00,
134 0x2c, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x14, 0x00,
135 0x2c, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00};
137 static unsigned char workingBits[] = {
138 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0xaa, 0xaa, 0x0a, 0x44, 0x55, 0x06,
139 0xcc, 0x2a, 0x02, 0x44, 0x55, 0x06, 0xcc, 0x2a, 0x02, 0x84, 0x15, 0x06,
140 0x8c, 0x2a, 0x02, 0x04, 0x15, 0x06, 0x0c, 0x0a, 0x02, 0x04, 0x06, 0x06,
141 0x0c, 0x0b, 0x02, 0x84, 0x15, 0x06, 0xcc, 0x2a, 0x02, 0x44, 0x55, 0x06,
142 0xcc, 0x2a, 0x02, 0x44, 0x55, 0x06, 0xcc, 0x2a, 0x02, 0x44, 0x55, 0x06,
143 0xfe, 0xff, 0x0f, 0x56, 0x55, 0x05, 0x00, 0x00, 0x00};
146 int G_dialog_closed = FALSE;
148 /*----------------------------------------------------------
152 * Given a path, return a pointer to the directory (folder)
153 * and file (object). On error, both will be set to empty
156 * The calling routine is responsible for allocating space
157 * for object and folder.
159 * This function simply searches for the last slash (/) in
160 * the path and returns the characters preceding the slash
161 * as folder and the characters after the last slash as
162 * object. Thus, object could be a directory/folder or a
165 * There is a complimentary function, build_path, to put
166 * object and folder back together to form a path.
168 *-----------------------------------------------------------*/
171 split_path(const String path, String folder, String object)
177 if ( (lastSlash = strrchr(path,'/')) != NULL)
179 strcpy(object,lastSlash+1);
180 if(lastSlash == path) /* Must be root Folder */
191 folder[0] = object[0] = '\0';
193 } /* end split_path */
198 char *rpath, tmppath[MAX_PATH];
199 char * _DtCopyPathFromInput();
200 if (!getcwd(tmppath,MAX_PATH))
202 rpath = _DtCopyPathFromInput(path,tmppath);
206 /*-----------------------------------------------------------------
210 * Given a directory (folder) and file (object), build a string
211 * with the complete path and return it.
213 * The calling routine is responsible for freeing storage used
214 * for the returned string.
216 * There is a complimentary function, split_path, to take
217 * path apart to form folder and object
219 *-----------------------------------------------------------------*/
222 build_path(const String folder, const String object)
228 strncpy(s, folder, MAX_PATH);
229 strncat(s, "/", MAX_PATH-strlen(s));
230 strncat(s, object, MAX_PATH-strlen(s));
231 path = (String) malloc(strlen(s)+1);
236 } /* end build_path */
240 /*--------------------------------------------------------------
244 * Given a path, generate a new file name and rename the file.
246 * The rc from the system call is returned and errno is set.
248 *--------------------------------------------------------------*/
251 auto_rename(const String path)
254 char newPath[MAX_PATH];
256 generate_NewPath(newPath,path);
258 return (rename(path,newPath));
260 } /* end auto_rename */
263 /*-----------------------------------------------------------------------
267 * Given a path (and a complete path is required), append a
268 * sequence number to generate a new file name. The new file
269 * will not exist. The sequence number consists of a one-character
270 * delimiter and an integer. The function will start with
271 * 1, if the file with 1 exists it will continue to 2, etc.
272 * newPath and oldPath can point to the same area. The sequence number
273 * is appended to the end of the name unless it contains a
274 * dot, in which case the sequence number precedes the dot. For example,
275 * /cde/dtfile/dtcopy/overwrtdialog.c becomes
276 * /cde/dtfile/dtcopy/overwrtdialog~1.c. However, if the dot
277 * is the first character in the file name, the sequence number is
278 * appended, (e.g. .profile --> .profile~1).
280 *-----------------------------------------------------------------------*/
283 generate_NewPath(String newPath, String oldPath)
287 const char delim = '_';
290 String lastDot, lastSlash;
291 char firstPart[MAX_PATH], lastPart[MAX_PATH];
296 lastDot = strrchr(oldPath,'.');
297 lastSlash = strrchr(oldPath,'/');
298 if (lastSlash == NULL)
299 lastSlash = oldPath - 1; /* allows for no path and first char is dot */
300 len = lastDot - oldPath;
301 if ( lastDot != NULL && /* no dot */
302 lastDot > lastSlash+1 && /* dot is in filename, not directory name */
303 len != strlen(oldPath)-1 ) /* dot is not last character of filename */
305 /* sequence number will be inserted before filename suffix */
306 memcpy(firstPart,oldPath,len);
307 firstPart[len] = '\0';
308 strcpy(lastPart,lastDot);
312 /* sequence number will be appended to filename */
313 strcpy(firstPart,oldPath);
321 sprintf(newPath,"%s%c%d%s",firstPart,delim,i,lastPart);
322 } while (lstat(newPath,&buf) == 0);
327 } /* end generate_NewPath */
330 /****************************************************************
331 * Create a default images for symbol... used in ClassInitialize.
339 unsigned int height )
343 image = XCreateImage(display,
344 DefaultVisual(display, DefaultScreen(display)),
345 1, XYBitmap, 0, bits, width, height, 8,
347 image->byte_order = LSBFirst;
348 image->bitmap_unit = 8;
349 image->bitmap_bit_order = LSBFirst;
352 } /* end CreateDefaultImage */
357 ImageInitialize( Display *display )
361 /* create and install the default images for the symbol */
363 image = CreateDefaultImage (display, (char *)errorBits, 20, 20);
364 XmInstallImage (image, "default_xm_error");
366 image = CreateDefaultImage (display, (char *)infoBits, 11, 24);
367 XmInstallImage (image, "default_xm_information");
369 image = CreateDefaultImage (display, (char *)questionBits, 22, 22);
370 XmInstallImage (image, "default_xm_question");
372 image = CreateDefaultImage (display, (char *)warningBits, 9, 22);
373 XmInstallImage (image, "default_xm_warning");
375 image = CreateDefaultImage (display, (char *)workingBits, 21, 23);
376 XmInstallImage (image, "default_xm_working");
379 } /* end ImageInitialize */
381 #if !defined(CSRG_BASED)
387 if(ustat(dev,&u1) < 0)
394 CopyCheckDeletePermissionRecur(
395 char *destinationPath)
403 DPRINTF(("CheckDeletePermissionRecur(\"%s\")\n", destinationPath));
405 if (lstat(destinationPath, &statbuf) < 0)
406 return -1; /* probably does not exist */
408 if (! S_ISDIR(statbuf.st_mode))
410 if(access(destinationPath,04) < 0)
412 return 0; /* no need to check anything more */
415 dirp = opendir (destinationPath);
417 return -1; /* could not read directory */
422 while (dp = readdir (dirp))
424 if (strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0)
428 /* check for write permission in this directory */
429 if (access(destinationPath, 04|02|01) < 0)
435 /* append a '/' to the end of directory name */
436 fnamep = destinationPath + strlen(destinationPath);
442 /* append file name to end of directory name */
443 strcpy(fnamep, dp->d_name);
445 /* recursively check permission on this file */
446 if (CopyCheckDeletePermissionRecur(destinationPath))
459 CopyCheckDeletePermission(
461 char *destinationPath)
463 #if defined(__FreeBSD__) || defined(__OpenBSD__)
464 struct statfs statbuf;
465 #elif defined(__NetBSD__)
466 struct statvfs statbuf;
470 char fname[PATH_MAX];
472 #if defined(__FreeBSD__) || defined(__OpenBSD__)
473 if (statfs(parentdir,&statbuf) < 0) /* does not exist */
474 #elif defined(__NetBSD__)
475 if (statvfs(parentdir,&statbuf) < 0) /* does not exist */
477 if (lstat(parentdir,&statbuf) < 0) /* does not exist */
481 /* check if we are root */
484 /* if NFS, need to check if server trusts root */
485 #if defined(CSRG_BASED)
486 if (!strcmp(statbuf.f_fstypename, "nfs")) /* Root user and nfs */
488 if (CopyFileSysType(statbuf.st_dev) < 0) /* Root user and nfs */
493 tmpfile = tempnam(parentdir,"dtfile");
496 /* Create a temporary file */
497 if ( (rv = creat(tmpfile,O_RDONLY)) < 0)
503 /* Delete the created file */
504 if (remove(tmpfile) < 0)
516 /* root user can delete anything */
520 /* check for read/write and execute permission on parent dir */
521 if (access(parentdir, R_OK | W_OK | X_OK) < 0)
524 /* copy destinationPath to tmp buffer */
525 strcpy(fname, destinationPath);
527 return CopyCheckDeletePermissionRecur(fname);
536 XtDestroyWidget((Widget)G_toplevel);
542 XtAppContext app_context,
548 if(checkPerms && move)
550 char title[200],*msg,*tmpmsg;
551 char *tmpstring = strdup(source_name),*tmpptr;
556 tmpptr = strrchr(tmpstring,'/');
557 if(!tmpstring || !tmpptr) /* Error */
561 if(tmpptr == tmpstring)
568 perm_status = CopyCheckDeletePermission(tmpptr,source_name);
572 if(!perm_status) /* Everything is fine just return */
579 strcpy(title,GETMESSAGE(4,7,"Object Trash - Error"));
580 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.");
582 msg = XtMalloc(strlen(tmpmsg)+strlen(source_name)+2);
583 sprintf(msg,tmpmsg,source_name);
584 _DtMessageDialog (G_toplevel, title, msg, 0, FALSE, NULL,
585 CloseTopLevel, NULL, NULL, False, ERROR_DIALOG);
587 XtAppAddTimeOut(app_context, delay, TimeoutHandler, NULL);
590 /* wait for user to close the dialog before exiting */
592 while (!G_dialog_closed)
594 XtAppNextEvent(app_context, &event);
595 XtDispatchEvent(&event);
601 TimeoutHandler(XtPointer client_data, XtIntervalId *id)
607 * This is a generic function for resolving a cannonical path from user input.
611 _DtCopyPathFromInput(char *input_string, char *current_dir)
614 char *tmp_path = NULL;
616 char *_DtCopyChangeTildeToHome();
618 /* find relative path */
620 tmp_path = path = XtNewString(input_string);
623 /* Strip any spaces from name -- input is overwritten */
624 path = (char *) _DtStripSpaces(path);
626 /* Resolve, if there're any, environement variables */
629 char command[MAX_PATH];
631 sprintf(command,"echo %s",path);
632 if((pfp=popen(command,"r")) == NULL)
638 if (fscanf(pfp,"%s",command) >= 1)
641 path = XtNewString(command);
653 /* Resolve '~' -- new memory is allocated, old memory is freed */
655 path = _DtCopyChangeTildeToHome(path);
657 /* If current dir provided, check for relative path */
658 if (path && current_dir)
662 /* file is relative path i.e. xyz/abc */
663 if (strcmp(current_dir, "/") == 0)
665 tmp_path = (char *)XtMalloc(strlen(current_dir) + strlen(path) + 1);
666 sprintf(tmp_path, "%s%s", current_dir, path);
670 tmp_path = (char *)XtMalloc(strlen(current_dir) + strlen(path) + 2);
671 sprintf(tmp_path, "%s/%s", current_dir, path);
685 /* Resolve '.' or '..' -- input is overwritten, output may be NULL! */
686 /* Save pointer to path to free if output is NULL. */
688 path = (char *) XeEliminateDots(path);
690 /* Strip off trailing '/' */
691 dir_len = strlen(path);
692 if (dir_len > 1 && *(path + dir_len - 1) == '/')
693 *(path + dir_len - 1) = '\0';
698 _DtCopyChangeTildeToHome (input_string)
701 _DtCopyChangeTildeToHome (
707 struct passwd * pwInfo;
708 char * homedir = (char *) XtNewString(getenv("HOME"));
710 if ((input_string[1] != '/'))
714 /* ~user or ~user/path format */
716 /* is there a path? */
717 path = (char *) DtStrchr(input_string, '/');
722 if ((pwInfo = getpwnam(input_string + 1)) == NULL)
724 /* user doesn't exist */
732 /* ~user/path format */
736 if (strcmp(pwInfo->pw_dir, "/") == 0)
738 /* We don't want to end up with double '/' in the path */
739 full_path = (char *) XtMalloc(strlen(path) + 1);
740 strcpy(full_path, path);
744 full_path = (char *) XtMalloc(strlen(pwInfo->pw_dir) +
746 sprintf(full_path, "%s%s", pwInfo->pw_dir, path);
753 full_path = XtMalloc(strlen(pwInfo->pw_dir) + 1);
754 strcpy(full_path, pwInfo->pw_dir);
757 else if (input_string[1])
761 /* NOTE: users_home_dir has trailing '/' */
762 full_path = (char *) XtMalloc(strlen(homedir) + strlen(input_string+2) + 1);
763 sprintf(full_path, "%s%s", homedir, (input_string + 2));
770 full_path = XtMalloc(strlen(homedir) + 1);
771 strcpy(full_path, homedir);
775 XtFree(input_string);
780 Check(char *spth, char *dpth, int mode)
782 struct stat sbuf, dbuf;
783 char filename [MAX_PATH];
789 if (lstat (spth, &sbuf) < 0)
791 tmpStr = (GETMESSAGE(4,9, "Cannot open %s"));
792 msg = XtMalloc(strlen(tmpStr)+strlen(filename)+1);
793 sprintf(msg,tmpStr,filename);
794 _DtMessageDialog (G_toplevel, title, msg, 0, FALSE, NULL,
795 CloseTopLevel, NULL, NULL, False, ERROR_DIALOG);
799 (void) strcpy (filename, dpth);
801 strcpy(title,GETMESSAGE(4,5,"Object Move - Error"));
803 strcpy(title,GETMESSAGE(4,6,"Object Copy - Error"));
806 while (dbuf.st_ino != ROOTINO)
808 /* Destination may not be available, in which case we need to
809 create it, so just return as successful and the remaining
810 code takes care of everything */
812 if (lstat (filename, &dbuf) < 0)
815 if (dbuf.st_ino == sbuf.st_ino)
818 tmpStr = GETMESSAGE(3,19,"Cannot move folder into itself. %s");
820 tmpStr = GETMESSAGE(3,20,"Cannot copy folder into itself. %s");
821 msg = XtMalloc(strlen(tmpStr)+strlen(dpth)+1);
822 sprintf(msg,tmpStr,dpth);
823 _DtMessageDialog (G_toplevel, title, msg, 0, FALSE, NULL,
824 CloseTopLevel, NULL, NULL, False, ERROR_DIALOG);
830 (void) strcat (filename, "/..");