Drizzled Public API Documentation

CSSys_win.cc
00001 /* Copyright (C) 2010 PrimeBase Technologies GmbH, Germany
00002  *
00003  * PrimeBase Media Stream for MySQL
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation; either version 2 of the License, or
00008  * (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
00018  *
00019  * Author: Barry Leslie
00020  *
00021  * 2010-02-05
00022  *
00023  * CORE SYSTEM:
00024  * Basic UNIX specific file I/O classes.
00025  *
00026  */
00027 
00028 #include "CSConfig.h"
00029 
00030 #include <io.h>
00031 
00032 #include "CSGlobal.h"
00033 #include "CSDefs.h"
00034 #include "CSStrUtil.h"
00035 #include "CSSys.h"
00036 
00037 #define CS_MASK   ((S_IRUSR | S_IWUSR) | (S_IRGRP | S_IWGRP) | (S_IROTH))
00038 //=====================
00039 // CSSysFile
00040 //=====================
00041 static int get_win_error()
00042 {
00043   return (int) GetLastError();
00044 }
00045 
00046 bool CSSysFile::isDirNotFound(CSException *e) { return e->getErrorCode() == ERROR_PATH_NOT_FOUND; }
00047 bool CSSysFile::isFileNotFound(CSException *e) { return e->getErrorCode() == ERROR_FILE_NOT_FOUND; }
00048 bool CSSysFile::isDirExists(CSException *e) { return e->getErrorCode() == ERROR_ALREADY_EXISTS; }
00049 
00050 
00051 //--------------
00052 void CSSysFile::sf_open(const char *path, bool readonly, bool create)
00053 {
00054   SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), 0, 0 };
00055   DWORD       flags;
00056 
00057   flags = (create)?OPEN_ALWAYS:OPEN_EXISTING;
00058   
00059   if (sf_fh != INVALID_HANDLE_VALUE)
00060     sf_close();
00061   
00062   sf_path = CSString::newString(path);
00063   
00064   sf_fh = CreateFileA(
00065     path,
00066     readonly ? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE),
00067     FILE_SHARE_READ | FILE_SHARE_WRITE,
00068     &sa,
00069     flags,
00070     FILE_FLAG_RANDOM_ACCESS,
00071     NULL);
00072     
00073   if (sf_fh == INVALID_HANDLE_VALUE) {
00074     sf_path->release();
00075     sf_path = NULL;
00076     CSException::throwFileError(CS_CONTEXT, path, get_win_error());
00077   }
00078 }
00079 
00080 //--------------
00081 void CSSysFile::sf_close()
00082 {
00083   if (sf_fh != INVALID_HANDLE_VALUE) {
00084     CloseHandle(sf_fh);
00085     sf_fh = INVALID_HANDLE_VALUE;
00086     sf_path->release();
00087     sf_path = NULL;
00088   } 
00089 }
00090 
00091 //--------------
00092 size_t CSSysFile::sf_pread(void *data, size_t size, off64_t offset)
00093 {
00094   LARGE_INTEGER liDistanceToMove;
00095   DWORD     result;
00096 
00097   liDistanceToMove.QuadPart = offset;
00098   if (!SetFilePointerEx(sf_fh, liDistanceToMove, NULL, FILE_BEGIN))
00099     CSException::throwFileError(CS_CONTEXT, sf_path->getCString(), get_win_error());
00100 
00101   if (!ReadFile(sf_fh, data, size, &result, NULL))
00102     CSException::throwFileError(CS_CONTEXT, sf_path->getCString(), get_win_error());
00103 
00104   return (size_t) result;
00105 }
00106 
00107 //--------------
00108 void CSSysFile::sf_pwrite(const void *data, size_t size, off64_t offset)
00109 {
00110   LARGE_INTEGER liDistanceToMove;
00111   DWORD     result;
00112   
00113   liDistanceToMove.QuadPart = offset;
00114   if (!SetFilePointerEx(sf_fh, liDistanceToMove, NULL, FILE_BEGIN))
00115     CSException::throwFileError(CS_CONTEXT, sf_path->getCString(), get_win_error());
00116 
00117   if (!WriteFile(sf_fh, data, size, &result, NULL))
00118     CSException::throwFileError(CS_CONTEXT, sf_path->getCString(), get_win_error());
00119 
00120   if (result != size)
00121     CSException::throwFileError(CS_CONTEXT, sf_path->getCString(), ERROR_HANDLE_EOF);
00122   
00123 }
00124 
00125 //--------------
00126 void CSSysFile::sf_setEOF(off64_t offset)
00127 {
00128   LARGE_INTEGER liDistanceToMove;
00129   
00130   liDistanceToMove.QuadPart = offset;
00131   if (!SetFilePointerEx(sf_fh, liDistanceToMove, NULL, FILE_BEGIN)) 
00132     CSException::throwFileError(CS_CONTEXT, sf_path->getCString(), get_win_error());
00133 
00134   if (!SetEndOfFile(sf_fh)) 
00135     CSException::throwFileError(CS_CONTEXT, sf_path->getCString(), get_win_error());
00136 }
00137 
00138 //--------------
00139 off64_t CSSysFile::sf_getEOF()
00140 {
00141   DWORD     result;
00142   LARGE_INTEGER lpFileSize;
00143 
00144   result = SetFilePointer(sf_fh, 0, NULL, FILE_END);
00145   if (result == 0xFFFFFFFF)  
00146     CSException::throwFileError(CS_CONTEXT, sf_path->getCString(), get_win_error());
00147 
00148   if (!GetFileSizeEx(sf_fh, &lpFileSize))  
00149     CSException::throwFileError(CS_CONTEXT, sf_path->getCString(), get_win_error());
00150 
00151   return lpFileSize.QuadPart;
00152 }
00153 
00154 //--------------
00155 void CSSysFile::sf_sync()
00156 {
00157   if (!FlushFileBuffers(sf_fh))  
00158     CSException::throwFileError(CS_CONTEXT, sf_path->getCString(), get_win_error());
00159 }
00160 
00161 //--------------
00162 void CSSysFile::sf_lock(bool shared)
00163 {
00164   OVERLAPPED overlap = {0};
00165   
00166   if (!LockFileEx(sf_fh, (shared)? 0: LOCKFILE_EXCLUSIVE_LOCK, 0, 512, 0, &overlap))  
00167     CSException::throwFileError(CS_CONTEXT, sf_path->getCString(), get_win_error());
00168 }
00169 
00170 //--------------
00171 void CSSysFile::sf_unlock()
00172 {
00173   OVERLAPPED overlap = {0};
00174 
00175   if (!UnlockFileEx(sf_fh, 0, 512, 0, &overlap))  
00176     CSException::throwFileError(CS_CONTEXT, sf_path->getCString(), get_win_error());
00177 }
00178 
00179 //=====================
00180 // CSSys
00181 //=====================
00182 //--------------
00183 bool CSSys::sys_exists(const char *path)
00184 {
00185    return (access(path, 0) != -1);
00186 }
00187 
00188 //--------------
00189 void CSSys::sys_getcwd(char *path, size_t size)
00190 {
00191   DWORD len;
00192 
00193   len = GetCurrentDirectoryA(size, path);
00194   if (len == 0)
00195     CSException::throwFileError(CS_CONTEXT, "GetCurrentDirectory()" , get_win_error());
00196   else if (len > (size -1))
00197     CSException::throwFileError(CS_CONTEXT, "GetCurrentDirectory()overflow " , len);
00198 
00199 }
00200 
00201 //--------------
00202 void CSSys::sys_setcwd(const char *path)
00203 {
00204   if (!SetCurrentDirectoryA(path))
00205     CSException::throwFileError(CS_CONTEXT, "SetCurrentDirectory()" , get_win_error());
00206 }
00207 
00208 //--------------
00209 void CSSys::sys_makeDir(const char *path)
00210 {
00211   SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), 0, 0 };
00212 
00213   if (!CreateDirectoryA(path, &sa))
00214     CSException::throwFileError(CS_CONTEXT, path, get_win_error());
00215 
00216 }
00217 
00218 #define FILE_NOT_FOUND(x)   ((x) == ERROR_FILE_NOT_FOUND || (x) == ERROR_PATH_NOT_FOUND)
00219 //--------------
00220 void CSSys::sys_removeDir(const char *path)
00221 {
00222   if (!RemoveDirectoryA(path)) {
00223     int err = get_win_error();
00224 
00225     if (!FILE_NOT_FOUND(err)) 
00226       CSException::throwFileError(CS_CONTEXT, path, err);
00227   }
00228 }
00229 
00230 //--------------
00231 void CSSys::sys_removeFile(const char *path)
00232 {
00233   if (!DeleteFileA(path)) {
00234     int err = get_win_error();
00235 
00236     if (!FILE_NOT_FOUND(err)) 
00237       CSException::throwFileError(CS_CONTEXT, path, err);
00238   }
00239 }
00240 
00241 
00242 //--------------
00243 
00244 void CSSys::sys_stat(const char *path, bool *is_dir, off64_t *size, CSTime *mod_time)
00245 {
00246   HANDLE            fh;
00247   BY_HANDLE_FILE_INFORMATION  info;
00248   SECURITY_ATTRIBUTES     sa = { sizeof(SECURITY_ATTRIBUTES), 0, 0 };
00249 
00250   fh = CreateFileA(
00251     path,
00252     0,
00253     FILE_SHARE_READ,
00254     &sa,
00255     OPEN_EXISTING,
00256     FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, // FILE_FLAG_BACKUP_SEMANTICS allows you to open directories.
00257     NULL);
00258     
00259   if (fh == INVALID_HANDLE_VALUE) {
00260     CSException::throwFileError(CS_CONTEXT, path, get_win_error());
00261   }
00262 
00263   if (!GetFileInformationByHandle(fh, &info)) {
00264     CloseHandle(fh);
00265     CSException::throwFileError(CS_CONTEXT, path, get_win_error());
00266   }
00267 
00268   CloseHandle(fh);
00269   if (is_dir)
00270     *is_dir = ((info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY);
00271 
00272   if (size)
00273     *size = (off64_t) info.nFileSizeLow | (((off64_t) info.nFileSizeHigh) << 32);
00274     
00275   if (mod_time) {
00276     SYSTEMTIME st;
00277     FileTimeToSystemTime(&info.ftLastWriteTime, &st);
00278     mod_time->setUTC(st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds * 1000000);
00279   }
00280 
00281 }
00282 
00283 //--------------
00284 bool CSSys::sys_isLink(const char *path)
00285 {
00286   CSException::throwFileError(CS_CONTEXT, "CSSys::sys_isLink() not implimented on windows.", -1);
00287   return false; 
00288 }
00289 
00290 //--------------
00291 void CSSys::sys_rename(const char *old_path, const char *new_path)
00292 {
00293    if (rename(old_path, new_path) == -1)
00294     CSException::throwFileError(CS_CONTEXT, old_path, errno);
00295 }
00296 
00297 //--------------
00298 uint32_t CSSys::sys_getpid()
00299 {
00300   return GetCurrentProcessId();
00301 }
00302 
00303 //--------------
00304 bool CSSys::sys_isAlive(uint32_t pid)
00305 {
00306   HANDLE h;
00307   bool isAlive = false;
00308   DWORD code;
00309 
00310   h = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
00311   if (h) {
00312     if (GetExitCodeProcess(h, &code) && (code == STILL_ACTIVE))
00313       isAlive = true;
00314       
00315     CloseHandle(h);
00316   } else {
00317     int err;
00318 
00319     err = HRESULT_CODE(GetLastError());
00320     if (err != ERROR_INVALID_PARAMETER)
00321       isAlive = true;
00322     else
00323       fprintf(stderr, "ERROR CSSys::sys_isAlive(%d):OpenProcess %d\n", pid, err);
00324   }
00325 
00326   return(isAlive);  
00327 }
00328 
00329 
00330 
00331 //=====================
00332 // CSSysDir
00333 //=====================
00334 CSSysDir::~CSSysDir()
00335 {
00336   close();
00337   if (sd_path)
00338     sd_path->release();
00339     
00340   if (sd_filter)
00341     sd_filter->release();
00342 }
00343 
00344 //--------------
00345 void CSSysDir::open()
00346 {
00347   enter_();
00348 
00349   if (! CSSys::sys_exists(sd_path->getCString()))
00350     CSException::throwFileError(CS_CONTEXT, sd_path->getCString(), ERROR_PATH_NOT_FOUND);
00351 
00352   sd_filter = new CSStringBuffer();
00353   sd_filter->append(sd_path->getCString());
00354 
00355   if (IS_DIR_CHAR(*(sd_filter->getBuffer(sd_filter->length()-1))))
00356     sd_filter->append("*");
00357   else
00358     sd_filter->append(CS_DIR_DELIM"*");
00359 
00360   exit_();
00361 }
00362 
00363 //--------------
00364 void CSSysDir::close()
00365 {
00366   if (sd_dir != INVALID_HANDLE_VALUE) {
00367     FindClose(sd_dir);
00368     sd_dir = INVALID_HANDLE_VALUE;
00369   }
00370 }
00371 
00372 //--------------
00373 bool CSSysDir::next()
00374 {
00375   int err = 0;
00376 
00377   while (true) {
00378     if (sd_dir == INVALID_HANDLE_VALUE) {
00379       sd_dir = FindFirstFileA(sd_filter->getCString(), &sd_entry);
00380       if (sd_dir == INVALID_HANDLE_VALUE)
00381         err = get_win_error();
00382     }
00383     else {
00384       if (!FindNextFileA(sd_dir, &sd_entry))
00385         err = get_win_error();
00386     }
00387 
00388     if (err) {
00389       if ((err != ERROR_NO_MORE_FILES) && (err != ERROR_FILE_NOT_FOUND)){
00390         CSException::throwFileError(CS_CONTEXT, sd_path->getCString(), err);
00391       }
00392       return false;
00393     }
00394 
00395     /* Filter out '.' and '..': */
00396     if (sd_entry.cFileName[0] == '.') {
00397       if (sd_entry.cFileName[1] == '.') {
00398         if (sd_entry.cFileName[2] == '\0')
00399           continue;
00400       }
00401       else {
00402         if (sd_entry.cFileName[1] == '\0')
00403           continue;
00404       }
00405     }
00406     break;
00407   }
00408 
00409   return true;
00410 }
00411 
00412 
00413 //--------------
00414 void CSSysDir::getEntryPath(char *path, size_t size)
00415 {
00416   cs_strcpy(size, path, sd_path->getCString());
00417   cs_add_dir_char(size, path);
00418   cs_strcat(size, path, entryName());
00419 }
00420 
00421 //--------------
00422 const char *CSSysDir::entryName()
00423 {
00424   return (const char*) sd_entry.cFileName;
00425 }
00426 
00427 //--------------
00428 bool CSSysDir::entryIsFile()
00429 {
00430   if (sd_entry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
00431     return false;
00432   return true;
00433 }
00434 
00436 // A windows version of gettimeofday() as taken from:
00437 // http://www.suacommunity.com/dictionary/gettimeofday-entry.php
00438 
00439 #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
00440   #define DELTA_EPOCH_IN_MICROSECS  11644473600000000Ui64
00441 #else
00442   #define DELTA_EPOCH_IN_MICROSECS  11644473600000000ULL
00443 #endif
00444  
00445 struct timezone
00446 {
00447   int  tz_minuteswest; /* minutes W of Greenwich */
00448   int  tz_dsttime;     /* type of dst correction */
00449 };
00450  
00451 // Definition of a gettimeofday function
00452  
00453 int gettimeofday(struct timeval *tv, struct timezone *tz)
00454 {
00455 // Define a structure to receive the current Windows filetime
00456   FILETIME ft;
00457  
00458 // Initialize the present time to 0 and the timezone to UTC
00459   unsigned __int64 tmpres = 0;
00460   static int tzflag = 0;
00461  
00462   if (NULL != tv)
00463   {
00464     GetSystemTimeAsFileTime(&ft);
00465  
00466 // The GetSystemTimeAsFileTime returns the number of 100 nanosecond 
00467 // intervals since Jan 1, 1601 in a structure. Copy the high bits to 
00468 // the 64 bit tmpres, shift it left by 32 then or in the low 32 bits.
00469     tmpres |= ft.dwHighDateTime;
00470     tmpres <<= 32;
00471     tmpres |= ft.dwLowDateTime;
00472  
00473 // Convert to microseconds by dividing by 10
00474     tmpres /= 10;
00475  
00476 // The Unix epoch starts on Jan 1 1970.  Need to subtract the difference 
00477 // in seconds from Jan 1 1601.
00478     tmpres -= DELTA_EPOCH_IN_MICROSECS;
00479  
00480 // Finally change microseconds to seconds and place in the seconds value. 
00481 // The modulus picks up the microseconds.
00482     tv->tv_sec = (long)(tmpres / 1000000UL);
00483     tv->tv_usec = (long)(tmpres % 1000000UL);
00484   }
00485  
00486   if (NULL != tz)
00487   {
00488     if (!tzflag)
00489     {
00490       _tzset();
00491       tzflag++;
00492     }
00493   
00494 // Adjust for the timezone west of Greenwich
00495       tz->tz_minuteswest = _timezone / 60;
00496     tz->tz_dsttime = _daylight;
00497   }
00498  
00499   return 0;
00500 }
00501