// Copyright (c) 1998-1999 Matra Datavision // Copyright (c) 1999-2014 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // // This library is free software; you can redistribute it and/or modify it under // the terms of the GNU Lesser General Public License version 2.1 as published // by the Free Software Foundation, with special exception defined in the file // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT // distribution for complete text of the license and disclaimer of any warranty. // // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. #ifndef _WIN32 //---------------------------------------------------------------------------- //------------------- Linux Sources of OSD_FileNode -------------------------- //---------------------------------------------------------------------------- #include #include #include #include #include #include #include #include #include #include #include #include #include #include // For "system" const OSD_WhoAmI Iam = OSD_WFileNode; // Create a file/directory object OSD_FileNode::OSD_FileNode() {} // Create and initialize a file/directory object OSD_FileNode::OSD_FileNode(const OSD_Path& Name) { SetPath(Name); } // Get values of object void OSD_FileNode::Path(OSD_Path& Name) const { Name = myPath; } // Set values of object void OSD_FileNode::SetPath(const OSD_Path& Name) { myError.Reset(); myPath = Name; } // Test if specified file/directory exists Standard_Boolean OSD_FileNode::Exists() { int status; // if (myPath.Name().Length()==0) A directory can have a null name field (ex: root) // throw OSD_OSDError("OSD_FileNode::Exists : no name was given"); (LD) // if (Failed()) Perror(); TCollection_AsciiString aBuffer; myPath.SystemName(aBuffer); status = access(aBuffer.ToCString(), F_OK); if (status == 0) return (Standard_True); else return (Standard_False); } // Physically remove a file/directory void OSD_FileNode::Remove() { // if (myPath.Name().Length()==0) A directory can have a null name field (ex: root) // throw OSD_OSDError("OSD_FileNode::Remove : no name was given"); (LD) // if (Failed()) Perror(); TCollection_AsciiString aBuffer; myPath.SystemName(aBuffer); if (access(aBuffer.ToCString(), W_OK)) { myError.SetValue(errno, Iam, "Remove"); return; } struct stat stat_buf; if (stat(aBuffer.ToCString(), &stat_buf)) { myError.SetValue(errno, Iam, "Remove"); return; } if (S_ISDIR(stat_buf.st_mode)) { // DIRECTORY if (rmdir(aBuffer.ToCString())) { myError.SetValue(errno, Iam, "Remove"); return; } return; } else if (S_ISREG(stat_buf.st_mode) || S_ISLNK(stat_buf.st_mode) || S_ISFIFO(stat_buf.st_mode)) { if (unlink(aBuffer.ToCString()) == -1) myError.SetValue(errno, Iam, "Remove"); return; } myError.SetValue(EINVAL, Iam, "Remove"); return; } // Move a file/directory to another path void OSD_FileNode::Move(const OSD_Path& NewPath) { int status; TCollection_AsciiString thisPath; // if (myPath.Name().Length()==0) // throw OSD_OSDError("OSD_FileNode::Move : no name was given"); // if (Failed()) Perror(); NewPath.SystemName(thisPath); // Get internal path name TCollection_AsciiString aBuffer; myPath.SystemName(aBuffer); status = rename(aBuffer.ToCString(), thisPath.ToCString()); if (status == -1) myError.SetValue(errno, Iam, "Move"); } // Copy a file to another path and name int static copy_file(const char* src, const char* trg) { int err = 0; errno = 0; int fds = open(src, O_RDONLY); if (fds < 0) return errno; int fdo = open(trg, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (fdo < 0) { err = errno; close(fds); return err; } const int BUFSIZE = 4096; char buf[BUFSIZE]; int n = 0; while ((n = (int)read(fds, buf, BUFSIZE)) > 0) { if (write(fdo, buf, n) != n) { // writing error if (!errno) { errno = ENOSPC; } break; } } err = errno; close(fdo); if (!err) err = errno; close(fds); if (!err) err = errno; return err; } void OSD_FileNode::Copy(const OSD_Path& ToPath) { int status; TCollection_AsciiString second_name; // if (myPath.Name().Length()==0) Copy .login would raise !! // throw OSD_OSDError("OSD_FileNode::Copy : no name was given"); // if (Failed()) Perror(); ToPath.SystemName(second_name); TCollection_AsciiString aBuffer; myPath.SystemName(aBuffer); status = copy_file(aBuffer.ToCString(), second_name.ToCString()); if (status != 0) myError.SetValue(-1, Iam, "Copy failed"); // (LD) #ifdef OCCT_DEBUG printf("Status %d : errno # %d\n", status, errno); #endif } // Get protections of a file/directory OSD_Protection OSD_FileNode::Protection() { OSD_Protection thisProt; struct stat myStat; int status; int s, u, g, w; // if (myPath.Name().Length()==0) // throw OSD_OSDError("OSD_FileNode::Protection : no name was given"); // if (Failed()) Perror(); TCollection_AsciiString aBuffer; myPath.SystemName(aBuffer); status = stat(aBuffer.ToCString(), &myStat); if (status == -1) myError.SetValue(errno, Iam, "Protection"); u = g = w = OSD_None; if (myStat.st_mode & S_IRUSR) u |= OSD_R; if (myStat.st_mode & S_IWUSR) u |= OSD_W; if (myStat.st_mode & S_IXUSR) u |= OSD_X; if (myStat.st_mode & S_IRGRP) g |= OSD_R; if (myStat.st_mode & S_IWGRP) g |= OSD_W; if (myStat.st_mode & S_IXGRP) g |= OSD_X; if (myStat.st_mode & S_IROTH) w |= OSD_R; if (myStat.st_mode & S_IWOTH) w |= OSD_W; if (myStat.st_mode & S_IXOTH) w |= OSD_X; s = g; thisProt.SetValues((OSD_SingleProtection)s, (OSD_SingleProtection)u, (OSD_SingleProtection)g, (OSD_SingleProtection)w); return (thisProt); } // Set protections of a file/directory void OSD_FileNode::SetProtection(const OSD_Protection& Prot) { int status; // if (myPath.Name().Length()==0) // throw OSD_OSDError("OSD_FileNode::SetProtection : no name was given"); // if (Failed()) Perror(); TCollection_AsciiString aBuffer; myPath.SystemName(aBuffer); status = chmod(aBuffer.ToCString(), (mode_t)Prot.Internal()); if (status == -1) myError.SetValue(errno, Iam, "SetProtection"); } // return the date of last access of file/directory Quantity_Date OSD_FileNode::CreationMoment() { Quantity_Date result; struct tm* decode; struct stat buffer; // if (myPath.Name().Length()==0) // throw OSD_OSDError("OSD_FileNode::CreationMoment : no name was given"); // if (Failed()) Perror(); /* Get File Information */ TCollection_AsciiString aBuffer; myPath.SystemName(aBuffer); if (!stat(aBuffer.ToCString(), &buffer)) { time_t aTime = (time_t)buffer.st_ctime; decode = localtime(&aTime); result.SetValues(decode->tm_mon + 1, decode->tm_mday, decode->tm_year + 1900, decode->tm_hour, decode->tm_min, decode->tm_sec, 0, 0); } else result.SetValues(1, 1, 1979, 0, 0, 0, 0, 0); return (result); } // return Last access of file/directory Quantity_Date OSD_FileNode::AccessMoment() { Quantity_Date result; struct tm* decode; struct stat buffer; // if (myPath.Name().Length()==0) // throw OSD_OSDError("OSD_FileNode::AccessMoment : no name was given"); // if (Failed()) Perror(); /* Get File Information */ TCollection_AsciiString aBuffer; myPath.SystemName(aBuffer); if (!stat(aBuffer.ToCString(), &buffer)) { time_t aTime = (time_t)buffer.st_ctime; decode = localtime(&aTime); result.SetValues(decode->tm_mon + 1, decode->tm_mday, decode->tm_year + 1900, decode->tm_hour, decode->tm_min, decode->tm_sec, 0, 0); } else result.SetValues(1, 1, 1979, 0, 0, 0, 0, 0); return (result); } void OSD_FileNode::Reset() { myError.Reset(); } Standard_Boolean OSD_FileNode::Failed() const { return (myError.Failed()); } void OSD_FileNode::Perror() { myError.Perror(); } Standard_Integer OSD_FileNode::Error() const { return (myError.Error()); } #else /* _WIN32 */ //---------------------------------------------------------------------------- //------------------- WNT Sources of OSD_FileNode --------------------------- //---------------------------------------------------------------------------- #ifdef NONLS #undef NONLS #endif #include #include #include #include #include #include #include #ifndef _INC_TCHAR #include #endif // _INC_TCHAR #include #define TEST_RAISE(arg) _test_raise(fName, (arg)) #define RAISE(arg) throw Standard_ProgramError((arg)) #ifndef OCCT_UWP // None of the existing security APIs are supported in a UWP applications PSECURITY_DESCRIPTOR __fastcall _osd_wnt_protection_to_sd(const OSD_Protection&, BOOL, const wchar_t*); BOOL __fastcall _osd_wnt_sd_to_protection(PSECURITY_DESCRIPTOR pSD, OSD_Protection& prot, BOOL); #endif Standard_Integer __fastcall _get_file_type(Standard_CString, HANDLE); void _osd_wnt_set_error(OSD_Error&, Standard_Integer, ...); static BOOL __fastcall _get_file_time(const wchar_t*, LPSYSTEMTIME, BOOL); static void __fastcall _test_raise(TCollection_AsciiString, Standard_CString); //======================================================================= // function : OSD_FileNode // purpose : Empty Constructor //======================================================================= OSD_FileNode::OSD_FileNode() {} //================================================================================================= OSD_FileNode::OSD_FileNode(const OSD_Path& Name) { myPath = Name; } // end constructor ( 2 ) //================================================================================================= void OSD_FileNode::Path(OSD_Path& Name) const { Name = myPath; } // end OSD_FileNode :: Path //================================================================================================= void OSD_FileNode::SetPath(const OSD_Path& Name) { myPath = Name; } // end OSD_FileNode :: SetPath //================================================================================================= Standard_Boolean OSD_FileNode::Exists() { myError.Reset(); Standard_Boolean retVal = Standard_False; TCollection_AsciiString fName; myPath.SystemName(fName); if (fName.IsEmpty()) return Standard_False; TEST_RAISE("Exists"); // make wide character string from UTF-8 TCollection_ExtendedString fNameW(fName); WIN32_FILE_ATTRIBUTE_DATA aFileInfo; if (!GetFileAttributesExW(fNameW.ToWideString(), GetFileExInfoStandard, &aFileInfo)) { if (GetLastError() != ERROR_FILE_NOT_FOUND) { _osd_wnt_set_error(myError, OSD_WFileNode, fNameW.ToWideString()); } } else { retVal = Standard_True; } return retVal; } // end OSD_FileNode :: Exists //================================================================================================= void OSD_FileNode::Remove() { TCollection_AsciiString fName; myPath.SystemName(fName); TCollection_ExtendedString fNameW(fName); TEST_RAISE("Remove"); switch (_get_file_type(fName.ToCString(), INVALID_HANDLE_VALUE)) { case FLAG_FILE: if (!DeleteFileW(fNameW.ToWideString())) _osd_wnt_set_error(myError, OSD_WFileNode, fNameW.ToWideString()); break; case FLAG_DIRECTORY: // LD : Suppression de l'appel a DeleteDirectory pour // ne pas detruire un repertoire no vide. if (!RemoveDirectoryW(fNameW.ToWideString())) _osd_wnt_set_error(myError, OSD_WFileNode, fNameW.ToWideString()); break; default: RAISE("OSD_FileNode :: Remove (): invalid file type - neither file nor directory"); } // end switch } // end OSD_FileNode :: Remove //================================================================================================= void OSD_FileNode::Move(const OSD_Path& NewPath) { TCollection_AsciiString fName; TCollection_AsciiString fNameDst; myPath.SystemName(fName); TCollection_ExtendedString fNameW(fName); TEST_RAISE("Move"); NewPath.SystemName(fNameDst); TCollection_ExtendedString fNameDstW(fNameDst); switch (_get_file_type(fName.ToCString(), INVALID_HANDLE_VALUE)) { case FLAG_FILE: if (!MoveFileExW(fNameW.ToWideString(), fNameDstW.ToWideString(), MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED)) _osd_wnt_set_error(myError, OSD_WFileNode, fNameW.ToWideString(), fNameDstW.ToWideString()); break; case FLAG_DIRECTORY: if (!MoveDirectory(fNameW.ToWideString(), fNameDstW.ToWideString())) _osd_wnt_set_error(myError, OSD_WFileNode, fNameW.ToWideString(), fNameDstW.ToWideString()); break; default: RAISE("OSD_FileNode :: Move (): invalid file type - neither file nor directory"); } // end switch } // end OSD_FileNode :: Move //================================================================================================= void OSD_FileNode::Copy(const OSD_Path& ToPath) { TCollection_AsciiString fName; TCollection_AsciiString fNameDst; myPath.SystemName(fName); TCollection_ExtendedString fNameW(fName); TEST_RAISE("Copy"); ToPath.SystemName(fNameDst); TCollection_ExtendedString fNameDstW(fNameDst); switch (_get_file_type(fName.ToCString(), INVALID_HANDLE_VALUE)) { case FLAG_FILE: #ifndef OCCT_UWP if (!CopyFileW(fNameW.ToWideString(), fNameDstW.ToWideString(), FALSE)) #else if (CopyFile2(fNameW.ToWideString(), fNameDstW.ToWideString(), FALSE) != S_OK) #endif _osd_wnt_set_error(myError, OSD_WFileNode, fNameW.ToWideString(), fNameDstW.ToWideString()); break; case FLAG_DIRECTORY: if (!CopyDirectory(fNameW.ToWideString(), fNameDstW.ToWideString())) _osd_wnt_set_error(myError, OSD_WFileNode, fNameW.ToWideString(), fNameDstW.ToWideString()); break; default: RAISE("OSD_FileNode :: Copy (): invalid file type - neither file nor directory"); } // end switch } // end OSD_FileNode :: Copy // None of the existing security APIs are supported in a UWP applications #ifndef OCCT_UWP //================================================================================================= OSD_Protection OSD_FileNode::Protection() { OSD_Protection retVal; TCollection_AsciiString fName; PSECURITY_DESCRIPTOR pSD; myPath.SystemName(fName); TCollection_ExtendedString fNameW(fName); TEST_RAISE("Protection"); if ((pSD = GetFileSecurityEx(fNameW.ToWideString(), DACL_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION)) == NULL || !_osd_wnt_sd_to_protection(pSD, retVal, _get_file_type(fName.ToCString(), INVALID_HANDLE_VALUE) == FLAG_DIRECTORY)) _osd_wnt_set_error(myError, OSD_WFileNode); if (pSD != NULL) FreeFileSecurity(pSD); return retVal; } // end OSD_FileNode :: Protection //================================================================================================= void OSD_FileNode::SetProtection(const OSD_Protection& Prot) { TCollection_AsciiString fName; PSECURITY_DESCRIPTOR pSD; myPath.SystemName(fName); TCollection_ExtendedString fNameW(fName); TEST_RAISE("SetProtection"); pSD = _osd_wnt_protection_to_sd(Prot, _get_file_type(fName.ToCString(), INVALID_HANDLE_VALUE) == FLAG_DIRECTORY, fNameW.ToWideString()); if (pSD == NULL || !SetFileSecurityW(fNameW.ToWideString(), DACL_SECURITY_INFORMATION, pSD)) _osd_wnt_set_error(myError, OSD_WFileNode, fNameW.ToWideString()); if (pSD != NULL) FreeSD(pSD); } // end OSD_FileNode :: SetProtection #else /* UWP stub */ #include //================================================================================================= OSD_Protection OSD_FileNode::Protection() { TCollection_AsciiString fName; myPath.SystemName(fName); TCollection_ExtendedString fNameW(fName); OSD_SingleProtection aProt = OSD_None; if (_waccess_s(fNameW.ToWideString(), 6)) aProt = OSD_RW; else if (_waccess_s(fNameW.ToWideString(), 2)) aProt = OSD_W; else if (_waccess_s(fNameW.ToWideString(), 4)) aProt = OSD_R; // assume full access for system and none for everybody OSD_Protection retVal(OSD_RWXD, aProt, aProt, OSD_None); return retVal; } // end OSD_FileNode :: Protection //================================================================================================= void OSD_FileNode::SetProtection(const OSD_Protection& /*Prot*/) { } // end OSD_FileNode :: SetProtection #endif //================================================================================================= Quantity_Date OSD_FileNode::AccessMoment() { Quantity_Date retVal; SYSTEMTIME stAccessMoment; SYSTEMTIME stAccessSystemMoment; TCollection_AsciiString fName; myPath.SystemName(fName); TCollection_ExtendedString fNameW(fName); TEST_RAISE("AccessMoment"); if (_get_file_time(fNameW.ToWideString(), &stAccessSystemMoment, TRUE)) { SYSTEMTIME* aSysTime = &stAccessMoment; BOOL aFlag = SystemTimeToTzSpecificLocalTime(NULL, &stAccessSystemMoment, &stAccessMoment); if (aFlag == 0) // AGV: test for success (e.g., unsupported on Win95/98) aSysTime = &stAccessSystemMoment; retVal.SetValues(aSysTime->wMonth, aSysTime->wDay, aSysTime->wYear, aSysTime->wHour, aSysTime->wMinute, aSysTime->wSecond, aSysTime->wMilliseconds); } else { _osd_wnt_set_error(myError, OSD_WFileNode, fNameW.ToWideString()); } return retVal; } // end OSD_FileNode :: AccessMoment //================================================================================================= Quantity_Date OSD_FileNode::CreationMoment() { Quantity_Date retVal; SYSTEMTIME stCreationMoment; SYSTEMTIME stCreationSystemMoment; TCollection_AsciiString fName; myPath.SystemName(fName); TCollection_ExtendedString fNameW(fName); TEST_RAISE("CreationMoment"); if (_get_file_time(fNameW.ToWideString(), &stCreationSystemMoment, FALSE)) { SYSTEMTIME* aSysTime = &stCreationMoment; BOOL aFlag = SystemTimeToTzSpecificLocalTime(NULL, &stCreationSystemMoment, &stCreationMoment); if (aFlag == 0) // AGV: test for success (e.g., unsupported on Win95/98) aSysTime = &stCreationSystemMoment; retVal.SetValues(aSysTime->wMonth, aSysTime->wDay, aSysTime->wYear, aSysTime->wHour, aSysTime->wMinute, aSysTime->wSecond, aSysTime->wMilliseconds); } else { _osd_wnt_set_error(myError, OSD_WFileNode, fNameW.ToWideString()); } return retVal; } // end OSD_FileNode :: CreationMoment //================================================================================================= Standard_Boolean OSD_FileNode::Failed() const { return myError.Failed(); } // end OSD_FileNode :: Failed //================================================================================================= void OSD_FileNode::Reset() { myError.Reset(); } // end OSD_FileNode :: Reset //================================================================================================= void OSD_FileNode::Perror() { myError.Perror(); } // end OSD_FileNode :: Perror //================================================================================================= Standard_Integer OSD_FileNode::Error() const { return myError.Error(); } // end OSD_FileNode :: Error void _osd_wnt_set_error(OSD_Error& err, Standard_Integer who, ...) { DWORD errCode; wchar_t buffer[2048]; va_list arg_ptr; va_start(arg_ptr, who); errCode = GetLastError(); if (!FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, 0, errCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), buffer, 2048, &arg_ptr)) { StringCchPrintfW(buffer, _countof(buffer), L"error code %d", (Standard_Integer)errCode); SetLastError(errCode); } // end if char aBufferA[2048]; WideCharToMultiByte(CP_UTF8, 0, buffer, -1, aBufferA, sizeof(aBufferA), NULL, NULL); err.SetValue(errCode, who, aBufferA); va_end(arg_ptr); } // end _set_error #if defined(__CYGWIN32__) || defined(__MINGW32__) #ifdef __try /* is defined on MinGw as either "try" or "if (true)" */ #undef __try #endif #define __try #define __finally #define __leave return retVal #endif static BOOL __fastcall _get_file_time(const wchar_t* fName, LPSYSTEMTIME lpSysTime, BOOL fAccess) { BOOL retVal = FALSE; FILETIME ftCreationTime; FILETIME ftLastWriteTime; LPFILETIME lpftPtr; HANDLE hFile = INVALID_HANDLE_VALUE; __try { #ifndef OCCT_UWP if ((hFile = CreateFileW(fName, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) #else CREATEFILE2_EXTENDED_PARAMETERS pCreateExParams = {}; pCreateExParams.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS); pCreateExParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; pCreateExParams.lpSecurityAttributes = NULL; pCreateExParams.hTemplateFile = NULL; if ((hFile = CreateFile2(fName, NULL, NULL, OPEN_EXISTING, &pCreateExParams)) == INVALID_HANDLE_VALUE) #endif __leave; if (!GetFileTime(hFile, &ftCreationTime, NULL, &ftLastWriteTime)) __leave; lpftPtr = fAccess ? &ftLastWriteTime : &ftCreationTime; if (!FileTimeToSystemTime(lpftPtr, lpSysTime)) __leave; retVal = TRUE; } // end __try __finally { if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile); } // end __finally return retVal; } // end _get_file_time #if defined(__CYGWIN32__) || defined(__MINGW32__) #undef __try #undef __finally #undef __leave #endif static void __fastcall _test_raise(TCollection_AsciiString fName, Standard_CString str) { if (fName.IsEmpty()) { TCollection_AsciiString buff = "OSD_FileNode :: "; buff += str; buff += " (): wrong access"; throw Standard_ProgramError(buff.ToCString()); } // end if } // end _test_raise #endif /* _WIN32 */