DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/misc/cross.cpp
00001 /*
00002  *  Copyright (C) 2002-2013  The DOSBox Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 
00019 
00020 #include "dosbox.h"
00021 #include "cross.h"
00022 #include "support.h"
00023 #include <string>
00024 #include <stdlib.h>
00025 
00026 #if defined(MACOSX)
00027 std::string MacOSXEXEPath;
00028 std::string MacOSXResPath;
00029 #endif
00030 
00031 #ifdef WIN32
00032 #ifndef _WIN32_IE
00033 #define _WIN32_IE 0x0400
00034 #endif
00035 #include <shlobj.h>
00036 #endif
00037 
00038 #if defined HAVE_SYS_TYPES_H && defined HAVE_PWD_H
00039 #include <sys/types.h>
00040 #include <pwd.h>
00041 #endif
00042 
00043 #if defined __MINGW32__
00044 #define _mkdir(x) mkdir(x)
00045 #endif
00046 
00047 #if defined(WIN32) && !defined(HX_DOS)
00048 static void W32_ConfDir(std::string& in,bool create) {
00049         int c = create?1:0;
00050         char result[MAX_PATH] = { 0 };
00051         BOOL r = SHGetSpecialFolderPath(NULL,result,CSIDL_LOCAL_APPDATA,c);
00052         if(!r || result[0] == 0) r = SHGetSpecialFolderPath(NULL,result,CSIDL_APPDATA,c);
00053         if(!r || result[0] == 0) {
00054                 char const * windir = getenv("windir");
00055                 if(!windir) windir = "c:\\windows";
00056                 safe_strncpy(result,windir,MAX_PATH);
00057                 char const* appdata = "\\Application Data";
00058                 size_t len = strlen(result);
00059                 if(len + strlen(appdata) < MAX_PATH) strcat(result,appdata);
00060                 if(create) _mkdir(result);
00061         }
00062         in = result;
00063 }
00064 #endif
00065 
00066 void Cross::GetPlatformResDir(std::string& in) {
00067 #if defined(MACOSX)
00068         in = MacOSXResPath;
00069 #elif defined(RESDIR)
00070         in = RESDIR;
00071 #endif
00072     if (!in.empty())
00073             in += CROSS_FILESPLIT;
00074 }
00075 
00076 void Cross::GetPlatformConfigDir(std::string& in) {
00077 #if defined(WIN32) && !defined(HX_DOS)
00078         W32_ConfDir(in,false);
00079         in += "\\DOSBox";
00080 #elif defined(MACOSX)
00081         in = "~/Library/Preferences";
00082         ResolveHomedir(in);
00083 #elif defined(HAIKU)
00084         in = "~/config/settings/dosbox";
00085         ResolveHomedir(in);
00086 #elif !defined(HX_DOS)
00087         in = "~/.dosbox";
00088         ResolveHomedir(in);
00089 #endif
00090         in += CROSS_FILESPLIT;
00091 }
00092 
00093 void Cross::GetPlatformConfigName(std::string& in) {
00094 #ifdef WIN32
00095 #define DEFAULT_CONFIG_FILE "dosbox-" VERSION ".conf"
00096 #elif defined(MACOSX)
00097 #define DEFAULT_CONFIG_FILE "DOSBox " VERSION " Preferences"
00098 #else /*linux freebsd*/
00099 #define DEFAULT_CONFIG_FILE "dosbox-" VERSION ".conf"
00100 #endif
00101         in = DEFAULT_CONFIG_FILE;
00102 }
00103 
00104 void Cross::CreatePlatformConfigDir(std::string& in) {
00105 #if defined(WIN32) && !defined(HX_DOS)
00106         W32_ConfDir(in,true);
00107         in += "\\DOSBox";
00108         _mkdir(in.c_str());
00109 #elif defined(MACOSX)
00110         in = "~/Library/Preferences/";
00111         ResolveHomedir(in);
00112         //Don't create it. Assume it exists
00113 #elif defined(HAIKU)
00114         in = "~/config/settings/dosbox";
00115         ResolveHomedir(in);
00116         mkdir(in.c_str(),0700);
00117 #elif !defined(HX_DOS)
00118         in = "~/.dosbox";
00119         ResolveHomedir(in);
00120         mkdir(in.c_str(),0700);
00121 #endif
00122         in += CROSS_FILESPLIT;
00123 }
00124 
00125 void Cross::ResolveHomedir(std::string & temp_line) {
00126         if(!temp_line.size() || temp_line[0] != '~') return; //No ~
00127 
00128         if(temp_line.size() == 1 || temp_line[1] == CROSS_FILESPLIT) { //The ~ and ~/ variant
00129                 char * home = getenv("HOME");
00130                 if(home) temp_line.replace(0,1,std::string(home));
00131 #if defined HAVE_SYS_TYPES_H && defined HAVE_PWD_H
00132         } else { // The ~username variant
00133                 std::string::size_type namelen = temp_line.find(CROSS_FILESPLIT);
00134                 if(namelen == std::string::npos) namelen = temp_line.size();
00135                 std::string username = temp_line.substr(1,namelen - 1);
00136                 struct passwd* pass = getpwnam(username.c_str());
00137                 if(pass) temp_line.replace(0,namelen,pass->pw_dir); //namelen -1 +1(for the ~)
00138 #endif // USERNAME lookup code
00139         }
00140 }
00141 
00142 void Cross::CreateDir(std::string const& in) {
00143 #ifdef WIN32
00144         _mkdir(in.c_str());
00145 #else
00146         mkdir(in.c_str(),0700);
00147 #endif
00148 }
00149 
00150 bool Cross::IsPathAbsolute(std::string const& in) {
00151         // Absolute paths
00152 #if defined (WIN32) || defined(OS2)
00153         // drive letter
00154         if (in.size() > 2 && in[1] == ':' ) return true;
00155         // UNC path
00156         else if (in.size() > 2 && in[0]=='\\' && in[1]=='\\') return true;
00157 #else
00158         if (in.size() > 1 && in[0] == '/' ) return true;
00159 #endif
00160         return false;
00161 }
00162 
00163 #if defined (WIN32)
00164 
00165 dir_information* open_directoryw(const wchar_t* dirname) {
00166         if (dirname == NULL) return NULL;
00167 
00168         size_t len = wcslen(dirname);
00169         if (len == 0) return NULL;
00170 
00171         static dir_information dir;
00172 
00173         wcsncpy(dir.wbase_path(),dirname,MAX_PATH);
00174 
00175         if (dirname[len-1] == '\\') wcscat(dir.wbase_path(),L"*.*");
00176         else                        wcscat(dir.wbase_path(),L"\\*.*");
00177 
00178     dir.wide = true;
00179         dir.handle = INVALID_HANDLE_VALUE;
00180 
00181         return (_waccess(dirname,0) ? NULL : &dir);
00182 }
00183 
00184 dir_information* open_directory(const char* dirname) {
00185         if (dirname == NULL) return NULL;
00186 
00187         size_t len = strlen(dirname);
00188         if (len == 0) return NULL;
00189 
00190         static dir_information dir;
00191 
00192         safe_strncpy(dir.base_path,dirname,MAX_PATH);
00193 
00194         if (dirname[len-1] == '\\') strcat(dir.base_path,"*.*");
00195         else                        strcat(dir.base_path,"\\*.*");
00196 
00197     dir.wide = false;
00198         dir.handle = INVALID_HANDLE_VALUE;
00199 
00200         return (_access(dirname,0) ? NULL : &dir);
00201 }
00202 
00203 bool read_directory_firstw(dir_information* dirp, wchar_t* entry_name, bool& is_directory) {
00204     if (!dirp->wide) return false;
00205 
00206     // TODO: offer a config.h option to opt out of Windows widechar functions
00207         dirp->handle = FindFirstFileW(dirp->wbase_path(), &dirp->search_data.w);
00208         if (INVALID_HANDLE_VALUE == dirp->handle) {
00209                 return false;
00210         }
00211 
00212     // TODO: offer a config.h option to opt out of Windows widechar functions
00213         wcsncpy(entry_name,dirp->search_data.w.cFileName,(MAX_PATH<CROSS_LEN)?MAX_PATH:CROSS_LEN);
00214 
00215         if (dirp->search_data.w.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) is_directory = true;
00216         else is_directory = false;
00217 
00218         return true;
00219 }
00220 
00221 bool read_directory_nextw(dir_information* dirp, wchar_t* entry_name, bool& is_directory) {
00222     if (!dirp->wide) return false;
00223 
00224     // TODO: offer a config.h option to opt out of Windows widechar functions
00225         int result = FindNextFileW(dirp->handle, &dirp->search_data.w);
00226         if (result==0) return false;
00227 
00228     // TODO: offer a config.h option to opt out of Windows widechar functions
00229         wcsncpy(entry_name,dirp->search_data.w.cFileName,(MAX_PATH<CROSS_LEN)?MAX_PATH:CROSS_LEN);
00230 
00231         if (dirp->search_data.w.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) is_directory = true;
00232         else is_directory = false;
00233 
00234         return true;
00235 }
00236 
00237 bool read_directory_first(dir_information* dirp, char* entry_name, bool& is_directory) {
00238     if (dirp->wide) return false;
00239 
00240     // TODO: offer a config.h option to opt out of Windows widechar functions
00241         dirp->handle = FindFirstFileA(dirp->base_path, &dirp->search_data.a);
00242         if (INVALID_HANDLE_VALUE == dirp->handle) {
00243                 return false;
00244         }
00245 
00246     // TODO: offer a config.h option to opt out of Windows widechar functions
00247         safe_strncpy(entry_name,dirp->search_data.a.cFileName,(MAX_PATH<CROSS_LEN)?MAX_PATH:CROSS_LEN);
00248 
00249         if (dirp->search_data.a.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) is_directory = true;
00250         else is_directory = false;
00251 
00252         return true;
00253 }
00254 
00255 bool read_directory_next(dir_information* dirp, char* entry_name, bool& is_directory) {
00256     if (dirp->wide) return false;
00257 
00258     // TODO: offer a config.h option to opt out of Windows widechar functions
00259         int result = FindNextFileA(dirp->handle, &dirp->search_data.a);
00260         if (result==0) return false;
00261 
00262     // TODO: offer a config.h option to opt out of Windows widechar functions
00263         safe_strncpy(entry_name,dirp->search_data.a.cFileName,(MAX_PATH<CROSS_LEN)?MAX_PATH:CROSS_LEN);
00264 
00265         if (dirp->search_data.a.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) is_directory = true;
00266         else is_directory = false;
00267 
00268         return true;
00269 }
00270 
00271 void close_directory(dir_information* dirp) {
00272         if (dirp->handle != INVALID_HANDLE_VALUE) {
00273                 FindClose(dirp->handle);
00274                 dirp->handle = INVALID_HANDLE_VALUE;
00275         }
00276 }
00277 
00278 #else
00279 
00280 dir_information* open_directory(const char* dirname) {
00281         static dir_information dir;
00282         dir.dir=opendir(dirname);
00283         safe_strncpy(dir.base_path,dirname,CROSS_LEN);
00284         return dir.dir?&dir:NULL;
00285 }
00286 
00287 bool read_directory_first(dir_information* dirp, char* entry_name, bool& is_directory) {
00288         struct dirent* dentry = readdir(dirp->dir);
00289         if (dentry==NULL) {
00290                 return false;
00291         }
00292 
00293 //      safe_strncpy(entry_name,dentry->d_name,(FILENAME_MAX<MAX_PATH)?FILENAME_MAX:MAX_PATH);  // [include stdio.h], maybe pathconf()
00294         safe_strncpy(entry_name,dentry->d_name,CROSS_LEN);
00295 
00296 #ifdef DIRENT_HAS_D_TYPE
00297         if(dentry->d_type == DT_DIR) {
00298                 is_directory = true;
00299                 return true;
00300         } else if(dentry->d_type == DT_REG) {
00301                 is_directory = false;
00302                 return true;
00303         }
00304 #endif
00305 
00306         // probably use d_type here instead of a full stat()
00307         static char buffer[2*CROSS_LEN] = { 0 };
00308         buffer[0] = 0;
00309         strcpy(buffer,dirp->base_path);
00310         strcat(buffer,entry_name);
00311         struct stat status;
00312         if (stat(buffer,&status)==0) is_directory = (S_ISDIR(status.st_mode)>0);
00313         else is_directory = false;
00314 
00315         return true;
00316 }
00317 
00318 bool read_directory_next(dir_information* dirp, char* entry_name, bool& is_directory) {
00319         struct dirent* dentry = readdir(dirp->dir);
00320         if (dentry==NULL) {
00321                 return false;
00322         }
00323 
00324 //      safe_strncpy(entry_name,dentry->d_name,(FILENAME_MAX<MAX_PATH)?FILENAME_MAX:MAX_PATH);  // [include stdio.h], maybe pathconf()
00325         safe_strncpy(entry_name,dentry->d_name,CROSS_LEN);
00326 
00327 #ifdef DIRENT_HAS_D_TYPE
00328         if(dentry->d_type == DT_DIR) {
00329                 is_directory = true;
00330                 return true;
00331         } else if(dentry->d_type == DT_REG) {
00332                 is_directory = false;
00333                 return true;
00334         }
00335 #endif
00336 
00337         // probably use d_type here instead of a full stat()
00338         static char buffer[2*CROSS_LEN] = { 0 };
00339         buffer[0] = 0;
00340         strcpy(buffer,dirp->base_path);
00341         strcat(buffer,entry_name);
00342         struct stat status;
00343 
00344         if (stat(buffer,&status)==0) is_directory = (S_ISDIR(status.st_mode)>0);
00345         else is_directory = false;
00346 
00347         return true;
00348 }
00349 
00350 void close_directory(dir_information* dirp) {
00351         closedir(dirp->dir);
00352 }
00353 
00354 #endif