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(HX_DOS)
00084         in = "~/.dosbox";
00085         ResolveHomedir(in);
00086 #endif
00087         in += CROSS_FILESPLIT;
00088 }
00089 
00090 void Cross::GetPlatformConfigName(std::string& in) {
00091 #ifdef WIN32
00092 #define DEFAULT_CONFIG_FILE "dosbox-" VERSION ".conf"
00093 #elif defined(MACOSX)
00094 #define DEFAULT_CONFIG_FILE "DOSBox " VERSION " Preferences"
00095 #else /*linux freebsd*/
00096 #define DEFAULT_CONFIG_FILE "dosbox-" VERSION ".conf"
00097 #endif
00098         in = DEFAULT_CONFIG_FILE;
00099 }
00100 
00101 void Cross::CreatePlatformConfigDir(std::string& in) {
00102 #if defined(WIN32) && !defined(HX_DOS)
00103         W32_ConfDir(in,true);
00104         in += "\\DOSBox";
00105         _mkdir(in.c_str());
00106 #elif defined(MACOSX)
00107         in = "~/Library/Preferences/";
00108         ResolveHomedir(in);
00109         //Don't create it. Assume it exists
00110 #elif !defined(HX_DOS)
00111         in = "~/.dosbox";
00112         ResolveHomedir(in);
00113         mkdir(in.c_str(),0700);
00114 #endif
00115         in += CROSS_FILESPLIT;
00116 }
00117 
00118 void Cross::ResolveHomedir(std::string & temp_line) {
00119         if(!temp_line.size() || temp_line[0] != '~') return; //No ~
00120 
00121         if(temp_line.size() == 1 || temp_line[1] == CROSS_FILESPLIT) { //The ~ and ~/ variant
00122                 char * home = getenv("HOME");
00123                 if(home) temp_line.replace(0,1,std::string(home));
00124 #if defined HAVE_SYS_TYPES_H && defined HAVE_PWD_H
00125         } else { // The ~username variant
00126                 std::string::size_type namelen = temp_line.find(CROSS_FILESPLIT);
00127                 if(namelen == std::string::npos) namelen = temp_line.size();
00128                 std::string username = temp_line.substr(1,namelen - 1);
00129                 struct passwd* pass = getpwnam(username.c_str());
00130                 if(pass) temp_line.replace(0,namelen,pass->pw_dir); //namelen -1 +1(for the ~)
00131 #endif // USERNAME lookup code
00132         }
00133 }
00134 
00135 void Cross::CreateDir(std::string const& in) {
00136 #ifdef WIN32
00137         _mkdir(in.c_str());
00138 #else
00139         mkdir(in.c_str(),0700);
00140 #endif
00141 }
00142 
00143 bool Cross::IsPathAbsolute(std::string const& in) {
00144         // Absolute paths
00145 #if defined (WIN32) || defined(OS2)
00146         // drive letter
00147         if (in.size() > 2 && in[1] == ':' ) return true;
00148         // UNC path
00149         else if (in.size() > 2 && in[0]=='\\' && in[1]=='\\') return true;
00150 #else
00151         if (in.size() > 1 && in[0] == '/' ) return true;
00152 #endif
00153         return false;
00154 }
00155 
00156 #if defined (WIN32)
00157 
00158 dir_information* open_directoryw(const wchar_t* dirname) {
00159         if (dirname == NULL) return NULL;
00160 
00161         size_t len = wcslen(dirname);
00162         if (len == 0) return NULL;
00163 
00164         static dir_information dir;
00165 
00166         wcsncpy(dir.wbase_path(),dirname,MAX_PATH);
00167 
00168         if (dirname[len-1] == '\\') wcscat(dir.wbase_path(),L"*.*");
00169         else                        wcscat(dir.wbase_path(),L"\\*.*");
00170 
00171     dir.wide = true;
00172         dir.handle = INVALID_HANDLE_VALUE;
00173 
00174         return (_waccess(dirname,0) ? NULL : &dir);
00175 }
00176 
00177 dir_information* open_directory(const char* dirname) {
00178         if (dirname == NULL) return NULL;
00179 
00180         size_t len = strlen(dirname);
00181         if (len == 0) return NULL;
00182 
00183         static dir_information dir;
00184 
00185         safe_strncpy(dir.base_path,dirname,MAX_PATH);
00186 
00187         if (dirname[len-1] == '\\') strcat(dir.base_path,"*.*");
00188         else                        strcat(dir.base_path,"\\*.*");
00189 
00190     dir.wide = false;
00191         dir.handle = INVALID_HANDLE_VALUE;
00192 
00193         return (_access(dirname,0) ? NULL : &dir);
00194 }
00195 
00196 bool read_directory_firstw(dir_information* dirp, wchar_t* entry_name, bool& is_directory) {
00197     if (!dirp->wide) return false;
00198 
00199     // TODO: offer a config.h option to opt out of Windows widechar functions
00200         dirp->handle = FindFirstFileW(dirp->wbase_path(), &dirp->search_data.w);
00201         if (INVALID_HANDLE_VALUE == dirp->handle) {
00202                 return false;
00203         }
00204 
00205     // TODO: offer a config.h option to opt out of Windows widechar functions
00206         wcsncpy(entry_name,dirp->search_data.w.cFileName,(MAX_PATH<CROSS_LEN)?MAX_PATH:CROSS_LEN);
00207 
00208         if (dirp->search_data.w.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) is_directory = true;
00209         else is_directory = false;
00210 
00211         return true;
00212 }
00213 
00214 bool read_directory_nextw(dir_information* dirp, wchar_t* entry_name, bool& is_directory) {
00215     if (!dirp->wide) return false;
00216 
00217     // TODO: offer a config.h option to opt out of Windows widechar functions
00218         int result = FindNextFileW(dirp->handle, &dirp->search_data.w);
00219         if (result==0) return false;
00220 
00221     // TODO: offer a config.h option to opt out of Windows widechar functions
00222         wcsncpy(entry_name,dirp->search_data.w.cFileName,(MAX_PATH<CROSS_LEN)?MAX_PATH:CROSS_LEN);
00223 
00224         if (dirp->search_data.w.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) is_directory = true;
00225         else is_directory = false;
00226 
00227         return true;
00228 }
00229 
00230 bool read_directory_first(dir_information* dirp, char* entry_name, bool& is_directory) {
00231     if (dirp->wide) return false;
00232 
00233     // TODO: offer a config.h option to opt out of Windows widechar functions
00234         dirp->handle = FindFirstFileA(dirp->base_path, &dirp->search_data.a);
00235         if (INVALID_HANDLE_VALUE == dirp->handle) {
00236                 return false;
00237         }
00238 
00239     // TODO: offer a config.h option to opt out of Windows widechar functions
00240         safe_strncpy(entry_name,dirp->search_data.a.cFileName,(MAX_PATH<CROSS_LEN)?MAX_PATH:CROSS_LEN);
00241 
00242         if (dirp->search_data.a.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) is_directory = true;
00243         else is_directory = false;
00244 
00245         return true;
00246 }
00247 
00248 bool read_directory_next(dir_information* dirp, char* entry_name, bool& is_directory) {
00249     if (dirp->wide) return false;
00250 
00251     // TODO: offer a config.h option to opt out of Windows widechar functions
00252         int result = FindNextFileA(dirp->handle, &dirp->search_data.a);
00253         if (result==0) return false;
00254 
00255     // TODO: offer a config.h option to opt out of Windows widechar functions
00256         safe_strncpy(entry_name,dirp->search_data.a.cFileName,(MAX_PATH<CROSS_LEN)?MAX_PATH:CROSS_LEN);
00257 
00258         if (dirp->search_data.a.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) is_directory = true;
00259         else is_directory = false;
00260 
00261         return true;
00262 }
00263 
00264 void close_directory(dir_information* dirp) {
00265         if (dirp->handle != INVALID_HANDLE_VALUE) {
00266                 FindClose(dirp->handle);
00267                 dirp->handle = INVALID_HANDLE_VALUE;
00268         }
00269 }
00270 
00271 #else
00272 
00273 dir_information* open_directory(const char* dirname) {
00274         static dir_information dir;
00275         dir.dir=opendir(dirname);
00276         safe_strncpy(dir.base_path,dirname,CROSS_LEN);
00277         return dir.dir?&dir:NULL;
00278 }
00279 
00280 bool read_directory_first(dir_information* dirp, char* entry_name, bool& is_directory) {
00281         struct dirent* dentry = readdir(dirp->dir);
00282         if (dentry==NULL) {
00283                 return false;
00284         }
00285 
00286 //      safe_strncpy(entry_name,dentry->d_name,(FILENAME_MAX<MAX_PATH)?FILENAME_MAX:MAX_PATH);  // [include stdio.h], maybe pathconf()
00287         safe_strncpy(entry_name,dentry->d_name,CROSS_LEN);
00288 
00289 #ifdef DIRENT_HAS_D_TYPE
00290         if(dentry->d_type == DT_DIR) {
00291                 is_directory = true;
00292                 return true;
00293         } else if(dentry->d_type == DT_REG) {
00294                 is_directory = false;
00295                 return true;
00296         }
00297 #endif
00298 
00299         // probably use d_type here instead of a full stat()
00300         static char buffer[2*CROSS_LEN] = { 0 };
00301         buffer[0] = 0;
00302         strcpy(buffer,dirp->base_path);
00303         strcat(buffer,entry_name);
00304         struct stat status;
00305         if (stat(buffer,&status)==0) is_directory = (S_ISDIR(status.st_mode)>0);
00306         else is_directory = false;
00307 
00308         return true;
00309 }
00310 
00311 bool read_directory_next(dir_information* dirp, char* entry_name, bool& is_directory) {
00312         struct dirent* dentry = readdir(dirp->dir);
00313         if (dentry==NULL) {
00314                 return false;
00315         }
00316 
00317 //      safe_strncpy(entry_name,dentry->d_name,(FILENAME_MAX<MAX_PATH)?FILENAME_MAX:MAX_PATH);  // [include stdio.h], maybe pathconf()
00318         safe_strncpy(entry_name,dentry->d_name,CROSS_LEN);
00319 
00320 #ifdef DIRENT_HAS_D_TYPE
00321         if(dentry->d_type == DT_DIR) {
00322                 is_directory = true;
00323                 return true;
00324         } else if(dentry->d_type == DT_REG) {
00325                 is_directory = false;
00326                 return true;
00327         }
00328 #endif
00329 
00330         // probably use d_type here instead of a full stat()
00331         static char buffer[2*CROSS_LEN] = { 0 };
00332         buffer[0] = 0;
00333         strcpy(buffer,dirp->base_path);
00334         strcat(buffer,entry_name);
00335         struct stat status;
00336 
00337         if (stat(buffer,&status)==0) is_directory = (S_ISDIR(status.st_mode)>0);
00338         else is_directory = false;
00339 
00340         return true;
00341 }
00342 
00343 void close_directory(dir_information* dirp) {
00344         closedir(dirp->dir);
00345 }
00346 
00347 #endif