VirtualBox

source: kBuild/trunk/src/kash/shfile.c@ 2289

Last change on this file since 2289 was 2289, checked in by bird, 16 years ago

kash: implementing shfile on top of the win32 api instead of msvcrt.

  • Property svn:eol-style set to LF
  • Property svn:keywords set to Id
File size: 28.4 KB
Line 
1/* $Id: shfile.c 2289 2009-02-26 04:58:49Z bird $ */
2/** @file
3 *
4 * File management.
5 *
6 * Copyright (c) 2007-2009 knut st. osmundsen <[email protected]>
7 *
8 *
9 * This file is part of kBuild.
10 *
11 * kBuild is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * kBuild is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with kBuild; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 */
26
27#include "shfile.h"
28#include "shinstance.h" /* TRACE2 */
29#include <stdlib.h>
30#include <stdio.h>
31#include <assert.h>
32
33#if K_OS == K_OS_WINDOWS
34# include <limits.h>
35# ifndef PIPE_BUF
36# define PIPE_BUF 512
37# endif
38# include <Windows.h>
39#else
40# include <unistd.h>
41# include <fcntl.h>
42# include <dirent.h>
43#endif
44
45#ifdef DEBUG
46extern FILE *tracefile;
47#endif
48
49
50/*******************************************************************************
51* Defined Constants And Macros *
52*******************************************************************************/
53/** @def SHFILE_IN_USE
54 * Whether the file descriptor table stuff is actually in use or not.
55 */
56#if !defined(SH_PURE_STUB_MODE) \
57 && ( K_OS == K_OS_WINDOWS \
58 || ( !defined(SH_STUB_MODE) \
59 && !defined(SH_FORKED_MODE)) \
60 )
61# define SHFILE_IN_USE
62#endif
63/** The max file table size. */
64#define SHFILE_MAX 1024
65/** The file table growth rate. */
66#define SHFILE_GROW 64
67/** The min native unix file descriptor. */
68#define SHFILE_UNIX_MIN_FD 32
69/** The path buffer size we use. */
70#define SHFILE_MAX_PATH 4096
71
72/** Set errno and return. Doing a trace in debug build. */
73#define RETURN_ERROR(rc, err, msg) \
74 do { \
75 TRACE2((NULL, "%s: " ## msg ## " - returning %d / %d\n", __FUNCTION__, (rc), (err))); \
76 errno = (err); \
77 return (rc); \
78 } while (0)
79
80
81#ifdef SHFILE_IN_USE
82
83/**
84 * Close the specified native handle.
85 *
86 * @param native The native file handle.
87 * @param flags The flags in case they might come in handy later.
88 */
89static void shfile_native_close(intptr_t native, unsigned flags)
90{
91#if K_OS == K_OS_WINDOWS
92 BOOL fRc = CloseHandle((HANDLE)native);
93 assert(fRc); (void)fRc;
94#else
95 int s = errno;
96 close(native);
97 errno = s;
98#endif
99 (void)flags;
100}
101
102/**
103 * Inserts the file into the descriptor table.
104 *
105 * If we're out of memory and cannot extend the table, we'll close the
106 * file, set errno to EMFILE and return -1.
107 *
108 * @returns The file descriptor number. -1 and errno on failure.
109 * @param pfdtab The file descriptor table.
110 * @param native The native file handle.
111 * @param flags The flags the it was created with.
112 * @param fdMin The minimum file descriptor number, pass -1 if any is ok.
113 * @param who Who we're doing this for (for logging purposes).
114 */
115static int shfile_insert(shfdtab *pfdtab, intptr_t native, unsigned flags, int fdMin, const char *who)
116{
117 shmtxtmp tmp;
118 int fd;
119 int i;
120
121 /*
122 * Fend of bad stuff.
123 */
124 if (fdMin >= SHFILE_MAX)
125 {
126 errno = EMFILE;
127 return -1;
128 }
129
130 shmtx_enter(&pfdtab->mtx, &tmp);
131
132 /*
133 * Search for a fitting unused location.
134 */
135 fd = -1;
136 for (i = 0; (unsigned)i < pfdtab->size; i++)
137 if ( i >= fdMin
138 && pfdtab->tab[i].fd == -1)
139 {
140 fd = i;
141 break;
142 }
143 if (fd == -1)
144 {
145 /*
146 * Grow the descriptor table.
147 */
148 shfile *new_tab;
149 int new_size = pfdtab->size + SHFILE_GROW;
150 while (new_size < fdMin)
151 new_size += SHFILE_GROW;
152 new_tab = realloc(pfdtab->tab, new_size * sizeof(shfile));
153 if (new_tab)
154 {
155 fd = i = pfdtab->size;
156 if (fd < fdMin)
157 fd = fdMin;
158 for (i = pfdtab->size; i < new_size; i++)
159 {
160 new_tab[i].fd = -1;
161 new_tab[i].flags = 0;
162 new_tab[i].native = -1;
163 }
164
165 pfdtab->tab = new_tab;
166 pfdtab->size = new_size;
167 }
168 }
169
170 /*
171 * Fill in the entry if we've found one.
172 */
173 if (fd != -1)
174 {
175 pfdtab->tab[fd].fd = fd;
176 pfdtab->tab[fd].flags = flags;
177 pfdtab->tab[fd].cloexec = 0;
178 pfdtab->tab[fd].native = native;
179 }
180 else
181 shfile_native_close(native, flags);
182
183 shmtx_leave(&pfdtab->mtx, &tmp);
184
185 if (fd == -1)
186 errno = EMFILE;
187 (void)who;
188 return fd;
189}
190
191/**
192 * Gets a file descriptor and lock the file descriptor table.
193 *
194 * @returns Pointer to the file and table ownership on success,
195 * NULL and errno set to EBADF on failure.
196 * @param pfdtab The file descriptor table.
197 * @param fd The file descriptor number.
198 * @param ptmp See shmtx_enter.
199 */
200static shfile *shfile_get(shfdtab *pfdtab, int fd, shmtxtmp *ptmp)
201{
202 shfile *file = NULL;
203 if ( fd >= 0
204 && (unsigned)fd < pfdtab->size)
205 {
206 shmtx_enter(&pfdtab->mtx, ptmp);
207 if ((unsigned)fd < pfdtab->size
208 && pfdtab->tab[fd].fd != -1)
209 file = &pfdtab->tab[fd];
210 else
211 shmtx_leave(&pfdtab->mtx, ptmp);
212 }
213 if (!file)
214 errno = EBADF;
215 return file;
216}
217
218/**
219 * Puts back a file descriptor and releases the table ownership.
220 *
221 * @param pfdtab The file descriptor table.
222 * @param file The file.
223 * @param ptmp See shmtx_leave.
224 */
225static void shfile_put(shfdtab *pfdtab, shfile *file, shmtxtmp *ptmp)
226{
227 shmtx_leave(&pfdtab->mtx, ptmp);
228 assert(file);
229 (void)file;
230}
231
232
233/**
234 * Constructs a path from the current directory and the passed in path.
235 *
236 * @returns 0 on success, -1 and errno set to ENAMETOOLONG or EINVAL on failure.
237 *
238 * @param pfdtab The file descriptor table
239 * @param path The path the caller supplied.
240 * @param buf Where to put the path. This is assumed to be SHFILE_MAX_PATH
241 * chars in size.
242 */
243int shfile_make_path(shfdtab *pfdtab, const char *path, char *buf)
244{
245 size_t path_len = strlen(path);
246 if (path_len == 0)
247 {
248 errno = EINVAL;
249 return -1;
250 }
251 if (path_len >= SHFILE_MAX_PATH)
252 {
253 errno = ENAMETOOLONG;
254 return -1;
255 }
256 if ( *path == '/'
257#if K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2
258 || *path == '\\'
259 || ( !*path
260 && path[1] == ':'
261 && ( (*path >= 'A' && *path <= 'Z')
262 || (*path >= 'a' && *path <= 'z')))
263#endif
264 )
265 {
266 memcpy(buf, path, path_len + 1);
267 }
268 else
269 {
270 size_t cwd_len;
271 shmtxtmp tmp;
272
273 shmtx_enter(&pfdtab->mtx, &tmp);
274
275 cwd_len = strlen(pfdtab->cwd);
276 memcpy(buf, pfdtab->cwd, cwd_len);
277
278 shmtx_leave(&pfdtab->mtx, &tmp);
279
280 if (cwd_len + path_len + 1 >= SHFILE_MAX_PATH)
281 {
282 errno = ENAMETOOLONG;
283 return -1;
284 }
285 if ( !cwd_len
286 || buf[cwd_len - 1] != '/')
287 buf[cwd_len++] = '/';
288 memcpy(buf + cwd_len, path, path_len + 1);
289 }
290
291#if K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2
292 if (!strcmp(buf, "/dev/null"))
293 strcpy(buf, "NUL");
294#endif
295 return 0;
296}
297
298# if K_OS == K_OS_WINDOWS
299/**
300 * Converts a DOS(/Windows) error code to errno,
301 * assigning it to errno.
302 *
303 * @returns -1
304 * @param err The DOS error.
305 */
306static int shfile_dos2errno(int err)
307{
308 switch (err)
309 {
310 case ERROR_BAD_ENVIRONMENT: errno = E2BIG; break;
311 case ERROR_ACCESS_DENIED: errno = EACCES; break;
312 case ERROR_CURRENT_DIRECTORY: errno = EACCES; break;
313 case ERROR_LOCK_VIOLATION: errno = EACCES; break;
314 case ERROR_NETWORK_ACCESS_DENIED: errno = EACCES; break;
315 case ERROR_CANNOT_MAKE: errno = EACCES; break;
316 case ERROR_FAIL_I24: errno = EACCES; break;
317 case ERROR_DRIVE_LOCKED: errno = EACCES; break;
318 case ERROR_SEEK_ON_DEVICE: errno = EACCES; break;
319 case ERROR_NOT_LOCKED: errno = EACCES; break;
320 case ERROR_LOCK_FAILED: errno = EACCES; break;
321 case ERROR_NO_PROC_SLOTS: errno = EAGAIN; break;
322 case ERROR_MAX_THRDS_REACHED: errno = EAGAIN; break;
323 case ERROR_NESTING_NOT_ALLOWED: errno = EAGAIN; break;
324 case ERROR_INVALID_HANDLE: errno = EBADF; break;
325 case ERROR_INVALID_TARGET_HANDLE: errno = EBADF; break;
326 case ERROR_DIRECT_ACCESS_HANDLE: errno = EBADF; break;
327 case ERROR_WAIT_NO_CHILDREN: errno = ECHILD; break;
328 case ERROR_CHILD_NOT_COMPLETE: errno = ECHILD; break;
329 case ERROR_FILE_EXISTS: errno = EEXIST; break;
330 case ERROR_ALREADY_EXISTS: errno = EEXIST; break;
331 case ERROR_INVALID_FUNCTION: errno = EINVAL; break;
332 case ERROR_INVALID_ACCESS: errno = EINVAL; break;
333 case ERROR_INVALID_DATA: errno = EINVAL; break;
334 case ERROR_INVALID_PARAMETER: errno = EINVAL; break;
335 case ERROR_NEGATIVE_SEEK: errno = EINVAL; break;
336 case ERROR_TOO_MANY_OPEN_FILES: errno = EMFILE; break;
337 case ERROR_FILE_NOT_FOUND: errno = ENOENT; break;
338 case ERROR_PATH_NOT_FOUND: errno = ENOENT; break;
339 case ERROR_INVALID_DRIVE: errno = ENOENT; break;
340 case ERROR_NO_MORE_FILES: errno = ENOENT; break;
341 case ERROR_BAD_NETPATH: errno = ENOENT; break;
342 case ERROR_BAD_NET_NAME: errno = ENOENT; break;
343 case ERROR_BAD_PATHNAME: errno = ENOENT; break;
344 case ERROR_FILENAME_EXCED_RANGE: errno = ENOENT; break;
345 case ERROR_BAD_FORMAT: errno = ENOEXEC; break;
346 case ERROR_ARENA_TRASHED: errno = ENOMEM; break;
347 case ERROR_NOT_ENOUGH_MEMORY: errno = ENOMEM; break;
348 case ERROR_INVALID_BLOCK: errno = ENOMEM; break;
349 case ERROR_NOT_ENOUGH_QUOTA: errno = ENOMEM; break;
350 case ERROR_DISK_FULL: errno = ENOSPC; break;
351 case ERROR_DIR_NOT_EMPTY: errno = ENOTEMPTY; break;
352 case ERROR_BROKEN_PIPE: errno = EPIPE; break;
353 case ERROR_NOT_SAME_DEVICE: errno = EXDEV; break;
354 default: errno = EINVAL; break;
355 }
356 return -1;
357}
358# endif /* K_OS == K_OS_WINDOWS */
359
360#endif /* SHFILE_IN_USE */
361
362/**
363 * Initializes a file descriptor table.
364 *
365 * @returns 0 on success, -1 and errno on failure.
366 * @param pfdtab The table to initialize.
367 * @param inherit File descriptor table to inherit from. If not specified
368 * we will inherit from the current process as it were.
369 */
370int shfile_init(shfdtab *pfdtab, shfdtab *inherit)
371{
372 int rc;
373
374 pfdtab->cwd = NULL;
375 pfdtab->size = 0;
376 pfdtab->tab = NULL;
377 rc = shmtx_init(&pfdtab->mtx);
378 if (!rc)
379 {
380#ifdef SHFILE_IN_USE
381 char buf[SHFILE_MAX_PATH];
382 if (getcwd(buf, sizeof(buf)))
383 {
384 pfdtab->cwd = strdup(buf);
385 if (!inherit)
386 {
387# if K_OS == K_OS_WINDOWS
388 static const struct
389 {
390 DWORD dwStdHandle;
391 unsigned flags;
392 } aStdHandles[3] =
393 {
394 { STD_INPUT_HANDLE, _O_RDONLY },
395 { STD_OUTPUT_HANDLE, _O_WRONLY },
396 { STD_ERROR_HANDLE, _O_WRONLY }
397 };
398 unsigned i;
399 STARTUPINFO Info;
400
401 rc = 0;
402
403 /* Try pick up the Visual C++ CRT file descriptor info. */
404 __try {
405 GetStartupInfo(&Info);
406 } __except (EXCEPTION_EXECUTE_HANDLER) {
407 memset(&Info, 0, sizeof(Info));
408 }
409 if ( Info.cbReserved2 <= sizeof(int)
410 && (uintptr_t)Info.lpReserved2 >= 0x1000
411 && *(int *)Info.lpReserved2 * (sizeof(int) + sizeof(intptr_t)) + 4 <= Info.cbReserved2
412 && *(int *)Info.lpReserved2 <= 2048
413 && *(int *)Info.lpReserved2 >= 1)
414 {
415 unsigned c = *(int *)Info.lpReserved2;
416 char *aosfile = (char *)Info.lpReserved2 + sizeof(int);
417 intptr_t *aosfhnd = (intptr_t *)(aosfile + c);
418
419 /** @todo process */
420
421 }
422
423 /* Check the three standard handles. */
424 for (i = 0; i < 3; i++)
425 {
426 HANDLE hFile = GetStdHandle(aStdHandles[i].dwStdHandle);
427 if ( hFile != INVALID_HANDLE_VALUE
428 && ( (unsigned)i >= pfdtab->size
429 || pfdtab->tab[i].fd == -1))
430 {
431 int fd2 = shfile_insert(pfdtab, (intptr_t)hFile, aStdHandles[i].flags, i, "shtab_init");
432 assert(fd2 == i); (void)fd2;
433 if (fd2 != i)
434 rc = -1;
435 }
436 }
437# else
438# endif
439 }
440 else
441 {
442 /** @todo */
443 errno = ENOSYS;
444 rc = -1;
445 }
446 }
447 else
448 rc = -1;
449#endif
450 }
451 return rc;
452}
453
454/**
455 * open().
456 */
457int shfile_open(shfdtab *pfdtab, const char *name, unsigned flags, mode_t mode)
458{
459 int fd;
460#ifdef SHFILE_IN_USE
461 char absname[SHFILE_MAX_PATH];
462# if K_OS == K_OS_WINDOWS
463 HANDLE hFile;
464 DWORD dwDesiredAccess;
465 DWORD dwShareMode;
466 DWORD dwCreationDisposition;
467 DWORD dwFlagsAndAttributes;
468 SECURITY_ATTRIBUTES SecurityAttributes;
469
470# ifndef _O_ACCMODE
471# define _O_ACCMODE (_O_RDONLY|_O_WRONLY|_O_RDWR)
472# endif
473 switch (flags & (_O_ACCMODE | _O_APPEND))
474 {
475 case _O_RDONLY: dwDesiredAccess = GENERIC_READ; break;
476 case _O_RDONLY | _O_APPEND: dwDesiredAccess = GENERIC_READ; break;
477 case _O_WRONLY: dwDesiredAccess = GENERIC_WRITE; break;
478 case _O_WRONLY | _O_APPEND: dwDesiredAccess = (FILE_GENERIC_WRITE & ~FILE_WRITE_DATA); break;
479 case _O_RDWR: dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; break;
480 case _O_RDWR | _O_APPEND: dwDesiredAccess = GENERIC_READ | (FILE_GENERIC_WRITE & ~FILE_WRITE_DATA); break;
481
482 default:
483 RETURN_ERROR(-1, EINVAL, "invalid mode");
484 }
485
486 dwShareMode = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE;
487
488 SecurityAttributes.nLength = sizeof(SecurityAttributes);
489 SecurityAttributes.lpSecurityDescriptor = NULL;
490 SecurityAttributes.bInheritHandle = (flags & _O_NOINHERIT) == 0;
491
492 if (flags & _O_CREAT)
493 {
494 if ((flags & (_O_EXCL | _O_TRUNC)) == (_O_EXCL | _O_TRUNC))
495 RETURN_ERROR(-1, EINVAL, "_O_EXCL | _O_TRUNC");
496
497 if (flags & _O_TRUNC)
498 dwCreationDisposition = CREATE_ALWAYS; /* not 100%, but close enough */
499 else if (flags & _O_EXCL)
500 dwCreationDisposition = CREATE_NEW;
501 else
502 dwCreationDisposition = OPEN_ALWAYS;
503 }
504 else if (flags & _O_TRUNC)
505 dwCreationDisposition = TRUNCATE_EXISTING;
506 else
507 dwCreationDisposition = OPEN_EXISTING;
508
509 if (!(flags & _O_CREAT) || (mode & 0222))
510 dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
511 else
512 dwFlagsAndAttributes = FILE_ATTRIBUTE_READONLY;
513
514 fd = shfile_make_path(pfdtab, name, &absname[0]);
515 if (!fd)
516 {
517 SetLastError(0);
518 hFile = CreateFileA(absname,
519 dwDesiredAccess,
520 dwShareMode,
521 &SecurityAttributes,
522 dwCreationDisposition,
523 dwFlagsAndAttributes,
524 NULL /* hTemplateFile */);
525 if (hFile != INVALID_HANDLE_VALUE)
526 fd = shfile_insert(pfdtab, (intptr_t)hFile, flags, -1, "shfile_open");
527 else
528 fd = shfile_dos2errno(GetLastError());
529 }
530
531# else /* K_OS != K_OS_WINDOWS */
532 fd = shfile_make_path(pfdtab, name, &absname[0]);
533 if (!fd)
534 {
535 fd = open(absname, flag, mode);
536 if (fd != -1)
537 {
538 int native = fcntl(fd, F_DUPFD, SHFILE_UNIX_MIN_FD);
539 int s = errno;
540 close(fd);
541 errno = s;
542 if (native != -1)
543 fd = shfile_insert(pfdtab, native, flags, -1, "shfile_open");
544 else
545 fd = -1;
546 }
547 }
548
549# endif /* K_OS != K_OS_WINDOWS */
550
551#elif defined(SH_PURE_STUB_MODE)
552 fd = -1;
553 errno = ENOSYS;
554
555#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
556 fd = open(name, flags, mode);
557#endif
558
559#ifdef DEBUG
560 if (tracefile)
561 TRACE2((NULL, "shfile_open(%p:{%s}, %#x, 0%o) -> %d [%d]\n", name, name, flags, mode, fd, errno));
562#endif
563 return fd;
564}
565
566int shfile_pipe(shfdtab *pfdtab, int fds[2])
567{
568#ifdef SH_PURE_STUB_MODE
569 return -1;
570
571#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
572# ifdef _MSC_VER
573 return _pipe(fds, PIPE_BUF, O_BINARY);
574# else
575 return pipe(fds);
576# endif
577
578#else
579#endif
580}
581
582int shfile_dup(shfdtab *pfdtab, int fd)
583{
584 int rc;
585#ifdef SH_PURE_STUB_MODE
586 rc = -1;
587
588#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
589 rc = dup(fd);
590
591#else
592#endif
593
594 TRACE2((NULL, "shfile_dup(%d) -> %d [%d]\n", fd, rc, errno));
595 return rc;
596}
597
598/**
599 * close().
600 */
601int shfile_close(shfdtab *pfdtab, unsigned fd)
602{
603 int rc;
604#ifdef SHFILE_IN_USE
605 shmtxtmp tmp;
606 shfile *file = shfile_get(pfdtab, fd, &tmp);
607 if (file)
608 {
609 shfile_native_close(file->native, file->flags);
610
611 file->fd = -1;
612 file->flags = 0;
613 file->native = -1;
614
615 shfile_put(pfdtab, file, &tmp);
616 rc = 0;
617 }
618 else
619 rc = -1;
620
621#elif defined(SH_PURE_STUB_MODE)
622 rc = -1;
623
624#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
625 rc = close(fd);
626#endif
627
628 TRACE2((NULL, "shfile_close(%d) -> %d [%d]\n", fd, rc, errno));
629 return rc;
630}
631
632/**
633 * read().
634 */
635long shfile_read(shfdtab *pfdtab, int fd, void *buf, size_t len)
636{
637 long rc;
638#ifdef SHFILE_IN_USE
639 shmtxtmp tmp;
640 shfile *file = shfile_get(pfdtab, fd, &tmp);
641 if (file)
642 {
643# if K_OS == K_OS_WINDOWS
644 DWORD dwRead = 0;
645 if (ReadFile((HANDLE)file->native, buf, (DWORD)len, &dwRead, NULL))
646 rc = dwRead;
647 else
648 rc = shfile_dos2errno(GetLastError());
649# else
650 rc = read(file->native, buf, len);
651# endif
652
653 shfile_put(pfdtab, file, &tmp);
654 }
655 else
656 rc = -1;
657
658#elif defined(SH_PURE_STUB_MODE)
659 rc = -1;
660
661#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
662# ifdef _MSC_VER
663 rc = read(fd, buf, (unsigned)len);
664# else
665 rc = read(fd, buf, len);
666# endif
667#endif
668 return rc;
669}
670
671/**
672 * write().
673 */
674long shfile_write(shfdtab *pfdtab, int fd, const void *buf, size_t len)
675{
676 long rc;
677#ifdef SHFILE_IN_USE
678 shmtxtmp tmp;
679 shfile *file = shfile_get(pfdtab, fd, &tmp);
680 if (file)
681 {
682# if K_OS == K_OS_WINDOWS
683 DWORD dwWritten = 0;
684 if (WriteFile((HANDLE)file->native, buf, (DWORD)len, &dwWritten, NULL))
685 rc = dwWritten;
686 else
687 rc = shfile_dos2errno(GetLastError());
688# else
689 rc = write(file->native, buf, len);
690# endif
691
692 shfile_put(pfdtab, file, &tmp);
693 }
694 else
695 rc = -1;
696
697#elif defined(SH_PURE_STUB_MODE)
698 rc = -1;
699
700#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
701# ifdef _MSC_VER
702 rc = write(fd, buf, (unsigned)len);
703# else
704 rc = write(fd, buf, len);
705# endif
706#endif
707 return rc;
708}
709
710/**
711 * lseek().
712 */
713long shfile_lseek(shfdtab *pfdtab, int fd, long off, int whench)
714{
715 long rc;
716#ifdef SHFILE_IN_USE
717 shmtxtmp tmp;
718 shfile *file = shfile_get(pfdtab, fd, &tmp);
719 if (file)
720 {
721# if K_OS == K_OS_WINDOWS
722 assert(SEEK_SET == FILE_BEGIN);
723 assert(SEEK_CUR == FILE_CURRENT);
724 assert(SEEK_END == FILE_END);
725 rc = SetFilePointer((HANDLE)file->native, off, NULL, whench);
726 if (rc == INVALID_SET_FILE_POINTER)
727 rc = shfile_dos2errno(GetLastError());
728# else
729 rc = lseek(file->native, off, whench);
730# endif
731
732 shfile_put(pfdtab, file, &tmp);
733 }
734 else
735 rc = -1;
736
737#elif defined(SH_PURE_STUB_MODE)
738 rc = -1;
739
740#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
741 rc = lseek(fd, off, whench);
742#endif
743
744 return rc;
745}
746
747int shfile_fcntl(shfdtab *pfdtab, int fd, int cmd, int arg)
748{
749 int rc;
750#ifdef SHFILE_IN_USE
751 shmtxtmp tmp;
752 shfile *file = shfile_get(pfdtab, fd, &tmp);
753 if (file)
754 {
755 switch (cmd)
756 {
757 case F_GETFL:
758 rc = file->flags;
759 break;
760
761 case F_SETFL:
762 {
763 unsigned mask = O_NONBLOCK | O_APPEND | O_BINARY | O_TEXT;
764# ifdef O_DIRECT
765 mask |= O_DIRECT;
766# endif
767# ifdef O_ASYNC
768 mask |= O_ASYNC;
769# endif
770# ifdef O_SYNC
771 mask |= O_SYNC;
772# endif
773 if ((file->flags & mask) == (arg & mask))
774 rc = 0;
775 else
776 {
777# if K_OS == K_OS_WINDOWS
778 assert(0);
779 errno = EINVAL;
780 rc = -1;
781# else
782 rc = fcntl(file->native, F_SETFL, arg);
783 if (rc != -1)
784 file->flags = (file->flags & ~mask) | (arg & mask);
785# endif
786 }
787 break;
788 }
789
790 case F_DUPFD:
791 {
792# if K_OS == K_OS_WINDOWS
793 HANDLE hNew = INVALID_HANDLE_VALUE;
794 if (DuplicateHandle(GetCurrentProcess(),
795 (HANDLE)file->native,
796 GetCurrentProcess(),
797 &hNew,
798 0,
799 TRUE /* bInheritHandle */,
800 DUPLICATE_SAME_ACCESS))
801 rc = shfile_insert(pfdtab, (intptr_t)hNew, file->flags, arg, "shfile_fcntl");
802 else
803 rc = shfile_dos2errno(GetLastError());
804# else
805 int nativeNew = fcntl(file->native F_DUPFD, SHFILE_UNIX_MIN_FD);
806 if (nativeNew != -1)
807 rc = shfile_insert(pfdtab, nativeNew, file->flags, arg, "shfile_fcntl");
808# endif
809 break;
810 }
811
812 default:
813 errno = -EINVAL;
814 rc = -1;
815 break;
816 }
817
818 shfile_put(pfdtab, file, &tmp);
819 }
820 else
821 rc = -1;
822
823#elif defined(SH_PURE_STUB_MODE)
824 rc = -1;
825
826#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
827# ifdef _MSC_VER
828 switch (cmd)
829 {
830 /* Just enough F_GETFL/F_SETFL to get along with. */
831 case F_GETFL:
832 errno = 0;
833 rc = _isatty(fd);
834 if (errno == EBADF)
835 rc = -1;
836 break;
837
838 case F_SETFL:
839 errno = 0;
840 rc = _isatty(fd);
841 if (errno != EBADF)
842 {
843 if (!arg)
844 rc = 0;
845 else
846 {
847 errno = EINVAL;
848 rc = -1;
849 }
850 }
851 else
852 rc = -1;
853 break;
854
855 case F_DUPFD:
856 {
857 /* the brute force approach. */
858 int i = 0;
859 int fds[256];
860 for (i = 0; i < 256; i++)
861 {
862 fds[i] = -1;
863 rc = _dup(fd);
864 if (rc >= arg)
865 break;
866 fds[i] = rc;
867 }
868 while (i-- > 0)
869 close(fds[i]);
870 if (rc < arg)
871 {
872 errno = EMFILE;
873 rc = -1;
874 }
875 break;
876 }
877 }
878# else
879 rc = fcntl(fd, cmd, arg);
880# endif
881#endif
882
883#ifdef DEBUG
884 if (tracefile)
885 switch (cmd)
886 {
887 case F_GETFL:
888 TRACE2((NULL, "shfile_fcntl(%d,F_GETFL,ignored=%d) -> %d [%d]\n", fd, arg, rc, errno));
889 break;
890 case F_SETFL:
891 TRACE2((NULL, "shfile_fcntl(%d,F_SETFL,newflags=%#x) -> %d [%d]\n", fd, arg, rc, errno));
892 break;
893 case F_DUPFD:
894 TRACE2((NULL, "shfile_fcntl(%d,F_DUPFS,minfd=%d) -> %d [%d]\n", fd, arg, rc, errno));
895 break;
896 default:
897 TRACE2((NULL, "shfile_fcntl(%d,%d,%d) -> %d [%d]\n", fd, cmd, arg, rc, errno));
898 break;
899 }
900#endif
901 return rc;
902}
903
904int shfile_stat(shfdtab *pfdtab, const char *path, struct stat *pst)
905{
906#ifdef SH_PURE_STUB_MODE
907 return -1;
908
909#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
910 return stat(path, pst);
911
912#else
913#endif
914}
915
916int shfile_lstat(shfdtab *pfdtab, const char *link, struct stat *pst)
917{
918#ifdef SH_PURE_STUB_MODE
919 return -1;
920
921#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
922# ifdef _MSC_VER
923 return stat(link, pst);
924# else
925 return lstat(link, pst);
926# endif
927
928#else
929#endif
930}
931
932int shfile_chdir(shfdtab *pfdtab, const char *path)
933{
934#ifdef SH_PURE_STUB_MODE
935 return -1;
936
937#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
938# ifdef _MSC_VER //???
939 return chdir(path);
940# else
941 return chdir(path);
942# endif
943
944#else
945#endif
946}
947
948char *shfile_getcwd(shfdtab *pfdtab, char *buf, int len)
949{
950#ifdef SH_PURE_STUB_MODE
951 return NULL;
952
953#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
954 return getcwd(buf, len);
955
956#else
957#endif
958}
959
960int shfile_access(shfdtab *pfdtab, const char *path, int type)
961{
962#ifdef SH_PURE_STUB_MODE
963 return -1;
964
965#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
966# ifdef _MSC_VER
967 type &= ~X_OK;
968 return access(path, type);
969# else
970 return access(path, type);
971# endif
972
973#else
974#endif
975}
976
977int shfile_isatty(shfdtab *pfdtab, int fd)
978{
979 int rc;
980
981#ifdef SH_PURE_STUB_MODE
982 rc = 0;
983#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
984 rc = isatty(fd);
985#else
986#endif
987
988 TRACE2((NULL, "isatty(%d) -> %d [%d]\n", fd, rc, errno));
989 return rc;
990}
991
992
993int shfile_cloexec(shfdtab *pfdtab, int fd, int closeit)
994{
995 int rc;
996
997#ifdef SH_PURE_STUB_MODE
998 rc = -1;
999
1000#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
1001# ifdef _MSC_VER
1002 errno = ENOSYS;
1003 rc = -1;
1004# else
1005 rc = fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0)
1006 | (closeit ? FD_CLOEXEC : 0));
1007# endif
1008
1009#else
1010#endif
1011
1012 TRACE2((NULL, "shfile_cloexec(%d, %d) -> %d [%d]\n", fd, closeit, rc, errno));
1013 return rc;
1014}
1015
1016
1017int shfile_ioctl(shfdtab *pfdtab, int fd, unsigned long request, void *buf)
1018{
1019 int rc;
1020
1021#ifdef SH_PURE_STUB_MODE
1022 rc = -1;
1023
1024#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
1025# ifdef _MSC_VER
1026 errno = ENOSYS;
1027 rc = -1;
1028# else
1029 rc = ioctl(fd, request, buf);
1030# endif
1031
1032#else
1033#endif
1034
1035 TRACE2((NULL, "ioctl(%d, %#x, %p) -> %d\n", fd, request, buf, rc));
1036 return rc;
1037}
1038
1039
1040mode_t shfile_get_umask(shfdtab *pfdtab)
1041{
1042#ifdef SH_PURE_STUB_MODE
1043 return 022;
1044
1045#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
1046 return 022;
1047
1048#else
1049#endif
1050}
1051
1052
1053shdir *shfile_opendir(shfdtab *pfdtab, const char *dir)
1054{
1055#ifdef SH_PURE_STUB_MODE
1056 return NULL;
1057
1058#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
1059# ifdef _MSC_VER
1060 errno = ENOSYS;
1061 return NULL;
1062# else
1063 return (shdir *)opendir(dir);
1064# endif
1065
1066#else
1067#endif
1068}
1069
1070shdirent *shfile_readdir(struct shdir *pdir)
1071{
1072#ifdef SH_PURE_STUB_MODE
1073 return NULL;
1074
1075#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
1076# ifdef _MSC_VER
1077 errno = ENOSYS;
1078 return NULL;
1079# else
1080 struct dirent *pde = readdir((DIR *)pdir);
1081 return pde ? (shdirent *)&pde->d_name[0] : NULL;
1082# endif
1083
1084#else
1085#endif
1086}
1087
1088void shfile_closedir(struct shdir *pdir)
1089{
1090#ifdef SH_PURE_STUB_MODE
1091 return NULL;
1092
1093#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
1094# ifdef _MSC_VER
1095 errno = ENOSYS;
1096# else
1097 closedir((DIR *)pdir);
1098# endif
1099
1100#else
1101#endif
1102}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette