/* * This file is part of the Advance project. * * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Andrea Mazzoleni * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. * * In addition, as a special exception, Andrea Mazzoleni * gives permission to link the code of this program with * the MAME library (or with modified versions of MAME that use the * same license as MAME), and distribute linked combinations including * the two. You must obey the GNU General Public License in all * respects for all of the code used other than MAME. If you modify * this file, you may extend this exception to your version of the * file, but you are not obligated to do so. If you do not wish to * do so, delete this exception statement from your version. */ #include "portable.h" #include "file.h" #include "snstring.h" #include #include /** Number of universal buffers. */ #define UNIVERSAL_MAX 4 /** Size of a universal buffer. */ #define UNIVERSAL_SIZE 4096 struct file_context { char file_abs_buffer[FILE_MAXPATH]; /**< Absolute path returned by file_abs_buffer. */ char file_home_buffer[FILE_MAXPATH]; char list_buffer[FILE_MAXPATH*4]; char universal_map[UNIVERSAL_MAX][UNIVERSAL_SIZE]; unsigned universal_mac; }; static struct file_context FL; /***************************************************************************/ /* Init */ adv_error file_init(void) { memset(&FL, 0, sizeof(FL)); FL.universal_mac = 0; return 0; } void file_done(void) { } /***************************************************************************/ /* File System */ char file_dir_separator(void) { return ';'; } char file_dir_slash(void) { return '\\'; } adv_error file_dir_make(const char* dir) { #ifdef __WIN32__ return mkdir(dir); #else return mkdir(dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); #endif } adv_bool file_path_is_abs(const char* path) { return path[0] == '\\' || (path[0] != 0 && path[1]==':'); } const char* file_abs(const char* dir, const char* file) { if (file_path_is_abs(file)) { snprintf(FL.file_abs_buffer, sizeof(FL.file_abs_buffer), "%s", file); } else { while (file[0] == '.' && file[1] == '\\') file += 2; if (!dir[0] || dir[strlen(dir)-1] != '\\') snprintf(FL.file_abs_buffer, sizeof(FL.file_abs_buffer), "%s\\%s", dir, file); else snprintf(FL.file_abs_buffer, sizeof(FL.file_abs_buffer), "%s%s", dir, file); } return FL.file_abs_buffer; } static char* import_conv(char* dst_begin, char* dst_end, const char* begin, const char* end) { adv_bool need_slash; if (end - begin == 2 && begin[1]==':') { /* only drive spec */ memcpy(dst_begin, "/dos/", 5); dst_begin += 5; *dst_begin++ = tolower(begin[0]); begin += 2; need_slash = 1; } else if (end - begin >= 3 && begin[1]==':' && (begin[2]=='\\' || begin[2]=='/')) { /* absolute path */ memcpy(dst_begin, "/dos/", 5); dst_begin += 5; *dst_begin++ = tolower(begin[0]); begin += 3; need_slash = 1; } else if (end - begin >= 3 && begin[1]==':') { /* drive + relative path, assume it's an absolute path */ memcpy(dst_begin, "/dos/", 5); dst_begin += 5; *dst_begin++ = tolower(begin[0]); begin += 2; need_slash = 1; } else if (end - begin >= 1 && (begin[0]=='\\' || begin[0]=='/')) { /* absolute path on the current drive */ memcpy(dst_begin, "/dos/", 5); dst_begin += 5; #ifdef __MSDOS__ *dst_begin++ = getdisk() + 'a'; #else *dst_begin++ = _getdrive() + 'a'; #endif begin += 1; need_slash = 1; } else { /* relative path, keep it relative */ need_slash = 0; } /* add a slash if something other is specified */ if (need_slash && begin != end) { *dst_begin++ = '/'; } /* copy the remaining path */ while (begin != end) { if (*begin=='\\') *dst_begin++ = '/'; else *dst_begin++ = tolower(*begin); ++begin; } return dst_begin; } static char* export_conv(char* dst_begin, char* dst_end, const char* begin, const char* end) { if (end - begin == 6 && memcmp(begin, "/dos/", 5)==0) { /* root dir */ *dst_begin++ = begin[5]; *dst_begin++ = ':'; *dst_begin++ = '\\'; begin += 6; } else if (end - begin >= 7 && memcmp(begin, "/dos/", 5)==0) { /* absolute path */ *dst_begin++ = begin[5]; *dst_begin++ = ':'; *dst_begin++ = '\\'; begin += 7; } else { /* relative path */ } /* copy the remaining path */ while (begin != end) { if (*begin=='/') *dst_begin++ = '\\'; else *dst_begin++ = *begin; ++begin; } return dst_begin; } const char* file_import(const char* path) { char* buffer = FL.universal_map[FL.universal_mac]; const char* begin = path; char* dst_begin = buffer; char* dst_end = buffer + UNIVERSAL_SIZE; FL.universal_mac = (FL.universal_mac + 1) % UNIVERSAL_MAX; while (*begin) { const char* end = strchr(begin, ';'); if (!end) end = begin + strlen(begin); if (dst_begin != buffer) *dst_begin++ = ':'; dst_begin = import_conv(dst_begin, dst_end, begin, end); begin = end; if (*begin) ++begin; } *dst_begin = 0; return buffer; } const char* file_export(const char* path) { char* buffer = FL.universal_map[FL.universal_mac]; const char* begin = path; char* dst_begin = buffer; char* dst_end = buffer + UNIVERSAL_SIZE; FL.universal_mac = (FL.universal_mac + 1) % UNIVERSAL_MAX; while (*begin) { const char* end = strchr(begin, ':'); if (!end) end = begin + strlen(begin); if (dst_begin != buffer) *dst_begin++ = ';'; dst_begin = export_conv(dst_begin, dst_end, begin, end); begin = end; if (*begin) ++begin; } *dst_begin = 0; return buffer; } /***************************************************************************/ /* Files */ const char* file_config_file_host(const char* file) { return 0; } const char* file_config_file_data(const char* file) { return 0; } const char* file_config_file_home(const char* file) { snprintf(FL.file_home_buffer, sizeof(FL.file_home_buffer), "%s", file); return FL.file_home_buffer; } const char* file_config_dir_multidir(const char* tag) { return tag; } const char* file_config_dir_singledir(const char* tag) { return tag; } const char* file_config_dir_singlefile(void) { return "."; } const char* file_config_list(const char* const_list, const char* (*expand_dir)(const char* tag), const char* ref_dir) { char* list = strdup(const_list); int i; FL.list_buffer[0] = 0; i = 0; while (list[i]) { char c; const char* file; file = stoken(&c, &i, list, ";", ""); if (FL.list_buffer[0]) sncat(FL.list_buffer, sizeof(FL.list_buffer), ";"); if (ref_dir) sncat(FL.list_buffer, sizeof(FL.list_buffer), file_abs(ref_dir, file)); else sncat(FL.list_buffer, sizeof(FL.list_buffer), file); } free(list); return FL.list_buffer; }