/* Library for handling pathnames * * pathnames.c * * (C) 2006 Sunrise Telephone Systems Ltd. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * In countries and territories where the above no-warranty disclaimer is * not permissible by applicable law, the following terms apply: * * NO PERMISSION TO USE THE SOFTWARE IS GRANTED AND THE SOFTWARE MUST NOT BE * USED AT ALL IN SUCH COUNTRIES AND TERRITORIES WHERE THE ABOVE NO-WARRANTY * DISCLAIMER IS NOT PERMISSIBLE AND INVALIDATED BY APPLICABLE LAW. HOWEVER, * THE COPYRIGHT HOLDERS HEREBY WAIVE THEIR RIGHT TO PURSUE OFFENDERS AS LONG * AS THEY OTHERWISE ABIDE BY THE TERMS OF THE LICENSE AS APPLICABLE FOR USE * OF THE SOFTWARE IN COUNTRIES AND TERRITORIES WHERE THE ABOVE NO-WARRANTY * DISCLAIMER IS PERMITTED BY APPLICABLE LAW. THIS WAIVER DOES NOT CONSTITUTE * A LICENSE TO USE THE SOFTWARE IN COUNTRIES AND TERRITORIES WHERE THE ABOVE * NO-WARRANTY DISCLAIMER IS NOT PERMISSIBLE AND INVALIDATED BY APPLICABLE * LAW. ANY LIABILITY OF ANY KIND IS CATEGORICALLY RULED OUT AT ALL TIMES. */ #include #include #include #include #include #include #include "pathnames.h" // -------------------------------------------------------------------------- // If god used C the universe would consist of nothing but infinite ugliness // -------------------------------------------------------------------------- // #define CSTRING(single_char) \ ((const char[2]) { single_char, CSTRING_TERMINATOR }) // -------------------------------------------------------------------------- // readability macros // -------------------------------------------------------------------------- // #define stringContainsChar(str,ch) (strchr((str), (ch)) != NULL) #define stringDoesNotContainChar(str,ch) (strchr((str), (ch)) == NULL) // --------------------------------------------------------------------------- // CARDINAL type definition // --------------------------------------------------------------------------- // // Default index type typedef unsigned int CARDINAL; // -------------------------------------------------------------------------- // function fileExistAtPath(path) // -------------------------------------------------------------------------- // // check if file at path exists // int fileExistsAtPath(const char *pathname) { struct stat status; return (stat(pathname, &status) == 0); } // end fileExistsAtPath // -------------------------------------------------------------------------- // function copyStrFromWorkingDirectory(str) // -------------------------------------------------------------------------- // // get string with current working directory // int copyStrFromWorkingDirectory(char *str) { char _workdir[MAX_PATHNAME_LENGTH] = ""; // private char *workdir = (char *)&_workdir; // silly compiler *str = CSTRING_TERMINATOR; if (getcwd(workdir, MAX_PATHNAME_LENGTH) != NULL) { strncpy(str, workdir, strlen(workdir)); } else { // error trying to obtain working directory // errno contains error code int error = errno; if (error == EINVAL) { return 3; } else if (error == ERANGE) { return 2; } else if (error == EACCES) { return 1; } else { // just in case return -1; } // enf if } // end if return 0; } // end copyStrFromWorkingDirectory // -------------------------------------------------------------------------- // function copyStrFromUserHomeDirectory(str) // -------------------------------------------------------------------------- // // get string with current user's home directory // int copyStrFromUserHomeDirectory(char *str) { uid_t userid; struct passwd *uinfo; *str = CSTRING_TERMINATOR; // obtain user id userid = getuid(); // obtain user pwd entry uinfo = getpwuid(userid); if (uinfo != NULL) { // pass user's home directory in str strncpy(str, uinfo->pw_dir, strlen(uinfo->pw_dir)); } // end if return 0; } // end copyStrFromUserHomeDirectory // -------------------------------------------------------------------------- // function copyStrFilenameByRemovingDirectory(str, path) // -------------------------------------------------------------------------- // // get string with filename and extension by removing directory from path // int copyStrFilenameByRemovingDirectory(char *str, const char *pathname) { CARDINAL len; char *filename = NULL; *str = CSTRING_TERMINATOR; // find last occurence of a slash in pathname filename = strrchr(pathname, FILESYSTEM_DIRECTORY_SEPARATOR); if (filename != NULL) { len = strlen(filename); if (len > 1) { strncpy(str, filename + 1, len); } // end if } // end if return 0; } // end copyStrFilenameByRemovingDirectory // -------------------------------------------------------------------------- // function copyStrFilenameByRemovingDirectoryAndFileExtension(str, path) // -------------------------------------------------------------------------- // // get string with base filename by removing directory and file extension // from path // int copyStrFilenameByRemovingDirectoryAndFileExtension(char *str, const char *pathname) { char ch; int index; char _filename[MAX_PATHNAME_LENGTH] = ""; // private char *filename = (char *)&_filename; // silly compiler *str = CSTRING_TERMINATOR; // remove directory from pathname and copy to filename copyStrFilenameByRemovingDirectory(filename, pathname); // find last occurence of a dot in filename if (filename != NULL) { // search for a dot // starting at the end index = strlen(filename) - 1; ch = filename[index]; // but ignore any leading dot while ((ch != FILESYSTEM_WORKDIR_WILDCARD) && (index > 0)) { index--; if (index > 0) { ch = filename[index]; } // end if } // end while // if we found a dot if (index > 0) { // cut the filename where the dot is and copy to str filename[index] = CSTRING_TERMINATOR; strncpy(str, filename, index + 1); } // otherwise, nothing to cut else { // copy filename as is to str strncpy(str, filename, strlen(filename)); } // end if } // end if return 0; } // end copyStrFilenameByRemovingDirectoryAndFileExtension // -------------------------------------------------------------------------- // function copyStrFileExtensionByRemovingDirectoryAndFilename(str, path) // -------------------------------------------------------------------------- // // get string with file extension by removing directory and filename from // path // int copyStrFileExtensionByRemovingDirectoryAndFilename(char *str, const char *pathname) { CARDINAL len; char _filename[MAX_PATHNAME_LENGTH] = ""; // private char *filename = (char *)&_filename; // silly compiler char *extension = NULL; *str = CSTRING_TERMINATOR; // remove directory from pathname and copy to filename copyStrFilenameByRemovingDirectory(filename, pathname); // find last occurence of a dot in filename extension = strrchr(filename, FILESYSTEM_EXTENSION_SEPARATOR); if (extension != NULL) { len = strlen(extension); if (len > 1) { strncpy(str, extension + 1, len); } // end if } // end if return 0; } // end copyStrFileExtensionByRemovingDirectoryAndFilename // -------------------------------------------------------------------------- // function modifyFilenameByAppendingFileExtension(filename, extension) // -------------------------------------------------------------------------- // // append file extension to filename // int modifyFilenameByAppendingFileExtension(char *filename, const char *extension) { CARDINAL lastchar; // if filename is empty, exit if (strlen(filename) == 0) { return 1; } // end if lastchar = strlen(filename) - 1; // if filename ends with a slash, exit if (filename[lastchar] == FILESYSTEM_DIRECTORY_SEPARATOR) { return 1; } // end if // if filename doesn't end with a dot and extension doesn't start with a dot ... if ((filename[lastchar] != FILESYSTEM_EXTENSION_SEPARATOR) && (extension[0] != FILESYSTEM_EXTENSION_SEPARATOR)) { // add a dot to the end of filename strncat(filename, CSTRING(FILESYSTEM_EXTENSION_SEPARATOR), 1); } // end if // add the extension strncat(filename, extension, strlen(extension)); return 0; } // end modifyFilenameByAppendingFileExtension // -------------------------------------------------------------------------- // function modifyFilenameByReplacingFileExtension(filename, extension) // -------------------------------------------------------------------------- // // replace file extension in filename // int modifyFilenameByReplacingFileExtension(char *filename, const char *extension) { char ch; int index; // if filename is empty, exit if (strlen(filename) == 0) { return 1; } // end if // if filename ends with a slash, exit if (filename[strlen(filename) - 1] == FILESYSTEM_DIRECTORY_SEPARATOR) { return 1; } // end if // find last occurence of a dot in filename if (filename != NULL) { // search for a dot // starting at the end index = (int) strlen(filename) - 1; ch = filename[index]; // but ignore any leading dot while ((ch != FILESYSTEM_WORKDIR_WILDCARD) && (index > 0)) { index--; if (index > 0) { ch = filename[index]; } // end if } // end while // if we found a dot if (index > 0) { // if extension starts with a dot ... if (extension[0] == FILESYSTEM_EXTENSION_SEPARATOR) { // ... cut filename at the dot filename[index] = CSTRING_TERMINATOR; } // otherwise, if extension has no dot else { // cut the filename after the dot filename[index + 1] = CSTRING_TERMINATOR; } // end if } // otherwise, there is no dot in filename else { // if extension does not start with a dot ... if (extension[0] != FILESYSTEM_EXTENSION_SEPARATOR) { // ... add a dot at the end of filename strncat(filename, CSTRING(FILESYSTEM_EXTENSION_SEPARATOR), 1); } // end if } // end if // add the extension to filename strncat(filename, extension, strlen(extension)); } // end if return 0; } // end modifyFilenameByReplacingFileExtension // -------------------------------------------------------------------------- // function copyStrDirectoryByRemovingFilenameAndExtension(str, path) // -------------------------------------------------------------------------- // // get string with directory by removing filename and extension from path // int copyStrDirectoryByRemovingFilenameAndExtension(char *str, const char *pathname) { char ch; int index; // if pathname is empty, exit if (strlen(pathname) == 0) { return 1; } // end if *str = CSTRING_TERMINATOR; // find last occurence of a slash in pathname if (pathname != NULL) { // search for a slash // starting at the end index = (int) strlen(pathname) - 1; ch = pathname[index]; while ((ch != FILESYSTEM_DIRECTORY_SEPARATOR) && (index >= 0)) { index--; if (index >= 0) { ch = pathname[index]; } // end if } // end while // if we found a slash if (index > 0) { // copy pathname up to before the slash strncpy(str, pathname, index); } // otherwise, there is no slash else { // copy all of pathname to str strncpy(str, pathname, strlen(pathname)); } // end if } // end if return 0; } // end copyStrDirectoryByRemovingFilenameAndExtension // -------------------------------------------------------------------------- // function modifyPathnameByAppendingFilename(pathname, filename) // -------------------------------------------------------------------------- // // append filename to pathname // int modifyPathnameByAppendingFilename(char *pathname, const char *filename) { int lastchar = strlen(pathname) - 1; // if filename ends with a dot, exit if (pathname[lastchar] == FILESYSTEM_EXTENSION_SEPARATOR) { return 1; } // end if // if pathname doesn't end with a slash and filename doesn't start with a slash ... if ((pathname[lastchar] != FILESYSTEM_DIRECTORY_SEPARATOR) && (filename[0] != FILESYSTEM_DIRECTORY_SEPARATOR)) { // ... add a slash to the end of pathname strncat(pathname, CSTRING(FILESYSTEM_DIRECTORY_SEPARATOR), 1); } // end if // add the extension strncat(pathname, filename, strlen(filename)); return 0; } // end modifyFilenameByAppendingFileExtension // -------------------------------------------------------------------------- // function copyStrPathnameByExpandingTildeInPath(str, path) // -------------------------------------------------------------------------- // // get string with full pathname by expanding tilde in path // int copyStrPathnameByExpandingTildeInPath(char *str, const char *pathname) { char _homedir[MAX_PATHNAME_LENGTH] = ""; // private char *homedir = (char *)&_homedir; // silly compiler *str = CSTRING_TERMINATOR; if (pathname != NULL) { // check for leading tilde-slash and expand if found if ((pathname[0] == FILESYSTEM_HOMEDIR_WILDCARD) && (pathname[1] == FILESYSTEM_DIRECTORY_SEPARATOR)) { if (copyStrFromUserHomeDirectory(homedir) == 0) { strncpy(str, homedir, strlen(homedir)); strncat(str, pathname, strlen(pathname)); } // otherwise, return error code else { // error trying to obtain working directory // errno contains error code int error = errno; if (error == EINVAL) { return 3; } else if (error == ERANGE) { return 2; } else if (error == EACCES) { return 1; } else { // just in case return -1; } // end if } // end if } // otherwise, there is nothing to expand else { // copy pathname as is strncpy(str, pathname, strlen(pathname)); } // enf if } // end if return 0; } // end copyStrPathnameByExpandingTildeInPath // -------------------------------------------------------------------------- // function copyStrPathnameByExpandingLeadingDotInPath(str, path) // -------------------------------------------------------------------------- // // get string with full pathname by expanding leading dot in path // int copyStrPathnameByExpandingLeadingDotInPath(char *str, const char *pathname) { char _workdir[MAX_PATHNAME_LENGTH] = ""; // private char *workdir = (char *)&_workdir; // silly compiler *str = CSTRING_TERMINATOR; if (pathname != NULL) { // check for leading dot-slash and expand if found if ((pathname[0] == FILESYSTEM_WORKDIR_WILDCARD) && (pathname[1] == FILESYSTEM_DIRECTORY_SEPARATOR)) { if (getcwd(workdir, MAX_PATHNAME_LENGTH) != 0) { strncpy(str, workdir, strlen(workdir)); strncat(str, pathname + 1, strlen(pathname)); } // otherwise, return error code else { // error trying to obtain working directory // errno contains error code int error = errno; if (error == EINVAL) { return 3; } else if (error == ERANGE) { return 2; } else if (error == EACCES) { return 1; } else { // just in case return -1; } // end if } // end if } // otherwise, there is nothing to expand else { strncpy(str, pathname, strlen(pathname)); } // end if } // end if return 0; } // end copyStrPathnameByExpandingLeadingDotInPath // -------------------------------------------------------------------------- // function copyStrPathnameByExpandingLeadingDotDotInPath(str, path) // -------------------------------------------------------------------------- // // get string with full pathname by expanding leading dotdot in path // int copyStrPathnameByExpandingLeadingDotDotInPath(char *str, const char *pathname) { // TO DO return 0; } // end copyStrPathnameByExpandingLeadingDotDotInPath // -------------------------------------------------------------------------- // function copyStrPathnameByExpandingTrailingDotInPath(str, path) // -------------------------------------------------------------------------- // // get string with full pathname by expanding trailing dot in path with // filename // int copyStrPathnameByExpandingTrailingDotInPath(char *str, const char *pathname, const char *filename) { int len = strlen(pathname); if (pathname != NULL) { strncpy(str, pathname, len); if (str[len - 1] == FILESYSTEM_WORKDIR_WILDCARD) { str[len - 1] = CSTRING_TERMINATOR; strncat(str, filename, strlen(filename)); } // otherwise, nothing to expand else { // copy pathname as is strncpy(str, pathname, len); } // end if } // otherwise, nothing to append to else { // copy filename as is strncpy(str, filename, strlen(filename)); } // end if return 0; } // end copyStrPathnameByExpandingTrailingDotInPath // END OF FILE