TrueCrypt  7.1
About: TrueCrypt is a software system for establishing and maintaining an on-the-fly-encrypted volume (data storage device).
  Fossies Dox: TrueCrypt-7.1a-Source.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)  

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
File.cpp
Go to the documentation of this file.
1 /*
2  Copyright (c) 2008-2010 TrueCrypt Developers Association. All rights reserved.
3 
4  Governed by the TrueCrypt License 3.0 the full text of which is contained in
5  the file License.txt included in TrueCrypt binary and source code distribution
6  packages.
7 */
8 
9 #include <errno.h>
10 #include <fcntl.h>
11 #include <unistd.h>
12 #include <utime.h>
13 
14 #ifdef TC_LINUX
15 #include <sys/mount.h>
16 #endif
17 
18 #ifdef TC_BSD
19 #include <sys/disk.h>
20 #endif
21 
22 #ifdef TC_SOLARIS
23 #include <stropts.h>
24 #include <sys/dkio.h>
25 #endif
26 
27 #include <sys/file.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 
31 #include "Platform/File.h"
32 #include "Platform/TextReader.h"
33 
34 namespace TrueCrypt
35 {
36 #if 0
37 # define TC_TRACE_FILE_OPERATIONS
38 
39  static void TraceFileOperation (int fileHandle, FilePath filePath, bool write, uint64 length, int64 position = -1)
40  {
41  string path = filePath;
42  if (path.empty() || path.find ("truecrypt_aux_mnt") != string::npos)
43  return;
44 
45  stringstream s;
46  s << path << ": " << (write ? "W " : "R ") << (position == -1 ? lseek (fileHandle, 0, SEEK_CUR) : position) << " (" << length << ")";
47  SystemLog::WriteError (s.str());
48  }
49 #endif
50 
51  void File::Close ()
52  {
54 
55  if (!SharedHandle)
56  {
57  close (FileHandle);
58  FileIsOpen = false;
59 
60  if ((mFileOpenFlags & File::PreserveTimestamps) && Path.IsFile())
61  {
62  struct utimbuf u;
63  u.actime = AccTime;
64  u.modtime = ModTime;
65 
66  try
67  {
68  throw_sys_sub_if (utime (string (Path).c_str(), &u) == -1, wstring (Path));
69  }
70  catch (...) // Suppress errors to allow using read-only files
71  {
72 #ifdef DEBUG
73  throw;
74 #endif
75  }
76  }
77  }
78  }
79 
80  void File::Delete ()
81  {
82  Close();
83  Path.Delete();
84  }
85 
86 
87  void File::Flush () const
88  {
90  throw_sys_sub_if (fsync (FileHandle) != 0, wstring (Path));
91  }
92 
94  {
95  if (Path.IsDevice())
96  {
97 #ifdef TC_LINUX
98  int blockSize;
99  throw_sys_sub_if (ioctl (FileHandle, BLKSSZGET, &blockSize) == -1, wstring (Path));
100  return blockSize;
101 
102 #elif defined (TC_MACOSX)
103  uint32 blockSize;
104  throw_sys_sub_if (ioctl (FileHandle, DKIOCGETBLOCKSIZE, &blockSize) == -1, wstring (Path));
105  return blockSize;
106 
107 #elif defined (TC_FREEBSD)
108  u_int sectorSize;
109  throw_sys_sub_if (ioctl (FileHandle, DIOCGSECTORSIZE, &sectorSize) == -1, wstring (Path));
110  return (uint32) sectorSize;
111 
112 #elif defined (TC_SOLARIS)
113  struct dk_minfo mediaInfo;
114  throw_sys_sub_if (ioctl (FileHandle, DKIOCGMEDIAINFO, &mediaInfo) == -1, wstring (Path));
115  return mediaInfo.dki_lbsize;
116 
117 #else
118 # error GetDeviceSectorSize()
119 #endif
120  }
121  else
122  throw ParameterIncorrect (SRC_POS);
123  }
124 
126  {
127 #ifdef TC_LINUX
128 
129  // HDIO_GETGEO ioctl is limited by the size of long
130  TextReader tr ("/sys/block/" + string (Path.ToHostDriveOfPartition().ToBaseName()) + "/" + string (Path.ToBaseName()) + "/start");
131 
132  string line;
133  tr.ReadLine (line);
135 
136 #elif defined (TC_MACOSX)
137 
138 #ifndef DKIOCGETBASE
139 # define DKIOCGETBASE _IOR('d', 73, uint64)
140 #endif
141  uint64 offset;
142  throw_sys_sub_if (ioctl (FileHandle, DKIOCGETBASE, &offset) == -1, wstring (Path));
143  return offset;
144 
145 #elif defined (TC_SOLARIS)
146 
147  struct extpart_info partInfo;
148  throw_sys_sub_if (ioctl (FileHandle, DKIOCEXTPARTINFO, &partInfo) == -1, wstring (Path));
149  return partInfo.p_start * GetDeviceSectorSize();
150 
151 #else
152  throw NotImplemented (SRC_POS);
153 #endif
154  }
155 
157  {
159 
160  // BSD does not support seeking to the end of a device
161 #ifdef TC_BSD
162  if (Path.IsBlockDevice() || Path.IsCharacterDevice())
163  {
164 # ifdef TC_MACOSX
165  uint32 blockSize;
166  uint64 blockCount;
167  throw_sys_sub_if (ioctl (FileHandle, DKIOCGETBLOCKSIZE, &blockSize) == -1, wstring (Path));
168  throw_sys_sub_if (ioctl (FileHandle, DKIOCGETBLOCKCOUNT, &blockCount) == -1, wstring (Path));
169  return blockCount * blockSize;
170 # else
171  uint64 mediaSize;
172  throw_sys_sub_if (ioctl (FileHandle, DIOCGMEDIASIZE, &mediaSize) == -1, wstring (Path));
173  return mediaSize;
174 # endif
175  }
176 #endif
177  off_t current = lseek (FileHandle, 0, SEEK_CUR);
178  throw_sys_sub_if (current == -1, wstring (Path));
179  SeekEnd (0);
180  uint64 length = lseek (FileHandle, 0, SEEK_CUR);
181  SeekAt (current);
182  return length;
183  }
184 
185  void File::Open (const FilePath &path, FileOpenMode mode, FileShareMode shareMode, FileOpenFlags flags)
186  {
187 #ifdef TC_LINUX
188  int sysFlags = O_LARGEFILE;
189 #else
190  int sysFlags = 0;
191 #endif
192 
193  switch (mode)
194  {
195  case CreateReadWrite:
196  sysFlags |= O_CREAT | O_TRUNC | O_RDWR;
197  break;
198 
199  case CreateWrite:
200  sysFlags |= O_CREAT | O_TRUNC | O_WRONLY;
201  break;
202 
203  case OpenRead:
204  sysFlags |= O_RDONLY;
205  break;
206 
207  case OpenWrite:
208  sysFlags |= O_WRONLY;
209  break;
210 
211  case OpenReadWrite:
212  sysFlags |= O_RDWR;
213  break;
214 
215  default:
216  throw ParameterIncorrect (SRC_POS);
217  }
218 
219  if ((flags & File::PreserveTimestamps) && path.IsFile())
220  {
221  struct stat statData;
222  throw_sys_sub_if (stat (string (path).c_str(), &statData) == -1, wstring (path));
223  AccTime = statData.st_atime;
224  ModTime = statData.st_mtime;
225  }
226 
227  FileHandle = open (string (path).c_str(), sysFlags, S_IRUSR | S_IWUSR);
228  throw_sys_sub_if (FileHandle == -1, wstring (path));
229 
230 #if 0 // File locking is disabled to avoid remote filesystem locking issues
231  try
232  {
233  struct flock fl;
234  memset (&fl, 0, sizeof (fl));
235  fl.l_whence = SEEK_SET;
236  fl.l_start = 0;
237  fl.l_len = 0;
238 
239  switch (shareMode)
240  {
241  case ShareNone:
242  fl.l_type = F_WRLCK;
243  if (fcntl (FileHandle, F_SETLK, &fl) == -1)
244  throw_sys_sub_if (errno == EAGAIN || errno == EACCES, wstring (path));
245  break;
246 
247  case ShareRead:
248  fl.l_type = F_RDLCK;
249  if (fcntl (FileHandle, F_SETLK, &fl) == -1)
250  throw_sys_sub_if (errno == EAGAIN || errno == EACCES, wstring (path));
251  break;
252 
253  case ShareReadWrite:
254  fl.l_type = (mode == OpenRead ? F_RDLCK : F_WRLCK);
255  if (fcntl (FileHandle, F_GETLK, &fl) != -1 && fl.l_type != F_UNLCK)
256  {
257  errno = EAGAIN;
258  throw SystemException (SRC_POS, wstring (path));
259  }
260  break;
261 
263  break;
264 
265  default:
266  throw ParameterIncorrect (SRC_POS);
267  }
268  }
269  catch (...)
270  {
271  close (FileHandle);
272  throw;
273  }
274 #endif // 0
275 
276  Path = path;
277  mFileOpenFlags = flags;
278  FileIsOpen = true;
279  }
280 
281  uint64 File::Read (const BufferPtr &buffer) const
282  {
284 
285 #ifdef TC_TRACE_FILE_OPERATIONS
286  TraceFileOperation (FileHandle, Path, false, buffer.Size());
287 #endif
288  ssize_t bytesRead = read (FileHandle, buffer, buffer.Size());
289  throw_sys_sub_if (bytesRead == -1, wstring (Path));
290 
291  return bytesRead;
292  }
293 
294  uint64 File::ReadAt (const BufferPtr &buffer, uint64 position) const
295  {
297 
298 #ifdef TC_TRACE_FILE_OPERATIONS
299  TraceFileOperation (FileHandle, Path, false, buffer.Size(), position);
300 #endif
301  ssize_t bytesRead = pread (FileHandle, buffer, buffer.Size(), position);
302  throw_sys_sub_if (bytesRead == -1, wstring (Path));
303 
304  return bytesRead;
305  }
306 
307  void File::SeekAt (uint64 position) const
308  {
310  throw_sys_sub_if (lseek (FileHandle, position, SEEK_SET) == -1, wstring (Path));
311  }
312 
313  void File::SeekEnd (int offset) const
314  {
316 
317  // BSD does not support seeking to the end of a device
318 #ifdef TC_BSD
319  if (Path.IsBlockDevice() || Path.IsCharacterDevice())
320  {
321  SeekAt (Length() + offset);
322  return;
323  }
324 #endif
325 
326  throw_sys_sub_if (lseek (FileHandle, offset, SEEK_END) == -1, wstring (Path));
327  }
328 
329  void File::Write (const ConstBufferPtr &buffer) const
330  {
332 
333 #ifdef TC_TRACE_FILE_OPERATIONS
334  TraceFileOperation (FileHandle, Path, true, buffer.Size());
335 #endif
336  throw_sys_sub_if (write (FileHandle, buffer, buffer.Size()) != (ssize_t) buffer.Size(), wstring (Path));
337  }
338 
339  void File::WriteAt (const ConstBufferPtr &buffer, uint64 position) const
340  {
342 
343 #ifdef TC_TRACE_FILE_OPERATIONS
344  TraceFileOperation (FileHandle, Path, true, buffer.Size(), position);
345 #endif
346  throw_sys_sub_if (pwrite (FileHandle, buffer, buffer.Size(), position) != (ssize_t) buffer.Size(), wstring (Path));
347  }
348 }