|
|
1.1 root 1: /*
2: Copyright (c) 2008 TrueCrypt Foundation. All rights reserved.
3:
4: Governed by the TrueCrypt License 2.4 the full text of which is contained
5: in the file License.txt included in TrueCrypt binary and source code
6: distribution packages.
7: */
8:
9: #define _LARGEFILE_SOURCE 1
10: #define _FILE_OFFSET_BITS 64
11:
12: #include <errno.h>
13: #ifdef TC_LINUX
14: #include <sys/mount.h>
15: #endif
16: #ifdef TC_BSD
17: #include <sys/disk.h>
18: #endif
19: #include <sys/file.h>
20: #include <sys/types.h>
21: #include <sys/stat.h>
22: #include <fcntl.h>
23: #include <unistd.h>
24: #include <utime.h>
25: #include "Platform/File.h"
26:
27: namespace TrueCrypt
28: {
29: void File::Close ()
30: {
31: ValidateState();
32:
33: if (!SharedHandle)
34: {
35: close (FileHandle);
36: FileIsOpen = false;
37:
38: if ((mFileOpenFlags & File::PreserveTimestamps) && Path.IsFile())
39: {
40: struct utimbuf u;
41: u.actime = AccTime;
42: u.modtime = ModTime;
43: throw_sys_sub_if (utime (string (Path).c_str(), &u) == -1, wstring (Path));
44: }
45: }
46: }
47:
48: void File::Delete ()
49: {
50: Close();
51: Path.Delete();
52: }
53:
54:
55: void File::Flush () const
56: {
57: ValidateState();
58: throw_sys_sub_if (fsync (FileHandle) != 0, wstring (Path));
59: }
60:
61: uint32 File::GetDeviceSectorSize () const
62: {
63: if (Path.IsDevice())
64: {
65: #ifdef TC_LINUX
66: int blockSize;
67: throw_sys_sub_if (ioctl (FileHandle, BLKSSZGET, &blockSize) == -1, wstring (Path));
68: return blockSize;
69:
70: #elif defined (TC_MACOSX)
71: uint32 blockSize;
72: throw_sys_sub_if (ioctl (FileHandle, DKIOCGETBLOCKSIZE, &blockSize) == -1, wstring (Path));
73: return blockSize;
74: #endif
75: }
76:
77: return 512;
78: }
79:
80: uint64 File::Length () const
81: {
82: ValidateState();
83:
84: // BSD does not support seeking to the end of a device
85: #ifdef TC_BSD
86: if (Path.IsBlockDevice() || Path.IsCharacterDevice())
87: {
88: # ifdef TC_MACOSX
89: uint32 blockSize;
90: uint64 blockCount;
91: throw_sys_sub_if (ioctl (FileHandle, DKIOCGETBLOCKSIZE, &blockSize) == -1, wstring (Path));
92: throw_sys_sub_if (ioctl (FileHandle, DKIOCGETBLOCKCOUNT, &blockCount) == -1, wstring (Path));
93: return blockCount * blockSize;
94: # else
95: uint64 mediaSize;
96: throw_sys_sub_if (ioctl (FileHandle, DIOCGMEDIASIZE, &mediaSize) == -1, wstring (Path));
97: return mediaSize;
98: # endif
99: }
100: #endif
101: off_t current = lseek (FileHandle, 0, SEEK_CUR);
102: throw_sys_sub_if (current == -1, wstring (Path));
103: SeekEnd (0);
104: uint64 length = lseek (FileHandle, 0, SEEK_CUR);
105: SeekAt (current);
106: return length;
107: }
108:
109: void File::Open (const FilePath &path, FileOpenMode mode, FileShareMode shareMode, FileOpenFlags flags)
110: {
111: #ifdef TC_LINUX
112: int sysFlags = O_LARGEFILE;
113: #else
114: int sysFlags = 0;
115: #endif
116:
117: switch (mode)
118: {
119: case CreateReadWrite:
120: sysFlags |= O_CREAT | O_TRUNC | O_RDWR;
121: break;
122:
123: case CreateWrite:
124: sysFlags |= O_CREAT | O_TRUNC | O_WRONLY;
125: break;
126:
127: case OpenRead:
128: sysFlags |= O_RDONLY;
129: break;
130:
131: case OpenWrite:
132: sysFlags |= O_WRONLY;
133: break;
134:
135: case OpenReadWrite:
136: sysFlags |= O_RDWR;
137: break;
138:
139: default:
140: throw ParameterIncorrect (SRC_POS);
141: }
142:
143: if ((flags & File::PreserveTimestamps) && path.IsFile())
144: {
145: struct stat statData;
146: throw_sys_sub_if (stat (string (path).c_str(), &statData) == -1, wstring (path));
147: AccTime = statData.st_atime;
148: ModTime = statData.st_mtime;
149: }
150:
151: FileHandle = open (string (path).c_str(), sysFlags, S_IRUSR | S_IWUSR);
152: throw_sys_sub_if (FileHandle == -1, wstring (path));
153:
154: try
155: {
156: switch (shareMode)
157: {
158: case ShareNone:
159: if (flock (FileHandle, LOCK_EX | LOCK_NB) == -1)
160: throw_sys_sub_if (errno == EAGAIN, wstring (path));
161: break;
162:
163: case ShareRead:
164: if (flock (FileHandle, LOCK_SH | LOCK_NB) == -1)
165: throw_sys_sub_if (errno == EAGAIN, wstring (path));
166: break;
167:
168: case ShareReadWrite:
169: if (flock (FileHandle, (mode == OpenRead ? LOCK_SH : LOCK_EX) | LOCK_NB) == -1)
170: throw_sys_sub_if (errno == EAGAIN, wstring (path));
171: flock (FileHandle, LOCK_UN | LOCK_NB);
172: break;
173:
174: case ShareReadWriteIgnoreLock:
175: break;
176:
177: default:
178: throw ParameterIncorrect (SRC_POS);
179: }
180: }
181: catch (...)
182: {
183: close (FileHandle);
184: throw;
185: }
186:
187: Path = path;
188: mFileOpenFlags = flags;
189: FileIsOpen = true;
190: }
191:
192: uint64 File::Read (const BufferPtr &buffer) const
193: {
194: ValidateState();
195:
196: ssize_t bytesRead = read (FileHandle, buffer, buffer.Size());
197: throw_sys_sub_if (bytesRead == -1, wstring (Path));
198:
199: return bytesRead;
200: }
201:
202: uint64 File::ReadAt (const BufferPtr &buffer, uint64 position) const
203: {
204: ValidateState();
205:
206: ssize_t bytesRead = pread (FileHandle, buffer, buffer.Size(), position);
207: throw_sys_sub_if (bytesRead == -1, wstring (Path));
208:
209: return bytesRead;
210: }
211:
212: void File::SeekAt (uint64 position) const
213: {
214: ValidateState();
215: throw_sys_sub_if (lseek (FileHandle, position, SEEK_SET) == -1, wstring (Path));
216: }
217:
218: void File::SeekEnd (int offset) const
219: {
220: ValidateState();
221:
222: // BSD does not support seeking to the end of a device
223: #ifdef TC_BSD
224: if (Path.IsBlockDevice() || Path.IsCharacterDevice())
225: {
226: SeekAt (Length() + offset);
227: return;
228: }
229: #endif
230:
231: throw_sys_sub_if (lseek (FileHandle, offset, SEEK_END) == -1, wstring (Path));
232: }
233:
234: void File::Write (const ConstBufferPtr &buffer) const
235: {
236: ValidateState();
237: throw_sys_sub_if (write (FileHandle, buffer, buffer.Size()) != buffer.Size(), wstring (Path));
238: }
239:
240: void File::WriteAt (const ConstBufferPtr &buffer, uint64 position) const
241: {
242: ValidateState();
243: throw_sys_sub_if (pwrite (FileHandle, buffer, buffer.Size(), position) != buffer.Size(), wstring (Path));
244: }
245: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.