diff options
Diffstat (limited to 'android/utils/path.c')
-rw-r--r-- | android/utils/path.c | 430 |
1 files changed, 0 insertions, 430 deletions
diff --git a/android/utils/path.c b/android/utils/path.c deleted file mode 100644 index 9dd238e..0000000 --- a/android/utils/path.c +++ /dev/null @@ -1,430 +0,0 @@ -/* Copyright (C) 2007-2009 The Android Open Source Project -** -** This software is licensed under the terms of the GNU General Public -** License version 2, as published by the Free Software Foundation, and -** may be copied, distributed, and modified under those terms. -** -** 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. -*/ -#include "android/utils/path.h" - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <errno.h> -#include <fcntl.h> - -#ifdef _WIN32 -#include <process.h> -#include <shlobj.h> -#include <tlhelp32.h> -#include <io.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <stdint.h> -#include <limits.h> -#include <winbase.h> -#else -#include <unistd.h> -#include <sys/stat.h> -#include <time.h> -#include <signal.h> -#endif - -#define D(...) ((void)0) - -#ifndef CHECKED -# ifdef _WIN32 -# define CHECKED(ret, call) (ret) = (call) -# else -# define CHECKED(ret, call) do { (ret) = (call); } while ((ret) < 0 && errno == EINTR) -# endif -#endif - -/** PATH HANDLING ROUTINES - ** - ** path_parent() can be used to return the n-level parent of a given directory - ** this understands . and .. when encountered in the input path - **/ - -static __inline__ int -ispathsep(int c) -{ -#ifdef _WIN32 - return (c == '/' || c == '\\'); -#else - return (c == '/'); -#endif -} - -char* -path_parent( const char* path, int levels ) -{ - const char* end = path + strlen(path); - char* result; - - while (levels > 0) { - const char* base; - - /* trim any trailing path separator */ - while (end > path && ispathsep(end[-1])) - end--; - - base = end; - while (base > path && !ispathsep(base[-1])) - base--; - - if (base <= path) /* we can't go that far */ - return NULL; - - if (end == base+1 && base[0] == '.') - goto Next; - - if (end == base+2 && base[0] == '.' && base[1] == '.') { - levels += 1; - goto Next; - } - - levels -= 1; - - Next: - end = base - 1; - } - result = malloc( end-path+1 ); - if (result != NULL) { - memcpy( result, path, end-path ); - result[end-path] = 0; - } - return result; -} - - -/** MISC FILE AND DIRECTORY HANDLING - **/ - -ABool -path_exists( const char* path ) -{ - int ret; - CHECKED(ret, access(path, F_OK)); - return (ret == 0) || (errno != ENOENT); -} - -/* checks that a path points to a regular file */ -ABool -path_is_regular( const char* path ) -{ - int ret; - struct stat st; - - CHECKED(ret, stat(path, &st)); - if (ret < 0) - return 0; - - return S_ISREG(st.st_mode); -} - - -/* checks that a path points to a directory */ -ABool -path_is_dir( const char* path ) -{ - int ret; - struct stat st; - - CHECKED(ret, stat(path, &st)); - if (ret < 0) - return 0; - - return S_ISDIR(st.st_mode); -} - -/* checks that one can read/write a given (regular) file */ -ABool -path_can_read( const char* path ) -{ - int ret; - CHECKED(ret, access(path, R_OK)); - return (ret == 0); -} - -ABool -path_can_write( const char* path ) -{ - int ret; - CHECKED(ret, access(path, R_OK)); - return (ret == 0); -} - -/* try to make a directory. returns 0 on success, -1 on failure - * (error code in errno) */ -APosixStatus -path_mkdir( const char* path, int mode ) -{ -#ifdef _WIN32 - (void)mode; - return _mkdir(path); -#else - int ret; - CHECKED(ret, mkdir(path, mode)); - return ret; -#endif -} - -static APosixStatus -path_mkdir_recursive( char* path, unsigned len, int mode ) -{ - char old_c; - int ret; - unsigned len2; - - /* get rid of trailing separators */ - while (len > 0 && ispathsep(path[len-1])) - len -= 1; - - if (len == 0) { - errno = ENOENT; - return -1; - } - - /* check that the parent exists, 'len2' is the length of - * the parent part of the path */ - len2 = len-1; - while (len2 > 0 && !ispathsep(path[len2-1])) - len2 -= 1; - - if (len2 > 0) { - old_c = path[len2]; - path[len2] = 0; - ret = 0; - if ( !path_exists(path) ) { - /* the parent doesn't exist, so try to create it */ - ret = path_mkdir_recursive( path, len2, mode ); - } - path[len2] = old_c; - - if (ret < 0) - return ret; - } - - /* at this point, we now the parent exists */ - old_c = path[len]; - path[len] = 0; - ret = path_mkdir( path, mode ); - path[len] = old_c; - - return ret; -} - -/* ensure that a given directory exists, create it if not, - 0 on success, -1 on failure (error code in errno) */ -APosixStatus -path_mkdir_if_needed( const char* path, int mode ) -{ - int ret = 0; - - if (!path_exists(path)) { - ret = path_mkdir(path, mode); - - if (ret < 0 && errno == ENOENT) { - char temp[MAX_PATH]; - unsigned len = (unsigned)strlen(path); - - if (len > sizeof(temp)-1) { - errno = EINVAL; - return -1; - } - memcpy( temp, path, len ); - temp[len] = 0; - - return path_mkdir_recursive(temp, len, mode); - } - } - return ret; -} - -/* return the size of a given file in '*psize'. returns 0 on - * success, -1 on failure (error code in errno) */ -APosixStatus -path_get_size( const char* path, uint64_t *psize ) -{ -#ifdef _WIN32 - /* avoid _stat64 which is only defined in MSVCRT.DLL, not CRTDLL.DLL */ - /* do not use OpenFile() because it has strange search behaviour that could */ - /* result in getting the size of a different file */ - LARGE_INTEGER size; - HANDLE file = CreateFile( /* lpFilename */ path, - /* dwDesiredAccess */ GENERIC_READ, - /* dwSharedMode */ FILE_SHARE_READ|FILE_SHARE_WRITE, - /* lpSecurityAttributes */ NULL, - /* dwCreationDisposition */ OPEN_EXISTING, - /* dwFlagsAndAttributes */ 0, - /* hTemplateFile */ NULL ); - if (file == INVALID_HANDLE_VALUE) { - /* ok, just to play fair */ - errno = ENOENT; - return -1; - } - if (!GetFileSizeEx(file, &size)) { - /* maybe we tried to get the size of a pipe or something like that ? */ - *psize = 0; - } - else { - *psize = (uint64_t) size.QuadPart; - } - CloseHandle(file); - return 0; -#else - int ret; - struct stat st; - - CHECKED(ret, stat(path, &st)); - if (ret == 0) { - *psize = (uint64_t) st.st_size; - } - return ret; -#endif -} - - -/** OTHER FILE UTILITIES - ** - ** path_empty_file() creates an empty file at a given path location. - ** if the file already exists, it is truncated without warning - ** - ** path_copy_file() copies one file into another. - ** - ** both functions return 0 on success, and -1 on error - **/ - -APosixStatus -path_empty_file( const char* path ) -{ -#ifdef _WIN32 - int fd = _creat( path, S_IWRITE ); -#else - /* on Unix, only allow the owner to read/write, since the file * - * may contain some personal data we don't want to see exposed */ - int fd = creat(path, S_IRUSR | S_IWUSR); -#endif - if (fd >= 0) { - close(fd); - return 0; - } - return -1; -} - -APosixStatus -path_copy_file( const char* dest, const char* source ) -{ - int fd, fs, result = -1; - - /* if the destination doesn't exist, create it */ - if ( access(source, F_OK) < 0 || - path_empty_file(dest) < 0) { - return -1; - } - -#ifdef _WIN32 - fd = _open(dest, _O_RDWR | _O_BINARY); - fs = _open(source, _O_RDONLY | _O_BINARY); -#else - fd = creat(dest, S_IRUSR | S_IWUSR); - fs = open(source, S_IREAD); -#endif - if (fs >= 0 && fd >= 0) { - char buf[4096]; - ssize_t total = 0; - ssize_t n; - result = 0; /* success */ - while ((n = read(fs, buf, 4096)) > 0) { - if (write(fd, buf, n) != n) { - /* write failed. Make it return -1 so that an - * empty file be created. */ - D("Failed to copy '%s' to '%s': %s (%d)", - source, dest, strerror(errno), errno); - result = -1; - break; - } - total += n; - } - } - - if (fs >= 0) { - close(fs); - } - if (fd >= 0) { - close(fd); - } - return result; -} - - -APosixStatus -path_delete_file( const char* path ) -{ -#ifdef _WIN32 - int ret = _unlink( path ); - if (ret == -1 && errno == EACCES) { - /* a first call to _unlink will fail if the file is set read-only */ - /* we can however try to change its mode first and call unlink */ - /* again... */ - ret = _chmod( path, _S_IREAD | _S_IWRITE ); - if (ret == 0) - ret = _unlink( path ); - } - return ret; -#else - return unlink(path); -#endif -} - - -void* -path_load_file(const char *fn, size_t *pSize) -{ - char* data; - int sz; - int fd; - - if (pSize) - *pSize = 0; - - data = NULL; - - fd = open(fn, O_BINARY | O_RDONLY); - if(fd < 0) return NULL; - - do { - sz = lseek(fd, 0, SEEK_END); - if(sz < 0) break; - - if (pSize) - *pSize = (size_t) sz; - - if (lseek(fd, 0, SEEK_SET) != 0) - break; - - data = (char*) malloc(sz + 1); - if(data == NULL) break; - - if (read(fd, data, sz) != sz) - break; - - close(fd); - data[sz] = 0; - - return data; - } while (0); - - close(fd); - - if(data != NULL) - free(data); - - return NULL; -} - |