DCL 4.0
Loading...
Searching...
No Matches
File.cpp
Go to the documentation of this file.
1#include <dcl/Config.h>
2
3#if __DCL_WINDOWS
4 #include <windows.h>
5 #include <wchar.h> // _wmktemp
6 #include <errno.h> // EINVAL
7#else
8 #include <stdlib.h> // mkstemp
9 #include <sys/ioctl.h> // available
10 #include <dcl/_fcntl.h>
11 #include <dcl/_stat.h>
12 #include <dcl/_unistd.h>
13#endif
14
15#include <dcl/File.h>
16
17#if __DCL_HAVE_ALLOC_DEBUG
18#undef __DCL_ALLOC_LEVEL
19#define __DCL_ALLOC_LEVEL __DCL_ALLOC_INTERNAL
20#endif
21
22#if __DCL_DEBUG
23#undef __THIS_FILE__
24static const char_t __THIS_FILE__[] = __T("dcl/File.cpp");
25#endif
26
27__DCL_BEGIN_NAMESPACE
28
30
31#ifndef INVALID_HANDLE_VALUE
32#define INVALID_HANDLE_VALUE -1
33#endif
34
35String File::toString() const
36{
37 StringBuilder r = className();
39 r += __T(" closed");
40 else
41 r += __T(" ") + __path;
42
43 return r;
44}
45
47{
49 try {
50 close();
51 }
52 catch (Exception* e) {
53 __DCL_TRACE1(__T("Error! File::~File %ls\n"), e->toString().data());
54 e->destroy();
55 }
56 }
57}
58
60{
62 __closeOnClose = true;
63#if __DCL_WINDOWS
64 __fileType = UNKNOWN;
65 __readEvent = NULL;
66 __writeEvent = NULL;
67#endif
68}
69
70File::File(const String& _path, int _oflags, int _mode)
72{
74 open(_path, _oflags, _mode);
75}
76
77void File::open(const String& _path, int _oflags, int _mode)
79{
81 close();
82
83 __closeOnClose = true;
84#if __DCL_WINDOWS
85 __fileType = UNKNOWN;
86 __readEvent = NULL;
87 __writeEvent = NULL;
88
89 FileType fileType = UNKNOWN;
90 // Console, COMM 을 검사한다.
91 HANDLE handle = CreateFileW(_path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
93 DWORD dw;
94 DCB dcb;
95 if (GetNamedPipeInfo(handle, NULL, NULL, NULL, NULL))
96 fileType = PIPE;
97 else if (GetConsoleMode(handle, &dw))
98 fileType = CONSOLE;
99 else if (GetCommState(handle, &dcb))
100 fileType = COMM;
101 CloseHandle(handle);
103 }
104
105 DWORD dwDesiredAccess = GENERIC_READ;
106 DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
107 SECURITY_ATTRIBUTES securityAttributes = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
108 DWORD dwCreationDisposition = OPEN_EXISTING;
109 DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
110
111 switch (_oflags & (READONLY | WRITEONLY | READWRITE)) {
112 default:
113 // _oflags == 0 이면 READONLY 인 것으로 간주한다.
114 case READONLY:
115 dwDesiredAccess = GENERIC_READ;
116 break;
117 case WRITEONLY:
118 if (_oflags & APPEND)
119 dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
120 else
121 dwDesiredAccess = GENERIC_WRITE;
122 break;
123 case READWRITE:
124 dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
125 break;
126 }
127
128 if (_oflags & EXCLUSIVE) {
129 dwShareMode = 0;
130 }
131
132 switch (_oflags & (CREATE | EXCLUSIVE | TRUNCATE)) {
133 default:
134 case EXCLUSIVE:
135 dwCreationDisposition = OPEN_EXISTING;
136 break;
137 case CREATE:
138 case CREATE | TRUNCATE:
139 dwCreationDisposition = OPEN_ALWAYS;
140 break;
141 case CREATE | EXCLUSIVE:
142 case CREATE | EXCLUSIVE | TRUNCATE:
143 dwCreationDisposition = CREATE_NEW;
144 break;
145 case TRUNCATE:
146 case TRUNCATE | EXCLUSIVE:
147 dwCreationDisposition = TRUNCATE_EXISTING;
148 break;
149 }
150
151 if (_oflags & NONBLOCK)
152 dwFlagsAndAttributes |= FILE_FLAG_OVERLAPPED;
153
154 if (_oflags & SYNC)
155 dwFlagsAndAttributes |= FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH;
156
157 if (fileType == CONSOLE || fileType == PIPE) {
158
159 handle = CreateFileW(_path, dwDesiredAccess, dwShareMode, &securityAttributes,
160 OPEN_EXISTING, dwFlagsAndAttributes, NULL);
161 }
162 else if (fileType == COMM) {
163 handle = CreateFileW(_path, dwDesiredAccess, dwShareMode, &securityAttributes,
164 OPEN_EXISTING, dwFlagsAndAttributes, NULL);
165 }
166 else {
167 // UNKNOWN, maybe REGULAR
168 switch (dwDesiredAccess & (GENERIC_READ | GENERIC_WRITE)) {
169 case GENERIC_READ:
170 dwFlagsAndAttributes |= FILE_FLAG_SEQUENTIAL_SCAN;
171 break;
172 case GENERIC_READ | GENERIC_WRITE:
173 dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
174 break;
175 }
176
177 if ((_oflags & TRUNCATE) && ((dwDesiredAccess & GENERIC_WRITE) == GENERIC_WRITE))
178 handle = CreateFileW(_path, dwDesiredAccess, dwShareMode,
179 &securityAttributes, TRUNCATE_EXISTING, dwFlagsAndAttributes, NULL);
180
182 handle = CreateFileW(_path, dwDesiredAccess, dwShareMode,
183 &securityAttributes, dwCreationDisposition, dwFlagsAndAttributes, NULL);
184
186 && (_oflags & APPEND) && ((dwDesiredAccess & GENERIC_READ) == GENERIC_READ)) {
187 fileType = REGULAR;
188 if (SetFilePointer(handle, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER) {
189 DWORD dwSaveError = GetLastError();
190 CloseHandle(handle);
192 SetLastError(dwSaveError);
193 }
194 }
195 }
196
197 // _oflags에 NONBLOCK이 있으면 read, write Overrlapped Io 하도록 Event 객체를 생성한다.
198 HANDLE readEvent = NULL, writeEvent = NULL;
199 if (handle != INVALID_HANDLE_VALUE && _oflags & NONBLOCK) {
200 __DCL_ASSERT(dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED);
201 if (_oflags & (WRITEONLY | READWRITE))
202 writeEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
203
204 // _oflags == 0 이면 READONLY 인 것으로 간주한다.
205 if (_oflags & (READONLY | READWRITE) || writeEvent == NULL)
206 readEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
207
208 if (readEvent == NULL && writeEvent == NULL) {
209 DWORD dwSaveError = GetLastError();
210 if (readEvent)
211 CloseHandle(readEvent);
212 if (writeEvent)
213 CloseHandle(writeEvent);
214
215 CloseHandle(handle);
217 SetLastError(dwSaveError);
218 }
219 }
220
222 throw new IOException(_path, GetLastError());
223
224 __fileType = fileType;
225 __readEvent = readEvent;
226 __writeEvent = writeEvent;
227#else
228 int oflags = 0;
229 if (_oflags & READONLY)
230 oflags |= O_RDONLY;
231 if (_oflags & WRITEONLY)
232 oflags |= O_WRONLY;
233 if (_oflags & READWRITE)
234 oflags |= O_RDWR;
235 if (_oflags & CREATE)
236 oflags |= O_CREAT;
237 if (_oflags & EXCLUSIVE)
238 oflags |= O_EXCL;
239 if (_oflags & NOCTTY)
240 oflags |= O_NOCTTY;
241 if (_oflags & APPEND)
242 oflags |= O_APPEND;
243 if (_oflags & TRUNCATE)
244 oflags |= O_TRUNC;
245 if (_oflags & NONBLOCK)
246 oflags |= O_NONBLOCK;
247 if (_oflags & SYNC)
248 oflags |= O_SYNC;
249
250 int handle = __open(_path, oflags, _mode);
251 if (handle == -1)
252 throw new IOException(_path, errno);
253#endif
255 __path = _path;
256}
257
258File::File(HandleType _handle, const String& _path)
259{
260 __handle = _handle;
261 __path = _path;
262 __closeOnClose = true;
263}
264
265File::File(HandleType _handle, int _ohints, bool _closeOnClose)
267{
269 open(_handle, _ohints, _closeOnClose);
270}
271
272void File::open(HandleType _handle, int _ohints, bool _closeOnClose)
274{
276 close();
277
278#if __DCL_WINDOWS
279 __fileType = UNKNOWN;
280 __readEvent = NULL;
281 __writeEvent = NULL;
282
283 StringBuilder path;
284 FileType fileType = UNKNOWN;
285
286 wchar_t nameInfo[PATH_MAX + 1 + 4] = { L'\0' };
287 DWORD dwConsoleMode;
288 DCB dcb;
289 if (GetFileInformationByHandleEx(_handle, FileNameInfo, nameInfo, sizeof(nameInfo))) {
290 fileType = REGULAR;
291 path.assign(((FILE_NAME_INFO*)nameInfo)->FileName);
292 }
293 else if (GetNamedPipeInfo(_handle, NULL, NULL, NULL, NULL)) {
294 path.format(__T("(pipe: %d)"), _handle);
295 fileType = PIPE;
296 }
297 else if (GetConsoleMode(_handle, &dwConsoleMode)) {
298 path = __T("CON");
299 fileType = CONSOLE;
300 }
301 else if (GetCommState(_handle, &dcb)) {
302 path = __T("COM#N");
303 fileType = COMM;
304 }
305 else {
306 path.format(__T("(HANDLE: %p)"), _handle);
307 throw new IOException(path, ERROR_INVALID_HANDLE);
308 }
309
310 HANDLE readEvent = NULL, writeEvent = NULL;
311 if (_ohints & NONBLOCK) {
312 if (_ohints & (WRITEONLY | READWRITE))
313 writeEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
314
315 // _oflags == 0 이면 READONLY 인 것으로 간주한다.
316 if (_ohints & (READONLY | READWRITE) || writeEvent == NULL)
317 readEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
318
319 if (readEvent == NULL && writeEvent == NULL) {
320 DWORD dwSaveError = GetLastError();
321 if (readEvent)
322 CloseHandle(readEvent);
323 if (writeEvent)
324 CloseHandle(writeEvent);
325
326 throw new IOException(path, dwSaveError);
327 }
328 }
329
330 __path = path.toString();
331 __fileType = fileType;
332 __readEvent = readEvent;
333 __writeEvent = writeEvent;
334#else
335 if (isatty(_handle)) {
336 if (__ttyname(_handle, __path) != 0)
337 throw new IOException(className(), errno);
338 }
339 else
340 __path = String::format(__T("(fd: %d)"), _handle);
341#endif
342
343 __handle = _handle;
344 __closeOnClose = _closeOnClose;
345}
346
349{
351
352#if __DCL_WINDOWS
353 if (!FlushFileBuffers(__handle))
354 // 콘솔과 같이 버러링을 하지 않는 장치
355 throw new IOException(__path, GetLastError());
356#else
357 if (fsync(__handle) == -1)
358 // EINVAL, EBADF, EROFS, EIO
359 throw new IOException(__path, errno);
360#endif
361}
362
365
366{
368
369#if __DCL_WINDOWS
370 if (__fileType == COMM)
371 PurgeComm(__handle, PURGE_RXABORT | PURGE_RXCLEAR
372 | PURGE_TXABORT | PURGE_TXCLEAR);
373 __fileType = UNKNOWN;
374 if (__readEvent) {
375 CloseHandle(__readEvent);
376 __readEvent = NULL;
377 }
378 if (__writeEvent) {
379 CloseHandle(__writeEvent);
380 __writeEvent = NULL;
381 }
382#endif
383
384 if (!__closeOnClose)
385 return;
386
387 HandleType handle = __handle;
388 String path = __path;
390 __path.clear();
391
392#if __DCL_WINDOWS
393 if (!CloseHandle(handle))
394 throw new IOException(path, GetLastError());
395#else
396 if (::close(handle))
397 throw(new IOException(path, errno));
398#endif
399}
400
401size_t File::available() const
403{
405
406#if __DCL_WINDOWS
407 size_t nbytes = 0;
408 switch (__fileType) {
409 case REGULAR: {
410 LARGE_INTEGER fileSize;
411 if (GetFileSizeEx(__handle, &fileSize)) {
412 LARGE_INTEGER distanceToMove;
413 LARGE_INTEGER newFilePointer;
414 distanceToMove.QuadPart = 0;
415 if (SetFilePointerEx(__handle, distanceToMove, &newFilePointer, FILE_CURRENT))
416 nbytes = (size_t)(fileSize.QuadPart - newFilePointer.QuadPart);
417 }
418 break;
419 }
420 case PIPE: {
421 DWORD dwTotalBytesAvail;
422 if (PeekNamedPipe(__handle, NULL, 0, NULL, &dwTotalBytesAvail, NULL))
423 nbytes = (size_t)dwTotalBytesAvail;
424 break;
425 }
426 case CONSOLE: {
427 INPUT_RECORD buf[200]; // 200 * (sizeof(INPUT_RECORD) == 20) 4000
428 DWORD dwEvents = 0;
429 if (PeekConsoleInput(__handle, buf, __countof(buf, INPUT_RECORD), &dwEvents)) {
430 size_t n = 0;
431 for (int i = 0; i < __countof(buf, INPUT_RECORD); i++) {
432 if (buf[i].EventType == KEY_EVENT) {
433 KEY_EVENT_RECORD& ev = buf[i].Event.KeyEvent;
434 if (ev.bKeyDown && ev.uChar.AsciiChar != 0) {
435 if (ev.uChar.AsciiChar == 13) {
436 nbytes = n + 2; // ReadFile에서 \r\n으로 변환되어 읽힌다.
437 break;
438 }
439 n += ev.wRepeatCount;
440 }
441 }
442 }
443 // NONBLOCK
444 if (nbytes == 0 && __readEvent)
445 nbytes = n;
446 }
447 break;
448 }
449 case COMM: {
450 DWORD dwErrors;
451 COMSTAT stat;
452 if (ClearCommError(__handle, &dwErrors, &stat))
453 nbytes = (size_t)stat.cbInQue;
454 break;
455 }
456#if 0
457 // 이 부분은 Socket 클래스에서 override한다.
458 case SOCKET: {
459 u_long n = 0;
460 if (ioctlsocket((::SOCKET)__handle, FIONREAD, &n))
461 throw new IOException(__path, WSAGetLastError());
462 nbytes = (size_t)n;
463 break;
464 }
465#endif
466 }
467 return nbytes;
468#else
469 // x64 nbytes를 off_t(long long int)로 하면 안된다.
470 unsigned int nbytes = 0;
471 ioctl(__handle, FIONREAD, &nbytes);
472 return (size_t)nbytes;
473#endif
474}
475
476size_t File::read(void* _buf, size_t _n)
478{
480 __DCL_ASSERT_PARAM(_buf != NULL);
481
482#if __DCL_WINDOWS
483 DWORD n = 0;
484 if (__readEvent) {
485 // NONBLOCK, Overrapped Read
486 OVERLAPPED ov;
487 ZeroMemory(&ov, sizeof(ov)); // cf. memset(&ov, 0, sizeof(ov));
488 ov.hEvent = __readEvent;
489 if (ReadFile(__handle, _buf, (DWORD)_n, &n, &ov)) {
490 // GetOverlappedResult가 성공하면 이벤트는 Set 된다.
491 SetEvent(ov.hEvent);
492
493 // 다른 스레드에서 WriteFile을 호출했을 경우 n == 0일 수 있다.
494 return n;
495 }
496 if (GetLastError() == ERROR_IO_PENDING) {
497 // 읽기가 진행중이다. 마칠때까지 기다린 후 결과를 확인한다.
498 switch (WaitForSingleObject(ov.hEvent, INFINITE)) {
499 case WAIT_OBJECT_0:
500 if (GetOverlappedResult(__handle, &ov, &n, FALSE))
501 return n;
502 break;
503 case WAIT_TIMEOUT: // 이것은 결코 도달하지 않는다. INFINITE
504 CancelIo(__handle);
505 SetLastError(ERROR_TIMEOUT);
506 break;
507 default:
508 __DCL_ASSERT(false);
509 }
510 }
511 // ERROR!
512 throw new IOException(__path, GetLastError());
513 }
514 else {
515 // __readEvent == NULL, Blocked Read
516 if (!ReadFile(__handle, _buf, (DWORD)_n, &n, NULL))
517 throw new IOException(__path, GetLastError());
518 }
519 return n;
520#else
521 ssize_t n = 0;
522 while ((n = ::read(__handle, _buf, _n)) == -1) {
523 // errno가 EAGAIN or EWOULDBLOCK인 경우
524 // fd가 O_NONBLOCK으로 열렸고, 읽기가 차단되었다.
525 // EAGAIN이면 0바이트를 읽었고, 읽기를 다시 시도한다.
526 // 그 외에는 오류이다.
527 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
528 throw new IOException(__path, errno);
529 }
530 }
531 return n;
532#endif
533}
534
535size_t File::write(const void* _buf, size_t _n)
537{
539 __DCL_ASSERT_PARAM(_buf != NULL);
540
541#if __DCL_WINDOWS
542 DWORD n = 0;
543 if (__writeEvent) {
544 // NONBLOCK, Overrapped Write
545 OVERLAPPED ov;
546 ZeroMemory(&ov, sizeof(ov)); // cf. memset(&ov, 0, sizeof(ov));
547 ov.hEvent = __writeEvent;
548 if (WriteFile(__handle, _buf, (DWORD)_n, &n, &ov)) {
549 // GetOverlappedResult가 성공하면 이벤트는 Set 된다.
550 SetEvent(ov.hEvent);
551 // 다른 스레드에서 ReadFile을 호출했을 경우 n == 0일 수 있다.
552 return n;
553 }
554 if (GetLastError() == ERROR_IO_PENDING) {
555 // 쓰기가 진행중이다. 마칠때까지 기다린 후 결과를 확인한다.
556 switch (WaitForSingleObject(ov.hEvent, INFINITE)) {
557 case WAIT_OBJECT_0:
558 if (GetOverlappedResult(__handle, &ov, &n, FALSE))
559 return n;
560 break;
561 case WAIT_TIMEOUT: // 이것은 결코 도달하지 않는다. INFINITE
562 CancelIo(__handle);
563 SetLastError(ERROR_TIMEOUT);
564 default:
565 __DCL_ASSERT(false);
566 }
567 }
568 // ERROR!
569 throw new IOException(__path, GetLastError());
570 }
571 else {
572 // __writeEvent == NULL, Blocked Write
573 if (!WriteFile(__handle, _buf, (DWORD)_n, &n, NULL))
574 throw new IOException(__path, GetLastError());
575 }
576 return n;
577#else
578 ssize_t n = ::write(__handle, _buf, _n);
579 if (n == -1) {
580 // 파일이 nonblocking으로 표시되었고 오퍼레이션이 블록되었다.
581 if (errno == EAGAIN || errno == EWOULDBLOCK)
582 return 0;
583 else
584 throw new IOException(__path, errno);
585 }
586 return n;
587#endif
588}
589
590File::off_t File::seek(off_t _offset, int _whence)
592{
594
595#if __DCL_WINDOWS
596 DWORD dwMoveMethod = FILE_BEGIN;
597 switch (_whence) {
598 case BEGIN:
599 dwMoveMethod = FILE_BEGIN;
600 break;
601 case CURRENT:
602 dwMoveMethod = FILE_CURRENT;
603 break;
604 case END:
605 dwMoveMethod = FILE_END;
606 break;
607 default:
608 __DCL_ASSERT(false);
609 }
610 LARGE_INTEGER distanceToMove;
611 LARGE_INTEGER newFilePointer;
612 distanceToMove.QuadPart = _offset;
613 if (!SetFilePointerEx(__handle, distanceToMove, &newFilePointer, dwMoveMethod))
614 throw new IOException(__path, GetLastError());
615 return newFilePointer.QuadPart;
616#else
617 int whence = 0;
618 switch (_whence) {
619 case BEGIN :
620 whence = SEEK_SET;
621 break;
622 case CURRENT :
623 whence = SEEK_CUR;
624 break;
625 case END :
626 whence = SEEK_END;
627 break;
628 default :
629 __DCL_ASSERT(false);
630 }
631
632 off_t r = lseek(__handle, _offset, whence);
633 if (r == (off_t)-1)
634 throw (new IOException(__path, errno));
635 return r;
636#endif
637}
638
639File::off_t File::size() const
641{
643
644#if __DCL_WINDOWS
645 LARGE_INTEGER fileSize;
646 if (!GetFileSizeEx(__handle, &fileSize))
647 throw new IOException(__path, GetLastError());
648 return fileSize.QuadPart;
649#else
650 struct stat st;
651 int r = fstat(__handle, &st);
652 if (r == -1)
653 throw (new IOException(__path, errno));
654
655 return st.st_size;
656#endif
657}
658
661{
662 time_t mtime;
663 if (!time((time_t * )NULL, &mtime, (time_t * )NULL)) {
664#if __DCL_WINDOWS
665 throw new IOException(__path, GetLastError());
666#else
667 throw (new IOException(__path, errno));
668#endif
669 }
670 return DateTime(mtime);
671}
672
673bool File::time(time_t* _atime, time_t* _mtime, time_t* _ctime) const
674{
676
677#if __DCL_WINDOWS
678 FILETIME atime;
679 FILETIME mtime;
680 FILETIME ctime;
681 if (!GetFileTime(__handle, &atime, &mtime, &ctime)) {
682 return false;
683 }
684
685 ULARGE_INTEGER n;
686 if (_atime) {
687 n.HighPart = atime.dwHighDateTime;
688 n.LowPart = atime.dwLowDateTime;
689 *_atime = n.QuadPart;
690 }
691 if (_mtime) {
692 n.HighPart = mtime.dwHighDateTime;
693 n.LowPart = mtime.dwLowDateTime;
694 *_mtime = n.QuadPart;
695 }
696 if (_ctime) {
697 n.HighPart = ctime.dwHighDateTime;
698 n.LowPart = ctime.dwLowDateTime;
699 *_ctime = n.QuadPart;
700 }
701#else
702 struct stat sb;
703 int r = fstat(__handle, &sb);
704 if (r == -1) {
705 return false;
706 }
707 if (_atime) {
708 *_atime = sb.st_atime;
709 }
710 if (_mtime) {
711 *_mtime = sb.st_mtime;
712 }
713 if (_ctime) {
714 *_ctime = sb.st_ctime;
715 }
716#endif
717 return true;
718}
719
720// "dir/prefixXXXXX" 이름의 파일을 생성하여 파일 기술자를 리턴
722 const String& _dirname,
723 const String& _prefix,
724 unsigned int _mode // = 0666
726{
727 File* r = NULL;
728
729 StringBuilder sbTemplate;
730 if (!_dirname.isEmpty()) {
731 sbTemplate = _dirname;
732 if (!_dirname.endsWith(L"/")) {
733 sbTemplate += L"/";
734 }
735 }
736
737 if (!_prefix.isEmpty()) {
738 sbTemplate += _prefix;
739 }
740 else {
741 sbTemplate += L"dcl";
742 }
743
744 sbTemplate += L"XXXXXX";
745
746#if __DCL_WINDOWS
747 if (::_wmktemp((wchar_t*)sbTemplate.data())) {
748 r = new File(sbTemplate, READWRITE | CREATE | EXCLUSIVE, _mode);
749 }
750 else {
751 throw new IOException(sbTemplate, EINVAL);
752 }
753#else
754 ByteString bsbTemplate = UTF8Encoder::encode(sbTemplate.toString());
755 int handle = ::mkstemp((char*)bsbTemplate.data());
756 if (handle == -1) {
757 throw new IOException(sbTemplate, errno);
758 }
759
760 struct stat st;
761 if (::fstat(handle, &st)) {
762 throw new IOException(sbTemplate, errno);
763 }
764
765 if (st.st_mode != _mode) {
766 if (::fchmod(handle, _mode)) {
767 throw new IOException(sbTemplate, errno);
768 }
769 }
770
771 r = new File(handle, UTF8Decoder::decode(bsbTemplate));
772#endif
773 return r;
774}
775
776__DCL_END_NAMESPACE
DCLCAPI int __open(const String &_path, int _oflags,...)
Definition _fcntl.cpp:23
#define __THIS_FILE__
Definition _trace.h:14
DCLCAPI int __ttyname(int fd, String &_r)
Definition _unistd.cpp:57
#define NULL
Definition Config.h:340
#define __countof(array, type)
Definition Config.h:365
wchar_t char_t
Definition Config.h:275
#define __DCL_THROWS1(e)
Definition Config.h:167
#define INVALID_HANDLE_VALUE
Definition Dir.cpp:31
#define TRUE
#define FALSE
#define __DCL_TRACE1(fmt, arg1)
Definition Object.h:376
#define __DCL_ASSERT_PARAM(expr)
Definition Object.h:384
#define __DCL_ASSERT(expr)
Definition Object.h:371
#define IMPLEMENT_CLASSINFO(class_name, base_class_name)
Definition Object.h:228
#define __T(str)
Definition Object.h:44
#define __DCL_ASSERT_HANDLE(expr)
Definition Object.h:383
ByteString r
ByteBuffer * buf
void CharsetConvertException *size_t n
Definition SQLField.cpp:253
#define ioctlsocket(s, cmd, argp)
Definition Socket.cpp:40
#define INFINITE
Definition Thread.h:17
virtual String toString() const
Definition Exception.cpp:40
virtual void destroy()
Definition Exception.cpp:74
Definition File.h:38
HandleType handle() const
Definition File.h:242
void open(const String &_path, int _oflags=READONLY, int _mode=0666) __DCL_THROWS1(IOException *)
Definition File.cpp:77
@ CURRENT
Definition File.h:206
@ END
Definition File.h:207
@ BEGIN
Definition File.h:205
HandleType __handle
Definition File.h:251
virtual void close() __DCL_THROWS1(IOException *)
Definition File.cpp:363
virtual ~File()
bool time(time_t *_atime, time_t *_mtime, time_t *_ctime) const
Definition File.cpp:673
DateTime mtime() const __DCL_THROWS1(IOException *)
Definition File.cpp:659
String __path
Definition File.h:250
off_t seek(off_t _offset, int _whence) __DCL_THROWS1(IOException *)
Definition File.cpp:590
virtual size_t read(void *_buf, size_t _n) __DCL_THROWS1(IOException *)
Definition File.cpp:476
static File * openTempFile(const String &_dirname, const String &_prefix, unsigned int _mode=0666) __DCL_THROWS1(IOException *)
Definition File.cpp:721
virtual String toString() const
const String & path() const
Definition File.h:247
virtual void sync() __DCL_THROWS1(IOException *)
Definition File.cpp:347
virtual size_t write(const void *_buf, size_t _n) __DCL_THROWS1(IOException *)
Definition File.cpp:535
bool __closeOnClose
Definition File.h:252
virtual size_t available() const __DCL_THROWS1(IOException *)
Definition File.cpp:401
File()
Definition File.cpp:59
off_t size() const __DCL_THROWS1(IOException *)
Definition File.cpp:639
String className() const
Definition Object.cpp:163