0022651: Impossible to build OCC as static library due to using Standard_EXPORT inste...
[occt.git] / src / OSD / OSD_Directory.cxx
1 // Copyright (c) 1998-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #include <OSD_Directory.hxx>
16
17 #include <OSD_Path.hxx>
18 #include <OSD_Protection.hxx>
19 #include <OSD_WhoAmI.hxx>
20 #include <Standard_ProgramError.hxx>
21 #include <TCollection_ExtendedString.hxx>
22 #include <NCollection_String.hxx>
23
24 #ifdef _WIN32
25   #include <OSD_WNT.hxx>
26   #include <stdio.h>
27
28   #ifndef _INC_TCHAR
29     #include <tchar.h>
30   #endif
31
32   void _osd_wnt_set_error (OSD_Error&, OSD_WhoAmI, ... );
33 #else
34   #include <errno.h>
35   #include <stdio.h>
36   #include <sys/stat.h>
37   #include <unistd.h>
38
39   const OSD_WhoAmI Iam = OSD_WDirectory;
40 #endif
41
42 // =======================================================================
43 // function : OSD_Directory
44 // purpose  :
45 // =======================================================================
46 OSD_Directory::OSD_Directory()
47 {
48   //
49 }
50
51 // =======================================================================
52 // function : OSD_Directory
53 // purpose  :
54 // =======================================================================
55 OSD_Directory::OSD_Directory (const OSD_Path& theName)
56 : OSD_FileNode (theName)
57 {
58   //
59 }
60
61 // =======================================================================
62 // function : Build
63 // purpose  :
64 // =======================================================================
65 void OSD_Directory::Build (const OSD_Protection& theProtect)
66 {
67 #ifdef _WIN32
68   TCollection_AsciiString aDirName;
69   myPath.SystemName (aDirName);
70   if (aDirName.IsEmpty())
71   {
72     throw Standard_ProgramError ( "OSD_Directory::Build(): incorrect call - no directory name");
73   }
74
75   Standard_Boolean isOK = Exists();
76   if (!isOK)
77   {
78     // myError will be set to fail by Exists() if intermediate dirs do not exist
79     myError.Reset();
80
81     // create directory if it does not exist;
82     TCollection_ExtendedString aDirNameW (aDirName);
83     if (CreateDirectoryW (aDirNameW.ToWideString(), NULL))
84     {
85       isOK = Standard_True;
86     }
87     // if failed due to absence of intermediate directories, create them recursively
88     else if (GetLastError() == ERROR_PATH_NOT_FOUND)
89     {
90       OSD_Path aSupPath = myPath;
91       aSupPath.UpTrek();
92       aSupPath.SetName (myPath.TrekValue (myPath.TrekLength())); // incredible, but required!
93       OSD_Directory aSupDir (aSupPath);
94       aSupDir.Build (theProtect);
95       if (aSupDir.Failed())
96       {
97         myError = aSupDir.myError;
98         return;
99       }
100       isOK = (CreateDirectoryW (aDirNameW.ToWideString(), NULL) != 0);
101     }
102   }
103
104   if (isOK)
105   {
106 #ifndef OCCT_UWP
107     SetProtection (theProtect);
108 #else
109     (void)theProtect;
110 #endif
111   }
112   else
113   {
114     _osd_wnt_set_error (myError, OSD_WDirectory);
115   }
116 #else
117   TCollection_AsciiString aBuffer;
118   mode_t anInternalProt = (mode_t )theProtect.Internal();
119   myPath.SystemName (aBuffer);
120   umask (0);
121   int aStatus = mkdir (aBuffer.ToCString(), anInternalProt);
122   if (aStatus == -1 && errno == ENOENT)
123   {
124     OSD_Path aSupPath = myPath;
125     aSupPath.UpTrek();
126     aSupPath.SetName (myPath.TrekValue (myPath.TrekLength())); // incredible, but required!
127     OSD_Directory aSupDir (aSupPath);
128     aSupDir.Build (theProtect);
129     if (aSupDir.Failed())
130     {
131       myError = aSupDir.myError;
132       return;
133     }
134     aStatus = mkdir (aBuffer.ToCString(), anInternalProt);
135   }
136   if (aStatus == -1 && errno != EEXIST)
137   {
138     char anErrMsg[2048];
139     Sprintf (anErrMsg, "OSD_Directory::Build Directory \"%.2000s\"", aBuffer.ToCString());
140     myError.SetValue (errno, Iam, anErrMsg);
141   }
142 #endif
143 }
144
145 // =======================================================================
146 // function : BuildTemporary
147 // purpose  :
148 // =======================================================================
149 OSD_Directory OSD_Directory::BuildTemporary()
150 {
151 #ifdef _WIN32
152   wchar_t* aTmpNameW = _wtmpnam (NULL);
153   if (aTmpNameW == NULL)
154   {
155     return OSD_Directory();
156   }
157
158   TCollection_AsciiString aTmpName (aTmpNameW);
159   OSD_Path aDirPath (aTmpName);
160   OSD_Directory aDir;
161   aDir.SetPath (aDirPath);
162   aDir.Build (OSD_Protection());
163   return aDir;
164 #else
165   // create a temporary directory with 0700 permissions
166   char aTmpName[] = "/tmp/CSFXXXXXX";
167   if (NULL == mkdtemp (aTmpName))
168   {
169     return OSD_Directory(); // can't create a directory
170   }
171
172   unlink (aTmpName); // destroys link but directory still exists while current process lives
173   OSD_Directory aDir;
174   aDir.SetPath (TCollection_AsciiString (aTmpName));
175   return aDir;
176 #endif
177 }