1 /*
2 * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
3 * University Research and Technology
4 * Corporation. All rights reserved.
5 * Copyright (c) 2004-2005 The University of Tennessee and The University
6 * of Tennessee Research Foundation. All rights
7 * reserved.
8 * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
9 * University of Stuttgart. All rights reserved.
10 * Copyright (c) 2004-2005 The Regents of the University of California.
11 * All rights reserved.
12 * Copyright (c) 2009-2014 Cisco Systems, Inc. All rights reserved.
13 * Copyright (c) 2014-2015 Research Organization for Information Science
14 * and Technology (RIST). All rights reserved.
15 * Copyright (c) 2014 Intel, Inc. All rights reserved.
16 * $COPYRIGHT$
17 *
18 * Additional copyrights may follow
19 *
20 * $HEADER$
21 */
22
23 #include "opal_config.h"
24
25 #include <stdlib.h>
26 #include <string.h>
27 #ifdef HAVE_LIBGEN_H
28 #include <libgen.h>
29 #endif /* HAVE_LIBGEN_H */
30
31 #include "opal/util/basename.h"
32 #include "opal/util/os_path.h"
33
34 /**
35 * Return a pointer into the original string where the last PATH delimiter
36 * was found. It does not modify the original string. Moreover, it does not
37 * scan the full string, but only the part allowed by the specified number
38 * of characters.
39 * If the last character on the string is a path separator, it will be skipped.
40 */
41 static inline char* opal_find_last_path_separator( const char* filename, size_t n )
42 {
43 char* p = (char*)filename + n;
44
45 /* First skip the latest separators */
46 for ( ; p >= filename; p-- ) {
47 if( *p != OPAL_PATH_SEP[0] )
48 break;
49 }
50
51 for ( ; p >= filename; p-- ) {
52 if( *p == OPAL_PATH_SEP[0] )
53 return p;
54 }
55
56 return NULL; /* nothing found inside the filename */
57 }
58
59 char *opal_basename(const char *filename)
60 {
61 size_t i;
62 char *tmp, *ret = NULL;
63 const char sep = OPAL_PATH_SEP[0];
64
65 /* Check for the bozo case */
66 if (NULL == filename) {
67 return NULL;
68 }
69 if (0 == strlen(filename)) {
70 return strdup("");
71 }
72 if (sep == filename[0] && '\0' == filename[1]) {
73 return strdup(filename);
74 }
75
76 /* Remove trailing sep's (note that we already know that strlen > 0) */
77 tmp = strdup(filename);
78 for (i = strlen(tmp) - 1; i > 0; --i) {
79 if (sep == tmp[i]) {
80 tmp[i] = '\0';
81 } else {
82 break;
83 }
84 }
85 if (0 == i) {
86 tmp[0] = sep;
87 return tmp;
88 }
89
90 /* Look for the final sep */
91 ret = opal_find_last_path_separator( tmp, strlen(tmp) );
92 if (NULL == ret) {
93 return tmp;
94 }
95 ret = strdup(ret + 1);
96 free(tmp);
97 return ret;
98 }
99
100 char* opal_dirname(const char* filename)
101 {
102 #if defined(HAVE_DIRNAME) || OPAL_HAVE_DIRNAME
103 char* safe_tmp = strdup(filename), *result;
104 if (NULL == safe_tmp) {
105 return NULL;
106 }
107 result = strdup(dirname(safe_tmp));
108 free(safe_tmp);
109 return result;
110 #else
111 const char* p = opal_find_last_path_separator(filename, strlen(filename));
112 /* NOTE: p will be NULL if no path separator was in the filename - i.e.,
113 * if filename is just a local file */
114
115 for( ; NULL != p && p != filename; p-- ) {
116 if( (*p == '\\') || (*p == '/') ) {
117 /* If there are several delimiters remove them all */
118 for( --p; p != filename; p-- ) {
119 if( (*p != '\\') && (*p != '/') ) {
120 p++;
121 break;
122 }
123 }
124 if( p != filename ) {
125 char* ret = (char*)malloc( p - filename + 1 );
126 if (NULL == ret) {
127 return NULL;
128 }
129 opal_string_copy(ret, filename, p - filename);
130 ret[p - filename] = '\0';
131 return opal_make_filename_os_friendly(ret);
132 }
133 break; /* return the duplicate of "." */
134 }
135 }
136 return strdup(".");
137 #endif /* defined(HAVE_DIRNAME) || OPAL_HAVE_DIRNAME */
138 }