/* * Copyright © 2006-2016 SplinterGU (Fenix/Bennugd) * Copyright © 2002-2006 Fenix Team (Fenix) * Copyright © 1999-2002 José Luis Cebrián Pagüe (Fenix) * * This file is part of Bennu - Game Development * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 3. This notice may not be removed or altered from any source * distribution. * */ /* * FILE : dirs.c * DESCRIPTION : directory functions * * HISTORY: * */ #include "bgdrtm.h" #include "dirs.h" #include "xstrings.h" #include #include #include /* ------------------------------------------------------------------------------------ */ /* * FUNCTION : dir_path_convert * * Convert a path to the valid OS format * * PARAMS : * char * path: path to convert * * RETURN VALUE : * char *: converted path * */ char * dir_path_convert( const char * dir ) { char *c, *p ; p = strdup( dir ) ; if ( !p ) return NULL; c = p ; /* Convert characters */ while ( *p ) { if ( *p == PATH_CHAR_ISEP ) *p = PATH_CHAR_SEP ; p++ ; } return c; } /* ------------------------------------------------------------------------------------ */ /* * FUNCTION : dir_current * * Retrieve current directory * * PARAMS : * * RETURN VALUE : * STRING ID pointing to a system string with the current dir * */ char * dir_current( void ) { return ( getcwd( NULL, 0 ) ) ; } /* ------------------------------------------------------------------------------------ */ /* * FUNCTION : dir_change * * Retrieve current directory * * PARAMS : * char * dir: the new current directory * * RETURN VALUE : * 0 - FAILURE * NON_ZERO - SUCCESS * */ int dir_change( const char * dir ) { char *c = dir_path_convert( dir ) ; if ( !c ) return 0; int r = chdir( c ) ; free( c ) ; return r ; } /* ------------------------------------------------------------------------------------ */ /* * FUNCTION : dir_create * * Retrieve current directory * * PARAMS : * char * dir: the directory to create * * RETURN VALUE : * 0 - FAILURE * NON_ZERO - SUCCESS * */ int dir_create( const char * dir ) { char *c = dir_path_convert( dir ) ; if ( !c ) return 0; #ifdef WIN32 int r = mkdir( c ) ; #else int r = mkdir( c, 0777 ) ; #endif free( c ) ; return r ; } /* ------------------------------------------------------------------------------------ */ /* * FUNCTION : dir_delete * * Retrieve current directory * * PARAMS : * char * dir: the directory to delete * * RETURN VALUE : * 0 - FAILURE * NON_ZERO - SUCCESS * */ int dir_delete( const char * dir ) { char *c = dir_path_convert( dir ) ; if ( !c ) return 0; int r = rmdir( c ) ; free( c ) ; return r ; } /* ------------------------------------------------------------------------------------ */ /* * FUNCTION : dir_deletefile * * Remove a given file * * PARAMS : * char * filename: the file to delete * * RETURN VALUE : * 0 - FAILURE * NON_ZERO - SUCCESS * */ int dir_deletefile( const char * filename ) { char *c = dir_path_convert( filename ) ; if ( !c ) return 0; int r = unlink( c ) ; free( c ) ; return ( r == -1 ) ? 0 : 1 ; } /* ------------------------------------------------------------------------------------ */ __DIR_ST * dir_open( const char * path ) { __DIR_ST * hDir = malloc( sizeof( __DIR_ST ) ); if ( !hDir ) return NULL; hDir->path = strdup( path ); if ( !hDir->path ) { free ( hDir ); return NULL; } #ifdef _WIN32 hDir->handle = FindFirstFile( hDir->path, &hDir->data ); hDir->eod = ( hDir->handle == INVALID_HANDLE_VALUE ); if ( !hDir->handle ) { free( hDir->path ); free( hDir ); return NULL; } #else const char * ptr = hDir->path; char * fptr; int r; hDir->pattern = malloc( strlen( path ) * 4 ); if ( !hDir->pattern ) { free ( hDir->path ); free ( hDir ); return NULL; } /* Clean the path creating a case-insensitive match pattern */ fptr = hDir->pattern; while ( *ptr ) { if ( *ptr == '\\' ) { *fptr++ = '/'; } else if ( *ptr >= 'a' && *ptr <= 'z' ) { *fptr++ = '['; *fptr++ = *ptr; *fptr++ = toupper( *ptr ); *fptr++ = ']'; } else if ( *ptr >= 'A' && *ptr <= 'Z' ) { *fptr++ = '['; *fptr++ = tolower( *ptr ); *fptr++ = *ptr; *fptr++ = ']'; } else *fptr++ = *ptr; ptr++; } *fptr = 0; /* Convert '*.*' to '*' */ if ( fptr > hDir->pattern + 2 && fptr[ -1 ] == '*' && fptr[ -2 ] == '.' && fptr[ -3 ] == '*' ) fptr[ -2 ] = 0; #if defined(TARGET_MAC) || defined(TARGET_BEOS) r = glob( hDir->pattern, GLOB_ERR | GLOB_NOSORT, NULL, &hDir->globd ); #else r = glob( hDir->pattern, GLOB_ERR | GLOB_PERIOD | GLOB_NOSORT, NULL, &hDir->globd ); #endif if ( r ) { free( hDir->pattern ); free( hDir->path ); free( hDir ); return NULL; } hDir->currFile = 0; #endif return hDir; } /* ------------------------------------------------------------------------------------ */ void dir_close ( __DIR_ST * hDir ) { free ( hDir->path ); #ifdef _WIN32 FindClose( hDir->handle ); #else globfree( &hDir->globd ); free( hDir->pattern ); #endif free ( hDir ); } /* ------------------------------------------------------------------------------------ */ __DIR_FILEINFO_ST * dir_read( __DIR_ST * hDir ) { char realpath[__MAX_PATH]; char * ptr ; #ifdef _WIN32 SYSTEMTIME time; if ( hDir->eod ) return NULL; /* Fill the FILEINFO struct */ strcpy( realpath, hDir->path ); ptr = realpath + strlen( realpath ); while ( ptr >= realpath ) { if ( *ptr == '\\' || *ptr == '/' ) { ptr[ 1 ] = 0; break; } ptr--; } memset( &hDir->info, '\0', sizeof( hDir->info ) ); strcat( realpath, hDir->data.cFileName ); GetFullPathName( realpath, __MAX_PATH, hDir->info.fullpath, &ptr ); if ( ptr ) * ptr = '\0'; strcpy ( hDir->info.filename, hDir->data.cFileName ); hDir->info.attributes = (( hDir->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) ? DIR_FI_ATTR_DIRECTORY : 0 ) | (( hDir->data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN ) ? DIR_FI_ATTR_HIDDEN : 0 ) | (( hDir->data.dwFileAttributes & FILE_ATTRIBUTE_READONLY ) ? DIR_FI_ATTR_READONLY : 0 ); hDir->info.size = hDir->data.nFileSizeLow; /* Format and store the creation time */ FileTimeToSystemTime( &hDir->data.ftCreationTime, &time ); hDir->info.crtime.tm_sec = time.wSecond; hDir->info.crtime.tm_min = time.wMinute; hDir->info.crtime.tm_hour = time.wHour; hDir->info.crtime.tm_mday = time.wDay; hDir->info.crtime.tm_mon = time.wMonth - 1; hDir->info.crtime.tm_year = time.wYear - 1900; hDir->info.crtime.tm_wday = time.wDayOfWeek; hDir->info.crtime.tm_yday = time.wMonth; hDir->info.crtime.tm_isdst = -1; /* Format and store the last write time */ FileTimeToSystemTime( &hDir->data.ftLastWriteTime, &time ); hDir->info.mtime.tm_sec = time.wSecond; hDir->info.mtime.tm_min = time.wMinute; hDir->info.mtime.tm_hour = time.wHour; hDir->info.mtime.tm_mday = time.wDay; hDir->info.mtime.tm_mon = time.wMonth - 1; hDir->info.mtime.tm_year = time.wYear - 1900; hDir->info.mtime.tm_wday = time.wDayOfWeek; hDir->info.mtime.tm_yday = time.wMonth; hDir->info.mtime.tm_isdst = -1; /* Format and store the last access time */ FileTimeToSystemTime( &hDir->data.ftLastAccessTime, &time ); hDir->info.atime.tm_sec = time.wSecond; hDir->info.atime.tm_min = time.wMinute; hDir->info.atime.tm_hour = time.wHour; hDir->info.atime.tm_mday = time.wDay; hDir->info.atime.tm_mon = time.wMonth - 1; hDir->info.atime.tm_year = time.wYear - 1900; hDir->info.atime.tm_wday = time.wDayOfWeek; hDir->info.atime.tm_yday = time.wMonth; hDir->info.atime.tm_isdst = -1; /* Continue last search */ if (!FindNextFile( hDir->handle, &hDir->data )) hDir->eod = 1; #else struct stat s; if ( hDir->currFile == hDir->globd.gl_pathc ) return NULL; memset( &hDir->info, '\0', sizeof( hDir->info ) ); stat( hDir->globd.gl_pathv[ hDir->currFile ], &s ); ptr = strrchr( hDir->globd.gl_pathv[ hDir->currFile ], '/' ); if ( !ptr ) { strcpy ( hDir->info.filename, hDir->globd.gl_pathv[ hDir->currFile ] ); strcpy ( hDir->info.fullpath, getcwd( realpath, sizeof( realpath ) ) ); } else { strcpy ( hDir->info.filename, ptr + 1 ); if ( hDir->globd.gl_pathv[ hDir->currFile ][0] == '/' ) { strcpy ( hDir->info.fullpath, hDir->globd.gl_pathv[ hDir->currFile ] ); hDir->info.fullpath[ ptr - hDir->globd.gl_pathv[ hDir->currFile ] + 1 ] = '\0'; } else { strcpy ( hDir->info.fullpath, getcwd( realpath, sizeof( realpath ) ) ); strcat ( hDir->info.fullpath, "/" ); strcat ( hDir->info.fullpath, hDir->globd.gl_pathv[ hDir->currFile ] ); ptr = strrchr( hDir->info.fullpath, '/' ); *(ptr + 1) = '\0'; } } hDir->info.attributes = (( S_ISDIR( s.st_mode ) ) ? DIR_FI_ATTR_DIRECTORY : 0 ) | (( hDir->info.filename[0] == '.' ) ? DIR_FI_ATTR_HIDDEN : 0 ) | (( !( s.st_mode & 0444 ) ) ? DIR_FI_ATTR_READONLY : 0 ); hDir->info.size = s.st_size; hDir->info.mtime = *localtime( &s.st_mtime ) ; hDir->info.atime = *localtime( &s.st_atime ) ; hDir->info.ctime = *localtime( &s.st_ctime ) ; hDir->currFile++; #endif return ( &hDir->info ); } /* ------------------------------------------------------------------------------------ */