/* * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana * University Research and Technology * Corporation. All rights reserved. * Copyright (c) 2004-2005 The University of Tennessee and The University * of Tennessee Research Foundation. All rights * reserved. * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, * University of Stuttgart. All rights reserved. * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. * Copyright (c) 2009-2014 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2014 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2014-2020 Intel, Inc. All rights reserved. * Copyright (c) 2021-2024 Nanook Consulting All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow * * $HEADER$ */ #include "src/include/pmix_config.h" #include #ifdef HAVE_STRING_H # include #endif /* HAVE_STRING_H */ #ifdef HAVE_LIBGEN_H # include #endif /* HAVE_LIBGEN_H */ #include "src/util/pmix_basename.h" #include "src/util/pmix_os_path.h" /** * Return a pointer into the original string where the last PATH delimiter * was found. It does not modify the original string. Moreover, it does not * scan the full string, but only the part allowed by the specified number * of characters. * If the last character on the string is a path separator, it will be skipped. */ static inline char *pmix_find_last_path_separator(const char *filename, size_t n) { char *p = (char *) filename + n; /* First skip the latest separators */ for (; p >= filename; p--) { if (*p != PMIX_PATH_SEP[0]) break; } for (; p >= filename; p--) { if (*p == PMIX_PATH_SEP[0]) return p; } return NULL; /* nothing found inside the filename */ } char *pmix_basename(const char *filename) { size_t i; char *tmp, *ret = NULL; const char sep = PMIX_PATH_SEP[0]; /* Check for the bozo case */ if (NULL == filename) { return NULL; } if (0 == strlen(filename)) { return strdup(""); } if (sep == filename[0] && '\0' == filename[1]) { return strdup(filename); } /* Remove trailing sep's (note that we already know that strlen > 0) */ tmp = strdup(filename); if (1 < strlen(tmp)) { for (i = strlen(tmp) - 1; i > 0; --i) { if (sep == tmp[i]) { tmp[i] = '\0'; } else { break; } } if (0 == i) { tmp[0] = sep; return tmp; } } /* Look for the final sep */ ret = pmix_find_last_path_separator(tmp, strlen(tmp)); if (NULL == ret) { return tmp; } ret = strdup(ret + 1); free(tmp); return ret; } char *pmix_dirname(const char *filename) { #if defined(HAVE_DIRNAME) || PMIX_HAVE_DIRNAME char *safe_tmp = strdup(filename), *result; result = strdup(dirname(safe_tmp)); free(safe_tmp); return result; #else const char *p = pmix_find_last_path_separator(filename, strlen(filename)); /* NOTE: p will be NULL if no path separator was in the filename - i.e., * if filename is just a local file */ for (; NULL != p && p != filename; p--) { if ((*p == '\\') || (*p == '/')) { /* If there are several delimiters remove them all */ for (--p; p != filename; p--) { if ((*p != '\\') && (*p != '/')) { p++; break; } } if (p != filename) { char *ret = (char *) malloc(p - filename + 1); pmix_strncpy(ret, filename, p - filename); ret[p - filename] = '\0'; return pmix_make_filename_os_friendly(ret); } break; /* return the duplicate of "." */ } } return strdup("."); #endif /* defined(HAVE_DIRNAME) || PMIX_HAVE_DIRNAME */ }