ucommon  7.0.0
About: GNU uCommon C++ is a portable and optimized class framework for writing C++ applications that need to use threads and support concurrent synchronization, and that use sockets, XML parsing, object serialization, thread-optimized string and data structure classes, etc..
  Fossies Dox: ucommon-7.0.0.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)  

fsys.cpp
Go to the documentation of this file.
1 // Copyright (C) 2006-2014 David Sugar, Tycho Softworks.
2 // Copyright (C) 2015 Cherokees of Idaho.
3 //
4 // This file is part of GNU uCommon C++.
5 //
6 // GNU uCommon C++ is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU Lesser General Public License as published
8 // by the Free Software Foundation, either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // GNU uCommon C++ is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public License
17 // along with GNU uCommon C++. If not, see <http://www.gnu.org/licenses/>.
18 
19 #ifndef _MSC_VER
20 #include <sys/stat.h>
21 #endif
22 
23 #ifndef _XOPEN_SOURCE
24 #define _XOPEN_SOURCE 600
25 #endif
26 
27 #include <ucommon-config.h>
28 
29 // broken BSD; XOPEN should not imply _POSIX_C_SOURCE,
30 // _POSIX_C_SOURCE should not stop __BSD_VISIBLE
31 
32 #define u_int unsigned int
33 #define u_short unsigned short
34 #define u_long unsigned long
35 #define u_char unsigned char
36 
37 #include <ucommon/export.h>
38 #include <ucommon/thread.h>
39 #include <ucommon/fsys.h>
40 #include <ucommon/string.h>
41 #include <ucommon/typeref.h>
42 #include <ucommon/memory.h>
43 #include <ucommon/shell.h>
44 
45 #ifdef HAVE_SYSLOG_H
46 #include <syslog.h>
47 #endif
48 
49 #ifdef HAVE_LINUX_VERSION_H
50 #include <linux/version.h>
51 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8)
52 #ifdef HAVE_POSIX_FADVISE
53 #undef HAVE_POSIX_FADVISE
54 #endif
55 #endif
56 #endif
57 
58 #include <stdio.h>
59 #include <fcntl.h>
60 #include <errno.h>
61 #include <string.h>
62 #include <ctype.h>
63 
64 #ifdef HAVE_POSIX_FADVISE
65 #ifndef POSIX_FADV_RANDOM
66 #undef HAVE_POSIX_FADVISE
67 #endif
68 #endif
69 
70 #ifdef HAVE_DIRENT_H
71 #include <dirent.h>
72 #endif
73 
74 #ifdef _MSWINDOWS_
75 #include <direct.h>
76 #include <winioctl.h>
77 #include <io.h>
78 #endif
79 
80 #ifdef HAVE_SYS_INOTIFY_H
81 #include <sys/inotify.h>
82 #endif
83 
84 #ifdef HAVE_SYS_EVENT_H
85 #include <sys/event.h>
86 #endif
87 
88 namespace ucommon {
89 
90 const fsys::offset_t fsys::end = (offset_t)(-1);
91 
92 #ifdef _MSWINDOWS_
93 
94 // removed from some sdk versions...
95 struct LOCAL_REPARSE_DATA_BUFFER
96 {
97  DWORD ReparseTag;
98  WORD ReparseDataLength;
99  WORD Reserved;
100 
101  // IO_REPARSE_TAG_MOUNT_POINT specifics follow
102  WORD SubstituteNameOffset;
103  WORD SubstituteNameLength;
104  WORD PrintNameOffset;
105  WORD PrintNameLength;
106  WCHAR PathBuffer[1];
107 };
108 
109 int fsys::remapError(void)
110 {
111  DWORD err = GetLastError();
112 
113  switch(err)
114  {
115  case ERROR_FILE_NOT_FOUND:
116  case ERROR_PATH_NOT_FOUND:
117  case ERROR_INVALID_NAME:
118  case ERROR_BAD_PATHNAME:
119  return ENOENT;
120  case ERROR_TOO_MANY_OPEN_FILES:
121  return EMFILE;
122  case ERROR_ACCESS_DENIED:
123  case ERROR_WRITE_PROTECT:
124  case ERROR_SHARING_VIOLATION:
125  case ERROR_LOCK_VIOLATION:
126  return EACCES;
127  case ERROR_INVALID_HANDLE:
128  return EBADF;
129  case ERROR_NOT_ENOUGH_MEMORY:
130  case ERROR_OUTOFMEMORY:
131  return ENOMEM;
132  case ERROR_INVALID_DRIVE:
133  case ERROR_BAD_UNIT:
134  case ERROR_BAD_DEVICE:
135  return ENODEV;
136  case ERROR_NOT_SAME_DEVICE:
137  return EXDEV;
138  case ERROR_NOT_SUPPORTED:
139  case ERROR_CALL_NOT_IMPLEMENTED:
140  return ENOSYS;
141  case ERROR_END_OF_MEDIA:
142  case ERROR_EOM_OVERFLOW:
143  case ERROR_HANDLE_DISK_FULL:
144  case ERROR_DISK_FULL:
145  return ENOSPC;
146  case ERROR_BAD_NETPATH:
147  case ERROR_BAD_NET_NAME:
148  return EACCES;
149  case ERROR_FILE_EXISTS:
150  case ERROR_ALREADY_EXISTS:
151  return EEXIST;
152  case ERROR_CANNOT_MAKE:
153  case ERROR_NOT_OWNER:
154  return EPERM;
155  case ERROR_NO_PROC_SLOTS:
156  return EAGAIN;
157  case ERROR_BROKEN_PIPE:
158  case ERROR_NO_DATA:
159  return EPIPE;
160  case ERROR_OPEN_FAILED:
161  return EIO;
162  case ERROR_NOACCESS:
163  return EFAULT;
164  case ERROR_IO_DEVICE:
165  case ERROR_CRC:
166  case ERROR_NO_SIGNAL_SENT:
167  return EIO;
168  case ERROR_CHILD_NOT_COMPLETE:
169  case ERROR_SIGNAL_PENDING:
170  case ERROR_BUSY:
171  return EBUSY;
172  case ERROR_DIR_NOT_EMPTY:
173  return ENOTEMPTY;
174  case ERROR_DIRECTORY:
175  return ENOTDIR;
176  default:
177  return EINVAL;
178  }
179 }
180 
181 int dir::create(const char *path, unsigned perms)
182 {
183  if(!CreateDirectory(path, NULL))
184  return remapError();
185 
186  if(perms & 06)
187  perms |= 01;
188  if(perms & 060)
189  perms |= 010;
190  if(perms & 0600)
191  perms |= 0100;
192 
193  return mode(path, perms);
194 }
195 
196 fd_t fsys::null(void)
197 {
198  SECURITY_ATTRIBUTES sattr;
199 
200  sattr.nLength = sizeof(SECURITY_ATTRIBUTES);
201  sattr.bInheritHandle = TRUE;
202  sattr.lpSecurityDescriptor = NULL;
203 
204  return CreateFile("nul", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, &sattr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
205 }
206 
207 int fsys::pipe(fd_t& input, fd_t& output, size_t size)
208 {
209  input = output = NULL;
210  SECURITY_ATTRIBUTES sattr;
211 
212  sattr.nLength = sizeof(SECURITY_ATTRIBUTES);
213  sattr.bInheritHandle = TRUE;
214  sattr.lpSecurityDescriptor = NULL;
215 
216  if(!CreatePipe(&input, &output, &sattr, (DWORD)size))
217  return remapError();
218 
219  return 0;
220 }
221 
222 int fsys::info(const char *path, struct stat *buf)
223 {
224  if(_stat(path, (struct _stat *)(buf)))
225  return remapError();
226  return 0;
227 }
228 
229 int fsys::trunc(offset_t offset)
230 {
231  if(fsys::seek(offset) != 0)
232  return remapError();
233 
234  if(SetEndOfFile(fd))
235  return 0;
236 
237  return remapError();
238 }
239 
240 int fsys::info(struct stat *buf)
241 {
242  int fn = _open_osfhandle((intptr_t)(fd), O_RDONLY);
243 
244  int rtn = _fstat(fn, (struct _stat *)(buf));
245  _close(fn);
246  if(rtn)
247  error = remapError();
248  return rtn;
249 }
250 
251 int fsys::prefix(const char *path)
252 {
253  if (_chdir(path))
254  return remapError();
255  return 0;
256 }
257 
258 int fsys::prefix(char *path, size_t len)
259 {
260  if (NULL == _getcwd(path, (socksize_t)len))
261  return remapError();
262  return 0;
263 }
264 
265 int fsys::mode(const char *path, unsigned value)
266 {
267  if(_chmod(path, value))
268  return remapError();
269  return 0;
270 }
271 
272 bool fsys::is_exists(const char *path)
273 {
274  if(_access(path, F_OK))
275  return false;
276  return true;
277 }
278 
279 bool fsys::is_readable(const char *path)
280 {
281  if(_access(path, R_OK))
282  return false;
283  return true;
284 }
285 
286 bool fsys::is_writable(const char *path)
287 {
288  if(_access(path, W_OK))
289  return false;
290  return true;
291 }
292 
293 bool fsys::is_executable(const char *path)
294 {
295  path = strrchr(path, '.');
296 
297  if(!path)
298  return false;
299 
300  if(eq_case(path, ".exe"))
301  return true;
302 
303  if(eq_case(path, ".bat"))
304  return true;
305 
306  if(eq_case(path, ".com"))
307  return true;
308 
309  if(eq_case(path, ".cmd"))
310  return true;
311 
312  if(eq_case(path, ".ps1"))
313  return true;
314 
315  return false;
316 }
317 
318 bool fsys::is_tty(fd_t fd)
319 {
320  if(fd == INVALID_HANDLE_VALUE)
321  return false;
322  DWORD type = GetFileType(fd);
323  if(type == FILE_TYPE_CHAR)
324  return true;
325  return false;
326 }
327 
328 bool fsys::is_tty(void) const
329 {
330  error = 0;
331  if(fd == INVALID_HANDLE_VALUE)
332  return false;
333  DWORD type = GetFileType(fd);
334  if(!type)
335  error = remapError();
336  if(type == FILE_TYPE_CHAR)
337  return true;
338  return false;
339 }
340 
341 void dir::close(void)
342 {
343  error = 0;
344 
345  if(ptr) {
346  if(::FindClose(fd)) {
347  delete ptr;
348  ptr = NULL;
350  }
351  else
352  error = remapError();
353  }
354  else
355  error = EBADF;
356 }
357 
358 int fsys::close(void)
359 {
360  error = 0;
361 
362  if(fd == INVALID_HANDLE_VALUE)
363  return EBADF;
364 
365  if(::CloseHandle(fd))
367  else
368  error = remapError();
369  return error;
370 }
371 
372 ssize_t dir::read(char *buf, size_t len)
373 {
374  ssize_t rtn = -1;
375  if(ptr) {
376  snprintf((char *)buf, len, ptr->cFileName);
377  rtn = (ssize_t)strlen(ptr->cFileName);
378  if(!FindNextFile(fd, ptr))
379  close();
380  return rtn;
381  }
382  return -1;
383 }
384 
385 ssize_t fsys::read(void *buf, size_t len)
386 {
387  ssize_t rtn = -1;
388  DWORD count;
389 
390  if(ReadFile(fd, (LPVOID) buf, (DWORD)len, &count, NULL))
391  rtn = count;
392  else
393  error = remapError();
394 
395  return rtn;
396 }
397 
398 ssize_t fsys::write(const void *buf, size_t len)
399 {
400  ssize_t rtn = -1;
401  DWORD count;
402 
403  if(WriteFile(fd, (LPVOID) buf, (DWORD)len, &count, NULL))
404  rtn = count;
405  else
406  error = remapError();
407 
408  return rtn;
409 }
410 
411 int fsys::sync(void)
412 {
413  return 0;
414 }
415 
416 fd_t fsys::input(const char *path)
417 {
418  SECURITY_ATTRIBUTES sattr;
419 
420  sattr.nLength = sizeof(SECURITY_ATTRIBUTES);
421  sattr.bInheritHandle = TRUE;
422  sattr.lpSecurityDescriptor = NULL;
423 
424  return CreateFile(path, GENERIC_READ, FILE_SHARE_READ, &sattr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
425 }
426 
427 fd_t fsys::output(const char *path)
428 {
429  SECURITY_ATTRIBUTES sattr;
430 
431  sattr.nLength = sizeof(SECURITY_ATTRIBUTES);
432  sattr.bInheritHandle = TRUE;
433  sattr.lpSecurityDescriptor = NULL;
434 
435  return CreateFile(path, GENERIC_WRITE, 0, &sattr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
436 }
437 
438 fd_t fsys::append(const char *path)
439 {
440  SECURITY_ATTRIBUTES sattr;
441 
442  sattr.nLength = sizeof(SECURITY_ATTRIBUTES);
443  sattr.bInheritHandle = TRUE;
444  sattr.lpSecurityDescriptor = NULL;
445 
446  fd_t fd = CreateFile(path, GENERIC_WRITE, 0, &sattr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
447 
448  if(fd != INVALID_HANDLE_VALUE)
449  SetFilePointer(fd, 0, NULL, FILE_END);
450 
451  return fd;
452 }
453 
454 void fsys::release(fd_t fd)
455 {
456  CloseHandle(fd);
457 }
458 
459 void dir::open(const char *path)
460 {
461  close();
462  error = 0;
463 
464  char tpath[256];
465  DWORD attr = GetFileAttributes(path);
466 
467  if((attr == (DWORD)~0l) || !(attr & FILE_ATTRIBUTE_DIRECTORY)) {
468  error = ENOTDIR;
469  return;
470  }
471 
472  snprintf(tpath, sizeof(tpath), "%s%s", path, "\\*");
473  ptr = new WIN32_FIND_DATA;
474  fd = FindFirstFile(tpath, ptr);
475  if(fd == INVALID_HANDLE_VALUE) {
476  delete ptr;
477  ptr = NULL;
478  error = remapError();
479  }
480  return;
481 }
482 
483 void fsys::open(const char *path, access_t access)
484 {
485  bool append = false;
486  DWORD amode = 0;
487  DWORD smode = 0;
488  DWORD attr = FILE_ATTRIBUTE_NORMAL;
489  char buf[128];
490 
491  close();
492  error = 0;
493 
494  if(access == DEVICE) {
495 #ifdef _MSWINDOWS_
496  if(isalpha(path[0]) && path[1] == ':') {
497  if(!QueryDosDevice(path, buf, sizeof(buf))) {
498  error = ENODEV;
499  return;
500  }
501  path = buf;
502  }
503 #else
504  if(!strchr(path, '/')) {
505  if(path[0] == 'S' && isdigit(path[1]))
506  snprintf(buf, sizeof(buf) "/dev/tty%s", path);
507  else if(strncmp(path, "USB", 3))
508  snprintf(buf, sizeof(buf), "/dev/tty%s", path);
509  else
510  snprintf(buf, sizeof(buf), "/dev/%s", path);
511 
512  char *cp = strchr(buf, ':');
513  if(cp)
514  *cp = 0;
515  path = buf;
516  }
517 #endif
518  if(!is_device(buf)) {
519  error = ENODEV;
520  return;
521  }
522  }
523 
524  switch(access)
525  {
526  case STREAM:
527 #ifdef FILE_FLAG_SEQUENTIAL_SCAN
528  attr |= FILE_FLAG_SEQUENTIAL_SCAN;
529 #endif
530  case RDONLY:
531  amode = GENERIC_READ;
532  smode = FILE_SHARE_READ;
533  break;
534  case WRONLY:
535  amode = GENERIC_WRITE;
536  break;
537  case DEVICE:
538  smode = FILE_SHARE_READ;
539  attr |= FILE_FLAG_WRITE_THROUGH | FILE_FLAG_NO_BUFFERING;
540  case EXCLUSIVE:
541  amode = GENERIC_READ | GENERIC_WRITE;
542  break;
543  case RANDOM:
544  attr |= FILE_FLAG_RANDOM_ACCESS;
545  case REWRITE:
546  amode = GENERIC_READ | GENERIC_WRITE;
547  smode = FILE_SHARE_READ;
548  break;
549  case APPEND:
550  amode = GENERIC_WRITE;
551  append = true;
552  break;
553  case SHARED:
554  amode = GENERIC_READ | GENERIC_WRITE;
555  smode = FILE_SHARE_READ | FILE_SHARE_WRITE;
556  break;
557  }
558 
559  fd = CreateFile(path, amode, smode, NULL, OPEN_EXISTING, attr, NULL);
560  if(fd != INVALID_HANDLE_VALUE && append)
561  seek(end);
562  else if(fd == INVALID_HANDLE_VALUE)
563  error = remapError();
564 }
565 
566 void fsys::open(const char *path, unsigned fmode, access_t access)
567 {
568  bool append = false;
569  DWORD amode = 0;
570  DWORD cmode = 0;
571  DWORD smode = 0;
572  DWORD attr = FILE_ATTRIBUTE_NORMAL;
573 
574  fmode &= 0666;
575 
576  close();
577  error = 0;
578 
579  const char *cp = strrchr(path, '\\');
580  const char *cp2 = strrchr(path, '/');
581  if(cp2 > cp)
582  cp = cp2;
583 
584  if(!cp)
585  cp = path;
586  else
587  ++cp;
588 
589  if(*cp == '.')
590  attr = FILE_ATTRIBUTE_HIDDEN;
591 
592  switch(access)
593  {
594  case DEVICE:
595  error = ENOSYS;
596  return;
597 
598  case RDONLY:
599  amode = GENERIC_READ;
600  cmode = OPEN_ALWAYS;
601  smode = FILE_SHARE_READ;
602  break;
603  case STREAM:
604  case WRONLY:
605  amode = GENERIC_WRITE;
606  cmode = CREATE_ALWAYS;
607  break;
608  case EXCLUSIVE:
609  amode = GENERIC_READ | GENERIC_WRITE;
610  cmode = OPEN_ALWAYS;
611  break;
612  case RANDOM:
613  attr |= FILE_FLAG_RANDOM_ACCESS;
614  case REWRITE:
615  amode = GENERIC_READ | GENERIC_WRITE;
616  cmode = OPEN_ALWAYS;
617  smode = FILE_SHARE_READ;
618  break;
619  case APPEND:
620  amode = GENERIC_WRITE;
621  cmode = OPEN_ALWAYS;
622  append = true;
623  break;
624  case SHARED:
625  amode = GENERIC_READ | GENERIC_WRITE;
626  cmode = OPEN_ALWAYS;
627  smode = FILE_SHARE_READ | FILE_SHARE_WRITE;
628  break;
629  }
630  fd = CreateFile(path, amode, smode, NULL, cmode, attr, NULL);
631  if(fd != INVALID_HANDLE_VALUE && append)
632  seek(end);
633  else if(fd == INVALID_HANDLE_VALUE)
634  error = remapError();
635  if(fd != INVALID_HANDLE_VALUE)
636  mode(path, fmode);
637 }
638 
639 fsys::fsys(const fsys& copy)
640 {
641  error = 0;
643 
644  if(copy.fd == INVALID_HANDLE_VALUE)
645  return;
646 
647  HANDLE pHandle = GetCurrentProcess();
648  if(!DuplicateHandle(pHandle, copy.fd, pHandle, &fd, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
650  error = remapError();
651  }
652 }
653 
654 int fsys::inherit(fd_t& from, bool enable)
655 {
656  HANDLE pHandle = GetCurrentProcess();
657 
658  if(!enable) {
659  if(!SetHandleInformation(from, HANDLE_FLAG_INHERIT, 0))
660  return remapError();
661  return 0;
662  }
663 
664  fd_t fd;
665  if(DuplicateHandle(pHandle, from, pHandle, &fd, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
666  release(from);
667  from = fd;
668  return 0;
669  }
670 
671  return remapError();
672 }
673 
674 fsys& fsys::operator=(fd_t from)
675 {
676  HANDLE pHandle = GetCurrentProcess();
677 
678  if(fd != INVALID_HANDLE_VALUE) {
679  if(!CloseHandle(fd)) {
680  error = remapError();
681  return *this;
682  }
683  }
684  if(DuplicateHandle(pHandle, from, pHandle, &fd, 0, FALSE, DUPLICATE_SAME_ACCESS))
685  error = 0;
686  else {
688  error = remapError();
689  }
690  return *this;
691 }
692 
693 fsys& fsys::operator=(const fsys& from)
694 {
695  HANDLE pHandle = GetCurrentProcess();
696 
697  if(fd != INVALID_HANDLE_VALUE) {
698  if(!CloseHandle(fd)) {
699  error = remapError();
700  return *this;
701  }
702  }
703  if(DuplicateHandle(pHandle, from.fd, pHandle, &fd, 0, FALSE, DUPLICATE_SAME_ACCESS))
704  error = 0;
705  else {
707  error = remapError();
708  }
709  return *this;
710 }
711 
712 int fsys::drop(offset_t size)
713 {
714  error = ENOSYS;
715  return ENOSYS;
716 }
717 
718 int fsys::seek(offset_t pos)
719 {
720  DWORD rpos = pos;
721  int mode = FILE_BEGIN;
722 
723  if(rpos == (DWORD)end) {
724  rpos = 0;
725  mode = FILE_END;
726  }
727  if(SetFilePointer(fd, rpos, NULL, mode) == INVALID_SET_FILE_POINTER) {
728  error = remapError();
729  return error;
730  }
731  return 0;
732 }
733 
734 #else
735 
736 ssize_t dir::read(char *buf, size_t len)
737 {
738  if(ptr) {
739  dirent *entry = ::readdir((DIR *)ptr);
740 
741  if(!entry)
742  return 0;
743 
744  String::set((char *)buf, len, entry->d_name);
745  return strlen(entry->d_name);
746  }
747  return -1;
748 }
749 
750 ssize_t fsys::read(void *buf, size_t len)
751 {
752  int rtn = ::read(fd, buf, len);
753 
754  if(rtn < 0)
755  error = remapError();
756  return rtn;
757 }
758 
759 int fsys::sync(void)
760 {
761  int rtn = ::fsync(fd);
762  if(rtn < 0)
763  error = remapError();
764  else
765  return 0;
766  return error;
767 }
768 
769 ssize_t fsys::write(const void *buf, size_t len)
770 {
771  int rtn = ::write(fd, buf, len);
772 
773  if(rtn < 0)
774  error = remapError();
775  return rtn;
776 }
777 
779 {
780  return ::open("/dev/null", O_RDWR);
781 }
782 
783 int fsys::pipe(fd_t& input, fd_t& output, size_t size)
784 {
785  input = output = -1;
786  int pfd[2];
787  if(::pipe(pfd))
788  return remapError();
789  input = pfd[0];
790  output = pfd[1];
791  return 0;
792 }
793 
795 {
796  if(isatty(fd))
797  return true;
798  return false;
799 }
800 
801 bool fsys::is_tty(void) const
802 {
803  if(isatty(fd))
804  return true;
805  return false;
806 }
807 
808 void dir::close(void)
809 {
810  error = 0;
811  if(ptr) {
812  if(::closedir((DIR *)ptr))
813  error = remapError();
814  ptr = NULL;
815  }
816  else
817  error = EBADF;
818 }
819 
820 int fsys::close(void)
821 {
822  error = 0;
823  if(fd != INVALID_HANDLE_VALUE) {
824  if(::close(fd) == 0)
826  else
827  error = remapError();
828  }
829  else
830  return EBADF; // not opened, but state still error free
831  return error;
832 }
833 
834 fd_t fsys::input(const char *path)
835 {
836  return ::open(path, O_RDONLY);
837 }
838 
839 fd_t fsys::output(const char *path)
840 {
841  return ::open(path, O_WRONLY | O_CREAT | O_TRUNC, EVERYONE);
842 }
843 
844 fd_t fsys::append(const char *path)
845 {
846  return ::open(path, O_WRONLY | O_CREAT | O_APPEND, EVERYONE);
847 }
848 
850 {
851  ::close(fd);
852 }
853 
854 void fsys::open(const char *path, unsigned fmode, access_t access)
855 {
856  unsigned flags = 0;
857 
858  close();
859  error = 0;
860 
861  switch(access)
862  {
863  case DEVICE:
864  error = ENOSYS;
865  return;
866 
867  case RDONLY:
868  flags = O_RDONLY | O_CREAT;
869  break;
870  case STREAM:
871  case WRONLY:
872  flags = O_WRONLY | O_CREAT | O_TRUNC;
873  break;
874  case RANDOM:
875  case SHARED:
876  case REWRITE:
877  case EXCLUSIVE:
878  flags = O_RDWR | O_CREAT;
879  break;
880  case APPEND:
881  flags = O_RDWR | O_APPEND | O_CREAT;
882  break;
883  }
884  fd = ::open(path, flags, fmode);
885  if(fd == INVALID_HANDLE_VALUE)
886  error = remapError();
887 #ifdef HAVE_POSIX_FADVISE
888  else {
889  if(access == RANDOM)
890  posix_fadvise(fd, (off_t)0, (off_t)0, POSIX_FADV_RANDOM);
891  }
892 #endif
893 }
894 
895 int dir::create(const char *path, unsigned perms)
896 {
897  if(perms & 06)
898  perms |= 01;
899  if(perms & 060)
900  perms |= 010;
901  if(perms & 0600)
902  perms |= 0100;
903 
904  if(::mkdir(path, perms))
905  return remapError();
906  return 0;
907 }
908 
909 void dir::open(const char *path)
910 {
911  close();
912  error = 0;
913 
914  ptr = opendir(path);
915  if(!ptr)
916  error = remapError();
917 }
918 
919 void fsys::open(const char *path, access_t access)
920 {
921  unsigned flags = 0;
922 
923  close();
924  error = 0;
925 
926  switch(access)
927  {
928  case STREAM:
929 #if defined(O_STREAMING)
930  flags = O_RDONLY | O_STREAMING;
931  break;
932 #endif
933  case RDONLY:
934  flags = O_RDONLY;
935  break;
936  case WRONLY:
937  flags = O_WRONLY;
938  break;
939  case EXCLUSIVE:
940  case RANDOM:
941  case SHARED:
942  case REWRITE:
943  case DEVICE:
944  flags = O_RDWR | O_NONBLOCK;
945  break;
946  case APPEND:
947  flags = O_RDWR | O_APPEND;
948  break;
949  }
950  fd = ::open(path, flags);
951  if(fd == INVALID_HANDLE_VALUE) {
952  error = remapError();
953  return;
954  }
955 #ifdef HAVE_POSIX_FADVISE
956  // Linux kernel bug prevents use of POSIX_FADV_NOREUSE in streaming...
957  if(access == STREAM)
958  posix_fadvise(fd, (off_t)0, (off_t)0, POSIX_FADV_SEQUENTIAL);
959  else if(access == RANDOM)
960  posix_fadvise(fd, (off_t)0, (off_t)0, POSIX_FADV_RANDOM);
961 #endif
962  if(access == DEVICE) {
963  flags = fcntl(fd, F_GETFL);
964  flags &= ~O_NONBLOCK;
965  fcntl(fd, F_SETFL, flags);
966  }
967 }
968 
969 int fsys::info(const char *path, struct stat *ino)
970 {
971  if(::stat(path, ino))
972  return remapError();
973  return 0;
974 }
975 
976 #ifdef HAVE_FTRUNCATE
977 int fsys::trunc(offset_t offset)
978 {
979  if(fsys::seek(offset) != 0)
980  return remapError();
981 
982  if(::ftruncate(fd, offset) == 0)
983  return 0;
984  return remapError();
985 }
986 #else
988 {
989  if(fsys::seek(offset) != 0)
990  return remapError();
991 
992  return ENOSYS;
993 }
994 #endif
995 
996 int fsys::info(struct stat *ino)
997 {
998  if(::fstat(fd, ino)) {
999  error = remapError();
1000  return error;
1001  }
1002  return 0;
1003 }
1004 
1005 int fsys::prefix(const char *path)
1006 {
1007  if(::chdir(path))
1008  return remapError();
1009  return 0;
1010 }
1011 
1012 int fsys::prefix(char *path, size_t len)
1013 {
1014  if(NULL == ::getcwd(path, len))
1015  return remapError();
1016  return 0;
1017 }
1018 
1019 int fsys::mode(const char *path, unsigned value)
1020 {
1021  if(::chmod(path, value))
1022  return remapError();
1023  return 0;
1024 }
1025 
1026 bool fsys::is_exists(const char *path)
1027 {
1028  if(::access(path, F_OK))
1029  return false;
1030 
1031  return true;
1032 }
1033 
1034 bool fsys::is_readable(const char *path)
1035 {
1036  if(::access(path, R_OK))
1037  return false;
1038 
1039  return true;
1040 }
1041 
1042 bool fsys::is_writable(const char *path)
1043 {
1044  if(::access(path, W_OK))
1045  return false;
1046 
1047  return true;
1048 }
1049 
1050 bool fsys::is_executable(const char *path)
1051 {
1052  if(is_dir(path))
1053  return false;
1054 
1055  if(::access(path, X_OK))
1056  return false;
1057 
1058  return true;
1059 }
1060 
1062 {
1064  error = 0;
1065 
1066  if(copy.fd != INVALID_HANDLE_VALUE) {
1067  fd = ::dup(copy.fd);
1068  }
1069  else
1071 }
1072 
1073 int fsys::inherit(fd_t& fd, bool enable)
1074 {
1075  unsigned long flags;
1076  if(fd > -1) {
1077  flags = fcntl(fd, F_GETFL);
1078  if(enable)
1079  flags &= ~FD_CLOEXEC;
1080  else
1081  flags |= FD_CLOEXEC;
1082  if(fcntl(fd, F_SETFL, flags))
1083  return remapError();
1084  }
1085  return 0;
1086 }
1087 
1089 {
1090  close();
1091  if(fd == INVALID_HANDLE_VALUE && from != INVALID_HANDLE_VALUE) {
1092  fd = ::dup(from);
1093  if(fd == INVALID_HANDLE_VALUE)
1094  error = remapError();
1095  }
1096  return *this;
1097 }
1098 
1100 {
1101  close();
1102  if(fd == INVALID_HANDLE_VALUE && from.fd != INVALID_HANDLE_VALUE) {
1103  fd = ::dup(from.fd);
1104  if(fd == INVALID_HANDLE_VALUE)
1105  error = remapError();
1106  }
1107  return *this;
1108 }
1109 
1111 {
1112 #ifdef HAVE_POSIX_FADVISE
1113  if(posix_fadvise(fd, (off_t)0, size, POSIX_FADV_DONTNEED)) {
1114  error = remapError();
1115  return error;
1116  }
1117  return 0;
1118 #else
1119  error = ENOSYS;
1120  return ENOSYS;
1121 #endif
1122 }
1123 
1125 {
1126  unsigned long rpos = pos;
1127  int mode = SEEK_SET;
1128 
1129  if(rpos == (unsigned long)end) {
1130  rpos = 0;
1131  mode = SEEK_END;
1132  }
1133  if(lseek(fd, rpos, mode) == ~0l) {
1134  error = remapError();
1135  return error;
1136  }
1137  return 0;
1138 }
1139 
1140 #endif
1141 
1143 {
1144  ptr = 0;
1145  error = 0;
1146 }
1147 
1148 dso::dso(const char *path)
1149 {
1150  ptr = 0;
1151  error = 0;
1152  map(path);
1153 }
1154 
1156 {
1157  release();
1158 }
1159 
1161 fsys()
1162 {
1163  ptr = NULL;
1164 }
1165 
1167 {
1168  close();
1169 }
1170 
1172 {
1174  error = 0;
1175 }
1176 
1177 dir::dir(const char *path) :
1178 fsys()
1179 {
1180  ptr = NULL;
1181  open(path);
1182 }
1183 
1184 fsys::fsys(const char *path, access_t access)
1185 {
1187  open(path, access);
1188 }
1189 
1190 fsys::fsys(const char *path, unsigned fmode, access_t access)
1191 {
1193  open(path, fmode, access);
1194 }
1195 
1197 {
1198  close();
1199 }
1200 
1202 {
1203  if(fd != INVALID_HANDLE_VALUE)
1204  close();
1205  fd = from;
1206  from = INVALID_HANDLE_VALUE;
1207  return *this;
1208 }
1209 
1210 int fsys::linkinfo(const char *path, char *buffer, size_t size)
1211 {
1212 #if defined(_MSWINDOWS_)
1213  HANDLE h;
1214  DWORD rsize;
1215  char *reparse = (char *)_malloca(MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
1216  if (!reparse)
1217  return EINVAL;
1218 
1219  if(!fsys::is_link(path))
1220  return EINVAL;
1221 
1222  h = CreateFile(path, GENERIC_READ, 0, 0, OPEN_EXISTING,
1223  FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0);
1224 
1225  if(!h || h == INVALID_HANDLE_VALUE)
1226  return EINVAL;
1227 
1228  memset(reparse, 0, MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
1229  LOCAL_REPARSE_DATA_BUFFER *rb = (LOCAL_REPARSE_DATA_BUFFER*)&reparse;
1230 
1231  if(!DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, NULL, 0, (LPVOID *)rb, MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &rsize, 0)) {
1232  CloseHandle(h);
1233  return remapError();
1234  }
1235 
1236 #ifdef UNICODE
1237  String::set(buffer, size, rb.PathBuffer);
1238 #else
1239  WideCharToMultiByte(CP_THREAD_ACP, 0, rb->PathBuffer, rb->SubstituteNameLength / sizeof(WCHAR) + 1, buffer, (int)size, "", FALSE);
1240 #endif
1241  CloseHandle(h);
1242  return 0;
1243 #elif defined(HAVE_READLINK)
1244  if(::readlink(path, buffer, size))
1245  return remapError();
1246  return 0;
1247 #else
1248  return EINVAL;
1249 #endif
1250 }
1251 
1252 int fsys::hardlink(const char *path, const char *target)
1253 {
1254 #ifdef _MSWINDOWS_
1255  if(!CreateHardLink(target, path, NULL))
1256  return remapError();
1257  return 0;
1258 #else
1259  if(::link(path, target))
1260  return remapError();
1261  return 0;
1262 #endif
1263 }
1264 
1265 int fsys::link(const char *path, const char *target)
1266 {
1267 #if defined(_MSWINDOWS_)
1268  TCHAR dest[512];
1269  HANDLE h;
1270  char *part;
1271  DWORD size;
1272  WORD len;
1273  char *reparse = (char *)_malloca(MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
1274  if (!reparse)
1275  return EINVAL;
1276 
1277  lstrcpy(dest, "\\??\\");
1278  dest[4] = 0;
1279  if(!GetFullPathName(path, sizeof(dest) - (4 * sizeof(TCHAR)), &dest[4], &part) || GetFileAttributes(&dest[4]) == INVALID_FILE_ATTRIBUTES)
1280  return remapError();
1281 
1282  LOCAL_REPARSE_DATA_BUFFER *rb = (LOCAL_REPARSE_DATA_BUFFER*)&reparse;
1283  memset(rb, 0, MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
1284 
1285  if(!MultiByteToWideChar(CP_THREAD_ACP, MB_PRECOMPOSED, dest, lstrlenA(dest) + 1, rb->PathBuffer, lstrlenA(dest) + 1))
1286  return remapError();
1287 
1288  len = lstrlenW(rb->PathBuffer) * 2;
1289  rb->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
1290  rb->ReparseDataLength = len + 12;
1291  rb->SubstituteNameLength = len;
1292  rb->PrintNameOffset = len + 2;
1293  h = CreateFile(target, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
1294  FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0);
1295  if(!h || h == INVALID_HANDLE_VALUE)
1296  return hardlink(path, target);
1297  if(!DeviceIoControl(h, FSCTL_SET_REPARSE_POINT, (LPVOID)rb, rb->ReparseDataLength + FIELD_OFFSET(LOCAL_REPARSE_DATA_BUFFER, SubstituteNameOffset), NULL, 0, &size, 0)) {
1298  CloseHandle(h);
1299  return hardlink(path, target);
1300  }
1301  CloseHandle(h);
1302  return 0;
1303 #elif defined(HAVE_SYMLINK)
1304  if(::symlink(path, target))
1305  return remapError();
1306  return 0;
1307 #else
1308  if(::link(path, target))
1309  return remapError();
1310  return 0;
1311 #endif
1312 }
1313 
1314 int fsys::unlink(const char *path)
1315 {
1316 #ifdef _MSWINDOWS_
1317  HANDLE h = INVALID_HANDLE_VALUE;
1318  if(is_link(path))
1319  h = CreateFile(path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
1320  FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0);
1321  if(h && h != INVALID_HANDLE_VALUE) {
1322  REPARSE_GUID_DATA_BUFFER rb;
1323  memset(&rb, 0, sizeof(rb));
1324  DWORD size;
1325  rb.ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
1326  if(!DeviceIoControl(h, FSCTL_DELETE_REPARSE_POINT, &rb,
1327  REPARSE_GUID_DATA_BUFFER_HEADER_SIZE, NULL, 0, &size, 0)) {
1328  CloseHandle(h);
1329  return remapError();
1330  }
1331  CloseHandle(h);
1332  ::remove(path);
1333  return 0;
1334  }
1335 #endif
1336  if(::remove(path))
1337  return remapError();
1338  return 0;
1339 }
1340 
1341 int fsys::erase(const char *path)
1342 {
1343  if(is_device(path))
1344  return ENOSYS;
1345 
1346  if(::remove(path))
1347  return remapError();
1348  return 0;
1349 }
1350 
1351 int dir::remove(const char *path)
1352 {
1353  if(is_device(path))
1354  return ENOSYS;
1355 
1356 #ifdef _MSWINDOWS_
1357  if(RemoveDirectory(path))
1358  return 0;
1359  int error = remapError();
1360  if(error == ENOTEMPTY)
1361  return ENOTEMPTY;
1362 #else
1363  if(!::rmdir(path))
1364  return 0;
1365  if(errno != ENOTDIR)
1366  return errno;
1367 #endif
1368 
1369  if(::remove(path))
1370  return remapError();
1371  return 0;
1372 }
1373 
1374 int fsys::copy(const char *oldpath, const char *newpath, size_t size)
1375 {
1376  int result = 0;
1377  char *buffer = new char[size];
1378  fsys src, dest;
1379  ssize_t count = (ssize_t)size;
1380 
1381  if(!buffer) {
1382  result = ENOMEM;
1383  goto end;
1384  }
1385 
1386  remove(newpath);
1387 
1388  src.open(oldpath, fsys::STREAM);
1389  if(!is(src))
1390  goto end;
1391 
1392  dest.open(newpath, GROUP_PUBLIC, fsys::STREAM);
1393  if(!is(dest))
1394  goto end;
1395 
1396  while(count > 0) {
1397  count = src.read(buffer, size);
1398  if(count < 0) {
1399  result = src.err();
1400  goto end;
1401  }
1402  if(count > 0)
1403  count = dest.write(buffer, size);
1404  if(count < 0) {
1405  result = dest.err();
1406  goto end;
1407  }
1408  }
1409 
1410 end:
1411  if(is(src))
1412  src.close();
1413 
1414  if(is(dest))
1415  dest.close();
1416 
1417  if(buffer)
1418  delete[] buffer;
1419 
1420  if(result != 0)
1421  remove(newpath);
1422 
1423  return result;
1424 }
1425 
1426 int fsys::rename(const char *oldpath, const char *newpath)
1427 {
1428  if(::rename(oldpath, newpath))
1429  return remapError();
1430  return 0;
1431 }
1432 
1433 int fsys::load(const char *path)
1434 {
1435  dso module;
1436 
1437  module.map(path);
1438 #ifdef _MSWINDOWS_
1439  if(module.ptr) {
1440  module.ptr = 0;
1441  return 0;
1442  }
1443  return remapError();
1444 #else
1445  if(module.ptr) {
1446  module.ptr = 0;
1447  return 0;
1448  }
1449  return module.error;
1450 #endif
1451 }
1452 
1453 bool fsys::is_file(const char *path)
1454 {
1455 #ifdef _MSWINDOWS_
1456  DWORD attr = GetFileAttributes(path);
1457  if(attr == (DWORD)~0l)
1458  return false;
1459 
1460  if(attr & FILE_ATTRIBUTE_DIRECTORY)
1461  return false;
1462 
1463  return true;
1464 
1465 #else
1466  struct stat ino;
1467 
1468  if(::stat(path, &ino))
1469  return false;
1470 
1471  if(S_ISREG(ino.st_mode))
1472  return true;
1473 
1474  return false;
1475 #endif
1476 }
1477 
1478 bool fsys::is_link(const char *path)
1479 {
1480 #if defined(_MSWINDOWS_)
1481  DWORD attr = GetFileAttributes(path);
1482  if (attr == 0xffffffff || !(attr & FILE_ATTRIBUTE_REPARSE_POINT))
1483  return false;
1484  return true;
1485 #elif defined(HAVE_LSTAT)
1486  struct stat ino;
1487 
1488  if(::lstat(path, &ino))
1489  return false;
1490 
1491  if(S_ISLNK(ino.st_mode))
1492  return true;
1493 
1494  return false;
1495 #else
1496  return false;
1497 #endif
1498 }
1499 
1500 bool fsys::is_dir(const char *path)
1501 {
1502 #ifdef _MSWINDOWS_
1503  DWORD attr = GetFileAttributes(path);
1504  if(attr == (DWORD)~0l)
1505  return false;
1506 
1507  if(attr & FILE_ATTRIBUTE_DIRECTORY)
1508  return true;
1509 
1510  return false;
1511 
1512 #else
1513  struct stat ino;
1514 
1515  if(::stat(path, &ino))
1516  return false;
1517 
1518  if(S_ISDIR(ino.st_mode))
1519  return true;
1520 
1521  return false;
1522 #endif
1523 }
1524 
1525 #ifdef _MSWINDOWS_
1526 
1527 void dso::map(const char *path)
1528 {
1529  error = 0;
1530  ptr = LoadLibrary(path);
1531  if(!ptr)
1532  error = ENOEXEC;
1533 }
1534 
1535 void dso::release(void)
1536 {
1537  if(ptr)
1538  FreeLibrary(ptr);
1539  ptr = 0;
1540 }
1541 
1542 dso::addr_t dso::find(const char *sym) const
1543 {
1544  if(ptr == 0)
1545  return (dso::addr_t)NULL;
1546 
1547  return (addr_t)GetProcAddress(ptr, sym);
1548 }
1549 
1550 #elif defined(HAVE_DLFCN_H)
1551 #include <dlfcn.h>
1552 
1553 #ifndef RTLD_GLOBAL
1554 #define RTLD_GLOBAL 0
1555 #endif
1556 
1557 void dso::map(const char *path)
1558 {
1559  error = 0;
1560  ptr = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
1561  if(ptr == NULL)
1562  error = ENOEXEC;
1563 }
1564 
1565 void dso::release(void)
1566 {
1567  if(ptr)
1568  dlclose(ptr);
1569  ptr = NULL;
1570 }
1571 
1572 dso::addr_t dso::find(const char *sym) const
1573 {
1574  if(!ptr)
1575  return (dso::addr_t)NULL;
1576 
1577  return (dso::addr_t)dlsym(ptr, (char *)sym);
1578 }
1579 
1580 #elif HAVE_MACH_O_DYLD_H
1581 #include <mach-o/dyld.h>
1582 
1583 void dso::map(const char *path)
1584 {
1585  NSObjectFileImage oImage;
1586  NSSymbol sym = NULL;
1587  NSModule mod;
1588  void (*init)(void);
1589 
1590  ptr = NULL;
1591  error = 0;
1592 
1593  if(NSCreateObjectFileImageFromFile(path, &oImage) != NSObjectFileImageSuccess) {
1594  error = ENOEXEC;
1595  return;
1596  }
1597 
1598  mod = NSLinkModule(oImage, path, NSLINKMODULE_OPTION_BINDNOW | NSLINKMODULE_OPTION_RETURN_ON_ERROR);
1599  NSDestroyObjectFileImage(oImage);
1600  if(mod == NULL) {
1601  error = ENOEXEC;
1602  return;
1603  }
1604 
1605  sym = NSLookupSymbolInModule(mod, "__init");
1606  if(sym) {
1607  init = (void (*)(void))NSAddressOfSymbol(sym);
1608  init();
1609  }
1610  ptr = (void *)mod;
1611 }
1612 
1613 void dso::release(void)
1614 {
1615  if(!ptr)
1616  return;
1617 
1618  NSModule mod = (NSModule)ptr;
1619  NSSymbol sym;
1620  void (*fini)(void);
1621  ptr = NULL;
1622 
1623  sym = NSLookupSymbolInModule(mod, "__fini");
1624  if(sym != NULL) {
1625  fini = (void (*)(void))NSAddressOfSymbol(sym);
1626  fini();
1627  }
1628  NSUnlinkModule(mod, NSUNLINKMODULE_OPTION_NONE);
1629 }
1630 
1631 dso::addr_t dso::find(const char *sym) const
1632 {
1633  if(!ptr)
1634  return NULL;
1635 
1636  NSModule mod = (NSModule)ptr;
1637  NSSymbol sym;
1638 
1639  sym = NSLookupSymbolInModule(mod, sym);
1640  if(sym != NULL) {
1641  return (dso::addr_t)NSAddressOfSymbol(sym);
1642 
1643  return (dso::addr_t)NULL;
1644 }
1645 
1646 #elif HAVE_SHL_LOAD
1647 #include <dl.h>
1648 
1649 void dso::map(const char *path)
1650 {
1651  error = 0;
1652  ptr = (void *)shl_load(path, BIND_IMMEDIATE, 0l);
1653  if(!ptr)
1654  error = ENOEXEC;
1655 }
1656 
1657 dso::addr_t dso::find(const char *sym) const
1658 {
1659  if(!ptr)
1660  return (dso::addr_t)NULL;
1661 
1662  shl_t image = (shl_t)ptr;
1663 
1664  if(shl_findsym(&image, sym, 0, &value) == 0)
1665  return (dso::addr_t)value;
1666 
1667  return (dso::addr_t)NULL;
1668 }
1669 
1670 void dso::release(void)
1671 {
1672  shl_t image = (shl_t)ptr;
1673  if(ptr)
1674  shl_unload(image);
1675  ptr = NULL;
1676 }
1677 
1678 #else
1679 
1680 void fsys::map(const char *path)
1681 {
1682  error = ENOEXEC;
1683  ptr = NULL;
1684 }
1685 
1686 void dso::release(void)
1687 {
1688 }
1689 
1690 dso::addr_t dso::find(const char *sym) const
1691 {
1692  return (dso::addr_t)NULL;
1693 }
1694 
1695 #endif
1696 
1697 bool fsys::is_device(const char *path)
1698 {
1699  if(!path)
1700  return false;
1701 
1702 #ifndef _MSWINDOWS_
1703  if(is_dir(path))
1704  return false;
1705 
1706  if(!strncmp(path, "/dev/", 5))
1707  return true;
1708 
1709  return false;
1710 #else
1711  if(path[1] == ':' && !path[2] && isalpha(*path))
1712  return true;
1713 
1714  if(!strncmp(path, "com", 3) || !strncmp(path, "lpt", 3)) {
1715  path += 3;
1716  while(isdigit(*path))
1717  ++path;
1718  if(!path || *path == ':')
1719  return true;
1720  return false;
1721  }
1722 
1723  if(!strcmp(path, "aux") || !strcmp(path, "prn")) {
1724  if(!path[3] || path[3] == ':')
1725  return true;
1726  return false;
1727  }
1728 
1729  if(!strncmp(path, "\\\\.\\", 4))
1730  return true;
1731 
1732  if(!strnicmp(path, "\\\\?\\Device\\", 12))
1733  return true;
1734 
1735  return false;
1736 
1737 #endif
1738 }
1739 
1740 bool fsys::is_hidden(const char *path)
1741 {
1742 #ifdef _MSWINDOWS_
1743  DWORD attr = GetFileAttributes(path);
1744  if(attr == (DWORD)~0l)
1745  return false;
1746 
1747  return ((attr & FILE_ATTRIBUTE_HIDDEN) != 0);
1748 #else
1749  const char *cp = strrchr(path, '/');
1750  if(cp)
1751  ++cp;
1752  else
1753  cp = path;
1754 
1755  if(*cp == '.')
1756  return true;
1757 
1758  return false;
1759 #endif
1760 }
1761 
1763 {
1764  fd = handle;
1765  error = 0;
1766 }
1767 
1768 void fsys::set(fd_t handle)
1769 {
1770  close();
1771  fd = handle;
1772  error = 0;
1773 }
1774 
1776 {
1777  fd_t save = fd;
1778 
1779  fd = INVALID_HANDLE_VALUE;
1780  error = 0;
1781  return save;
1782 }
1783 
1784 int fsys::exec(const char *path, char **argv, char **envp)
1785 {
1786  shell::pid_t pid = shell::spawn(path, argv, envp);
1787  return shell::wait(pid);
1788 }
1789 
1790 #ifdef _MSWINDOWS_
1791 
1793 {
1794  char *cp = _getcwd(NULL, 0);
1795  stringref_t result(cp);
1796  if(cp)
1797  ::free(cp);
1798  return result;
1799 }
1800 
1801 #else
1802 
1804 {
1805  size_t size = 40;
1807  stringref_t out;
1808  for(;;) {
1809  if(NULL != (getcwd(buf->get(), buf->max())))
1810  break;
1811  if(errno != ERANGE) {
1812  *(buf->get()) = 0;
1813  break;
1814  }
1815  stringref<auto_release>::expand(&buf, size);
1816  size += 40;
1817  }
1818  out.assign(buf);
1819  return out;
1820 }
1821 
1822 #endif
1823 
1824 } // namespace ucommon
ucommon::fsys::APPEND
Definition: fsys.h:165
ucommon::fsys::write
ssize_t write(const void *buffer, size_t count)
Definition: fsys.cpp:769
ucommon::shell::spawn
static shell::pid_t spawn(const char *path, char **argv, char **env=NULL, fd_t *stdio=NULL)
Definition: shell.cpp:2012
strnicmp
int strnicmp(const char *s1, const char *s2, size_t size)
Definition: cpr.cpp:104
ucommon::fsys::REWRITE
Definition: fsys.h:163
export.h
S_ISLNK
#define S_ISLNK(mode)
Definition: fsys.h:107
ucommon::fsys::access_t
access_t
Definition: fsys.h:160
fd_t
int fd_t
Definition: platform.h:415
out
static shell::stringopt out('o', "--output", _TEXT("output file"), "filename", "-")
ucommon::fsys::link
static int link(const char *path, const char *target)
Definition: fsys.cpp:1265
ucommon::eq_case
bool eq_case(char const *s1, char const *s2)
Definition: string.h:1699
ucommon::fsys::read
ssize_t read(void *buffer, size_t count)
Definition: fsys.cpp:750
ucommon::fsys::is_readable
static bool is_readable(const char *path)
Definition: fsys.cpp:1034
ucommon
Definition: access.cpp:23
init
T * init(T *memory)
Definition: platform.h:551
ucommon::fsys::is_link
static bool is_link(const char *path)
Definition: fsys.cpp:1478
ucommon::fsys::unlink
static int unlink(const char *path)
Definition: fsys.cpp:1314
ucommon::fsys::sync
int sync(void)
Definition: fsys.cpp:759
ucommon::fsys::is_tty
bool is_tty(void) const
Definition: fsys.cpp:801
ucommon::fsys::fsys
fsys()
Definition: fsys.cpp:1171
ucommon::fsys::output
static fd_t output(const char *path)
Definition: fsys.cpp:839
O_NONBLOCK
#define O_NONBLOCK
Definition: dccp.cpp:63
INVALID_HANDLE_VALUE
#define INVALID_HANDLE_VALUE
Definition: platform.h:417
ucommon::fsys::err
int err(void) const
Definition: fsys.h:557
ucommon::fsys::erase
static int erase(const char *path)
Definition: fsys.cpp:1341
ucommon::dir::remove
static int remove(const char *path)
Definition: fsys.cpp:1351
result
static void result(const char *path, int code)
Definition: mdsum.cpp:35
ucommon::dso::find
addr_t find(const char *symbol) const
Definition: fsys.cpp:1690
ucommon::fsys::drop
int drop(offset_t size=0)
Definition: fsys.cpp:1110
ucommon::fsys::remapError
static int remapError(void)
Definition: fsys.h:152
ucommon::fsys::EXCLUSIVE
Definition: fsys.h:167
ucommon::dso::release
void release(void)
Definition: fsys.cpp:1686
ucommon::copy
T copy(const T &src)
Definition: generics.h:395
ucommon::fsys::offset_t
long offset_t
Definition: fsys.h:176
ucommon::typeref::value
Definition: typeref.h:329
ucommon::dso::dso
dso()
Definition: fsys.cpp:1142
ucommon::is_dir
bool is_dir(const char *path)
Definition: fsys.h:863
ucommon::dso::ptr
void * ptr
Definition: fsys.h:670
ucommon::dir::open
void open(const char *path)
Definition: fsys.cpp:909
ucommon::fsys::operator=
fsys & operator=(const fsys &descriptor)
Definition: fsys.cpp:1099
ucommon::fsys::set
void set(fd_t descriptor)
Definition: fsys.cpp:1768
ucommon::dso::error
int error
Definition: fsys.h:672
ucommon::fsys::linkinfo
static int linkinfo(const char *path, char *buffer, size_t size)
Definition: fsys.cpp:1210
ucommon::fsys::RANDOM
Definition: fsys.h:170
ucommon::fsys::rename
static int rename(const char *oldpath, const char *newpath)
Definition: fsys.cpp:1426
output
static FILE * output
Definition: car.cpp:43
ucommon::fsys::copy
static int copy(const char *source, const char *target, size_t size=1024)
Definition: fsys.cpp:1374
ucommon::dir::create
static int create(const char *path, unsigned mode)
Definition: fsys.cpp:895
ucommon::fsys::SHARED
Definition: fsys.h:166
ucommon::fsys::error
int error
Definition: fsys.h:129
ucommon::fsys::close
int close(void)
Definition: fsys.cpp:820
thread.h
ucommon::dso::map
void map(const char *path)
ucommon::fsys::info
int info(fileinfo_t *buffer)
ucommon::fsys::is_device
static bool is_device(const char *path)
Definition: fsys.cpp:1697
ucommon::fsys::input
static fd_t input(const char *path)
Definition: fsys.cpp:834
ucommon::dir::ptr
void * ptr
Definition: fsys.h:750
input
static shell::stringopt input('i', "--input", _TEXT("stdin path to use"), "filename")
ucommon::typeref< const char * >::expand
static void expand(value **handle, size_t size)
Definition: typeref.cpp:322
ucommon::fsys::inherit
static int inherit(fd_t &descriptor, bool enable)
Definition: fsys.cpp:1073
ucommon::dir::close
void close(void)
Definition: fsys.cpp:808
ucommon::fsys::hardlink
static int hardlink(const char *path, const char *target)
Definition: fsys.cpp:1252
ucommon::fsys::append
static fd_t append(const char *path)
Definition: fsys.cpp:844
ucommon::fsys::release
fd_t release(void)
Definition: fsys.cpp:1775
ucommon::fsys::exec
static int exec(const char *path, char **argv, char **envp=NULL)
Definition: fsys.cpp:1784
ucommon::dup
T * dup(const T &object)
Definition: generics.h:324
ucommon::String::set
void set(const char *text)
Definition: string.cpp:802
ucommon::fsys::null
static fd_t null(void)
Definition: fsys.cpp:778
ucommon::fsys::is_exists
static bool is_exists(const char *path)
Definition: fsys.cpp:1026
fsys.h
ucommon::fsys::DEVICE
Definition: fsys.h:168
ucommon::fsys::trunc
int trunc(offset_t offset)
Definition: fsys.cpp:987
ucommon::fsys::is_dir
static bool is_dir(const char *path)
Definition: fsys.cpp:1500
buffer
static uint8_t buffer[65536]
Definition: zerofill.cpp:27
ucommon::typeref
Definition: typeref.h:326
ucommon::fsys::is_writable
static bool is_writable(const char *path)
Definition: fsys.cpp:1042
ucommon::stringref::create
static value * create(size_t size)
Definition: typeref.h:673
socksize_t
size_t socksize_t
Definition: platform.h:296
ucommon::fsys::is_hidden
static bool is_hidden(const char *path)
Definition: fsys.cpp:1740
ucommon::dso::~dso
~dso()
Definition: fsys.cpp:1155
ucommon::fsys::STREAM
Definition: fsys.h:169
ucommon::fsys::load
static int load(const char *path)
Definition: fsys.cpp:1433
ucommon::shell::pid_t
int pid_t
Definition: shell.h:147
ucommon::dir::dir
dir()
Definition: fsys.cpp:1160
ucommon::dir::read
ssize_t read(char *buffer, size_t count)
Definition: fsys.cpp:736
ucommon::fsys
Definition: fsys.h:125
ucommon::fsys::open
void open(const char *path, access_t access)
Definition: fsys.cpp:919
string.h
ucommon::fsys::EVERYONE
Definition: fsys.h:143
ucommon::fsys::prefix
static stringref_t prefix(void)
Definition: fsys.cpp:1803
ucommon::fsys::operator*=
fsys & operator*=(fd_t &descriptor)
Definition: fsys.cpp:1201
ucommon::fsys::GROUP_PUBLIC
Definition: fsys.h:142
ucommon::fsys::fd
fd_t fd
Definition: fsys.h:128
ucommon::fsys::RDONLY
Definition: fsys.h:161
ucommon::fsys::end
static const offset_t end
Definition: fsys.h:181
ucommon::fsys::is_executable
static bool is_executable(const char *path)
Definition: fsys.cpp:1050
ucommon::fsys::pipe
static int pipe(fd_t &input, fd_t &output, size_t size=0)
Definition: fsys.cpp:783
shell.h
S_ISREG
#define S_ISREG(mode)
Definition: fsys.h:89
ucommon::fsys::WRONLY
Definition: fsys.h:162
ucommon::fsys::~fsys
~fsys()
Definition: fsys.cpp:1196
ucommon::dso
Definition: fsys.h:662
ucommon::fsys::is_file
static bool is_file(const char *path)
Definition: fsys.cpp:1453
memory.h
ucommon::fsys::seek
int seek(offset_t offset)
Definition: fsys.cpp:1124
ucommon::shell::wait
static int wait(shell::pid_t pid)
Definition: shell.cpp:2070
ucommon::is
bool is(T &object)
Definition: generics.h:292
ucommon::dso::addr_t
void * addr_t
Definition: fsys.h:680
typeref.h
ucommon::fsys::mode
static int mode(const char *path, unsigned value)
Definition: fsys.cpp:1019
ucommon::dir::~dir
~dir()
Definition: fsys.cpp:1166