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 //%% (c) Copyright 1993, 1994 Hewlett-Packard Company
24 //%% (c) Copyright 1993, 1994 International Business Machines Corp.
25 //%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
26 //%% (c) Copyright 1993, 1994 Novell, Inc.
27 //%% $XConsortium: tttar_file_utils.C /main/3 1995/10/20 17:00:26 rswiston $
29 * tttar_file_utils.cc - File utilities for the ToolTalk archive tool.
31 * Copyright (c) 1990 by Sun Microsystems, Inc.
38 #include <sys/param.h>
39 #include <sys/types.h>
42 #include <sys/inode.h>
43 #define S_ISLNK(m) (((m)&IFMT) == IFLNK)
46 #include "tttar_utils.h"
47 #include "tttar_file_utils.h"
49 extern char *_tt_get_realpath(char *, char *);
52 * is_child_in() - Is <path> a node in any of the path trees listed?
54 * Returns true if, for any string <pathtree> in <paths>,
55 * a) "<path>" == "<pathtree>", or
56 * b) "<pathtree>/" is a prefix of "<path>".
60 is_child_in( _Tt_string path, _Tt_string_list_ptr paths )
62 _Tt_string_list_cursor path_cursor( paths );
63 while (path_cursor.next()) {
64 if (is_child_of( path, (*path_cursor))) {
72 * is_child_of() - Is <path> in the path tree given?
75 * a) "<path>" == "<pathtree>", or
76 * b) "<pathtree>/" is a prefix of "<path>".
80 is_child_of( _Tt_string path, _Tt_string pathtree )
82 if (pathtree == path) {
85 _Tt_string prefix = pathtree.cat( "/" );
86 if ( prefix == path.left( prefix.len())) {
93 * new_name() - Return the most specific renaming, or an empty string.
96 new_name( _Tt_string old_name, Lstar_string_map_list_ptr renamings )
99 Lstar_string_map_ptr best_renaming(new Lstar_string_map);
100 Lstar_string_map_list_cursor renaming_cursor( renamings );
102 while (renaming_cursor.next()) {
103 _Tt_string rename_pattern = (*renaming_cursor)->old_string();
104 if (is_child_of( old_name, rename_pattern )) {
105 if ( rename_pattern.len()
106 > best_renaming->old_string().len())
108 best_renaming = *renaming_cursor;
113 * If a renaming was found...
115 if ( best_renaming->old_string().len() > 0) {
117 * ... the new name will have as its prefix the
118 * replacement part of the mapping.
120 _new_name = best_renaming->new_string();
122 * If it was not a perfect match...
124 if (old_name != best_renaming->old_string()) {
126 * ... we need to tack on whatever is
127 * unique about old_string.
133 - best_renaming->old_string().len()));
140 * dir_entries() - Return a new list of paths, with one entry for each
141 * entry in the directory <path>, each entry consisting of
142 * <path> appended by a slash and the name of the entry.
143 * Returns an empty list if <path> is not a directory.
144 * If !follow_symlinks, returns an empty list if <path> is a symlink.
147 dir_entries( _Tt_string path, bool_t follow_symlinks )
150 _Tt_string_list_ptr entries(new _Tt_string_list);
152 if (! follow_symlinks) {
153 struct stat lstat_buf;
156 lstat_status = lstat( (char *)path, &lstat_buf );
157 if (( lstat_status == 0) && S_ISLNK(lstat_buf.st_mode)) {
161 dirp = opendir( (char *)path );
166 struct dirent *entry;
168 _Tt_string epath_slash;
171 entry = readdir( dirp );
175 ename = entry->d_name;
176 if ((ename == ".") || (ename == "..")) {
179 epath_slash = path.cat( "/" );
180 epath = epath_slash.cat( entry->d_name );
181 entries->push( epath );
183 if (closedir( dirp ) != 0) {
184 fprintf( stderr, "%s: closedir(\"%s\"): %s\n",
185 our_process_name, (char *)path, strerror(errno) );
189 } /* dir_entries() */
192 * realtrees() - Return a new absolutized list of the paths given.
193 * If follow_symlinks, then recurse on any directories listed and
194 * put the realpath of the other end of the symlink onto the list.
197 realtrees( _Tt_string_list_ptr paths, bool_t follow_symlinks )
199 _Tt_string_list_ptr realpaths(new _Tt_string_list);
200 _Tt_string_list_cursor path_cursor( paths );
202 while (path_cursor.next()) {
203 char resolved_path_buf[ MAXPATHLEN+1 ];
207 struct stat lstat_buf;
210 path = (*path_cursor);
211 lstat_status = lstat( (char *)path, &lstat_buf );
212 if ( lstat_status != 0) {
214 * ToolTalk objects can be associated
215 * with paths that don't exist.
217 if (errno != ENOENT) {
219 "%s: lstat(\"%s\"): %s\n",
221 (char *)path, strerror(errno) );
225 _tt_get_realpath( (char *)path,
228 } else if (S_ISLNK(lstat_buf.st_mode)) {
229 if (follow_symlinks) {
230 resolved_path = _tt_get_realpath( (char *)path,
234 * Use the absolute path of the
235 * symlink instead of the path of the
238 char *dir = dirname( (char *)path );
239 char *base = basename( (char *)path );
240 resolved_path = _tt_get_realpath( dir,
242 if (resolved_path != NULL) {
243 strcat( resolved_path_buf, "/" );
244 int len = strlen( resolved_path_buf );
245 strncat( resolved_path_buf,
246 base, MAXPATHLEN - len );
251 resolved_path = _tt_get_realpath( (char *)path,
254 if (resolved_path != NULL) {
255 abs_path = resolved_path;
257 if (errno == ENOENT) {
259 * XXX: We need to figure out here what the
260 * realpath would be if the file existed.
263 fprintf( stderr, "%s: %s: %s\n",
265 (char *)path, strerror(errno) );
268 realpaths->push( abs_path );
269 if (follow_symlinks) {
270 append_real_subtrees( realpaths, abs_path );
278 * append_real_subtrees() - If <path> is a directory, add to <realtrees>
279 * any directories it contains links to, and recurse on both
280 * these and any other real directories in <path>.
283 append_real_subtrees( _Tt_string_list_ptr realtrees, _Tt_string path )
285 struct stat stat_buf;
288 if (stat( (char *)path, &stat_buf ) != 0) {
289 fprintf( stderr, "%s: stat(\"%s\"): %s\n",
290 our_process_name, (char *)path, strerror(errno) );
293 if (! S_ISDIR(stat_buf.st_mode)) {
296 dirp = opendir( (char *)path );
298 fprintf( stderr, "%s: realpath(\"%s\"): %s\n",
299 our_process_name, (char *)path, strerror(errno) );
304 struct dirent *entry;
305 struct stat lstat_buf;
307 _Tt_string epath_slash;
310 entry = readdir( dirp );
314 ename = entry->d_name;
315 if ((ename == ".") || (ename == "..")) {
318 epath_slash = path.cat( "/" );
319 epath = epath_slash.cat( entry->d_name );
320 if (lstat( (char *)epath, &lstat_buf ) != 0) {
321 fprintf( stderr, "%s: lstat(\"%s\"): %s\n",
322 our_process_name, (char *)epath,
327 if (stat( (char *)epath, &stat_buf ) != 0) {
328 fprintf( stderr, "%s: stat(\"%s\"): %s\n",
329 our_process_name, (char *)epath,
334 if (S_ISDIR(stat_buf.st_mode)) {
335 if (S_ISLNK(lstat_buf.st_mode)) {
336 char rpath_buf[ MAXPATHLEN+1 ];
339 rpath = _tt_get_realpath( (char *)epath, rpath_buf );
342 "%s: realpath(\"%s\"): %s\n",
343 our_process_name,(char *)epath,
346 _Tt_string rp( rpath );
347 realtrees->push( rp );
350 append_real_subtrees( realtrees, epath );
353 if (closedir( dirp ) != 0) {
354 fprintf( stderr, "%s: closedir(\"%s\"): %s\n",
355 our_process_name, (char *)path, strerror(errno) );
358 } /* append_real_subtrees() */
361 * basename() - Return the last component of a pathname.
364 char *basename( char *pathname ) {
367 the_basename = strrchr( pathname, '/' );
368 if (the_basename == NULL) {
369 the_basename = pathname;
371 the_basename++; // Don't want the '/'
378 * dirname() - Return the pathname minus the basename, or "." if the
379 * basename is all there is. Caller is responsible for free()ing
380 * the storage returned.
382 char *dirname( char *pathname ) {
386 the_basename = strrchr( pathname, '/' );
387 if (the_basename == NULL) {
388 the_dirname = (char *)malloc((size_t)(2 * sizeof(char)));
389 the_dirname[0] = '.';
390 the_dirname[1] = '\0';
392 int len = the_basename - pathname;
393 the_dirname = (char *)
394 malloc((size_t)( sizeof(char) * (len + 1)));
395 strncpy( the_dirname, pathname, len );
396 the_dirname[ len ] = '\0';