/* * OpenVPN -- An application to securely tunnel IP networks * over a single UDP port, with support for SSL/TLS-based * session authentication and key exchange, * packet encryption, packet authentication, and * packet compression. * * Copyright (C) 2011 - David Sommerseth * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #elif defined(_MSC_VER) #include "config-msvc.h" #endif #ifndef HAVE_DIRNAME #include "compat.h" #include /* Unoptimised version of glibc memrchr(). * This is considered fast enough, as only this compat * version of dirname() depends on it. */ static const char * __memrchr(const char *str, int c, size_t n) { const char *end = str; end += n - 1; /* Go to the end of the string */ while (end >= str) { if (c == *end) { return end; } else { end--; } } return NULL; } /* Modified version based on glibc-2.14.1 by Ulrich Drepper * This version is extended to handle both / and \ in path names. */ char * dirname(char *path) { static const char dot[] = "."; char *last_slash; char separator = '/'; /* Find last '/'. */ last_slash = path != NULL ? strrchr(path, '/') : NULL; /* If NULL, check for \ instead ... might be Windows a path */ if (!last_slash) { last_slash = path != NULL ? strrchr(path, '\\') : NULL; separator = last_slash ? '\\' : '/'; /* Change the separator if \ was found */ } if (last_slash != NULL && last_slash != path && last_slash[1] == '\0') { /* Determine whether all remaining characters are slashes. */ char *runp; for (runp = last_slash; runp != path; --runp) { if (runp[-1] != separator) { break; } } /* The '/' is the last character, we have to look further. */ if (runp != path) { last_slash = (char *) __memrchr(path, separator, runp - path); } } if (last_slash != NULL) { /* Determine whether all remaining characters are slashes. */ char *runp; for (runp = last_slash; runp != path; --runp) { if (runp[-1] != separator) { break; } } /* Terminate the path. */ if (runp == path) { /* The last slash is the first character in the string. We have to * return "/". As a special case we have to return "//" if there * are exactly two slashes at the beginning of the string. See * XBD 4.10 Path Name Resolution for more information. */ if (last_slash == path + 1) { ++last_slash; } else { last_slash = path + 1; } } else { last_slash = runp; } last_slash[0] = '\0'; } else { /* This assignment is ill-designed but the XPG specs require to * return a string containing "." in any case no directory part is * found and so a static and constant string is required. */ path = (char *) dot; } return path; } #endif /* HAVE_DIRNAME */