00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 #include <config.h>
00046
00047 #include <errno.h>
00048 #include <fcntl.h>
00049 #include <io.h>
00050 #include <share.h>
00051 #include <stdio.h>
00052 #include <stdarg.h>
00053
00054
00055
00056
00057
00058 #include "sys/socket.h"
00059 #include <sys/stat.h>
00060 #include <ws2tcpip.h>
00061
00062 #include "misc.h"
00063 #include "sys/uio.h"
00064 #include "unistd.h"
00065
00066
00067
00068
00069
00070
00071
00072 #define MAX_FDS (FD_SETSIZE * 2)
00073
00074 enum fdmap_io_type {
00075 FDMAP_IO_NOTUSED = 0,
00076 FDMAP_IO_FILE,
00077 FDMAP_IO_SOCKET,
00078 FDMAP_IO_ANY
00079 };
00080
00081 struct fdmap {
00082 int handle;
00083 enum fdmap_io_type type;
00084 };
00085
00086 static struct fdmap fdmap[MAX_FDS] = {
00087 {0, FDMAP_IO_FILE},
00088 {1, FDMAP_IO_FILE},
00089 {2, FDMAP_IO_FILE}
00090 };
00091 static int nfd = 3;
00092
00093
00094
00095
00096
00097
00098
00099 static int
00100 get_fd(void)
00101 {
00102 int fd;
00103
00104 for (fd = 0; fd < nfd && fdmap[fd].type != FDMAP_IO_NOTUSED; fd++) ;
00105 if (fd == MAX_FDS) {
00106 errno = EMFILE;
00107 return -1;
00108 }
00109 if (fd == nfd) {
00110 fdmap[fd].type = FDMAP_IO_NOTUSED;
00111 nfd++;
00112 }
00113 return fd;
00114 }
00115
00116
00117
00118
00119 static void
00120 free_fd(int fd)
00121 {
00122 fdmap[fd].type = FDMAP_IO_NOTUSED;
00123 for(; fdmap[nfd - 1].type == FDMAP_IO_NOTUSED; nfd--) ;
00124 }
00125
00126
00127
00128
00129 static void
00130 set_fd(int fd, enum fdmap_io_type type, int handle)
00131 {
00132 int i;
00133
00134 fdmap[fd].handle = handle;
00135 fdmap[fd].type = type;
00136
00137
00138
00139
00140
00141
00142 for (i = 0; i < nfd; i++) {
00143 if (i != fd && type == fdmap[i].type && handle == fdmap[i].handle)
00144 free_fd(i);
00145 }
00146 }
00147
00148
00149
00150
00151
00152
00153
00154
00155 static int
00156 lookup_handle(int fd, enum fdmap_io_type d_type, int error,
00157 enum fdmap_io_type *type_ptr, int *handle_ptr)
00158 {
00159
00160 if (fd < 0 || fd >= MAX_FDS) {
00161 if (error != 0)
00162 errno = error;
00163 return 0;
00164 } else if ((fdmap[fd].type != d_type && d_type != FDMAP_IO_ANY) ||
00165 (fdmap[fd].type == FDMAP_IO_NOTUSED && d_type == FDMAP_IO_ANY)) {
00166 if (error != 0)
00167 errno = error;
00168 return 0;
00169 }
00170 if (type_ptr != NULL)
00171 *type_ptr = fdmap[fd].type;
00172 if (handle_ptr != NULL)
00173 *handle_ptr = fdmap[fd].handle;
00174 return 1;
00175 }
00176
00177
00178
00179
00180
00181
00182
00183 static int
00184 lookup_fd(int handle, enum fdmap_io_type d_type)
00185 {
00186 int i;
00187
00188 for (i = 0; i < nfd; i++)
00189 if (fdmap[i].handle == handle && fdmap[i].type == d_type)
00190 return i;
00191 return -1;
00192 }
00193
00194
00195
00196
00197 int
00198 posix_fd2socket(int fd)
00199 {
00200 int handle;
00201 enum fdmap_io_type type;
00202
00203 if (!lookup_handle(fd, FDMAP_IO_SOCKET, WSAENOTSOCK,
00204 &type, &handle))
00205 return INVALID_SOCKET;
00206 return handle;
00207 }
00208
00209 #define SOCKET_FUNCTION(expr) \
00210 int result; \
00211 int handle; \
00212 \
00213 if (!lookup_handle(fd, FDMAP_IO_SOCKET, \
00214 ENOTSOCK, NULL, &handle)) \
00215 return -1; \
00216 \
00217 result = (expr); \
00218 if (result == SOCKET_ERROR) { \
00219 errno = WSAGetLastError(); \
00220 return -1; \
00221 } \
00222 return result;
00223
00224
00225
00226
00227 #undef accept
00228 int
00229 posix_accept(int fd, struct sockaddr *addr, socklen_t *addrlen)
00230 {
00231 int new_fd;
00232 int handle;
00233 SOCKET new_handle;
00234
00235 if (!lookup_handle(fd, FDMAP_IO_SOCKET, ENOTSOCK, NULL, &handle))
00236 return -1;
00237
00238 new_fd = get_fd();
00239 if (new_fd < 0)
00240 return -1;
00241
00242 new_handle = accept(handle, addr, addrlen);
00243 if (new_handle == INVALID_SOCKET) {
00244 free_fd(new_fd);
00245 errno = WSAGetLastError();
00246 return -1;
00247 }
00248 set_fd(new_fd, FDMAP_IO_SOCKET, (int)new_handle);
00249 return new_fd;
00250 }
00251
00252
00253
00254
00255 #undef bind
00256 int
00257 posix_bind(int fd, const struct sockaddr *name, socklen_t namelen)
00258 {
00259 SOCKET_FUNCTION(bind(handle, name, namelen))
00260 }
00261
00262
00263
00264
00265 #undef listen
00266 int
00267 posix_listen(int fd, int backlog)
00268 {
00269 SOCKET_FUNCTION(listen(handle, backlog))
00270 }
00271
00272
00273
00274
00275 #undef setsockopt
00276 int
00277 posix_setsockopt(int fd, int level, int optname,
00278 const void *optval, socklen_t optlen)
00279 {
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 if (level == SOL_SOCKET && optname == SO_REUSEADDR)
00290 return 0;
00291 {
00292 SOCKET_FUNCTION(setsockopt(handle, level, optname,
00293 optval, optlen))
00294 }
00295 }
00296
00297
00298
00299
00300 #undef shutdown
00301 int
00302 posix_shutdown(int fd, int how)
00303 {
00304 SOCKET_FUNCTION(shutdown(handle, how))
00305 }
00306
00307
00308
00309
00310 #undef socket
00311 int
00312 posix_socket(int domain, int type, int protocol)
00313 {
00314 SOCKET handle;
00315 int new_fd;
00316
00317 if ((new_fd = get_fd()) < 0)
00318 return -1;
00319
00320 handle = socket(domain, type, protocol);
00321 if (handle == INVALID_SOCKET) {
00322 free_fd(new_fd);
00323 errno = WSAGetLastError();
00324 return -1;
00325 }
00326 set_fd(new_fd, FDMAP_IO_SOCKET, (int)handle);
00327 return new_fd;
00328 }
00329
00330 #ifdef HAVE_GETADDRINFO
00331 const char *
00332 inet_ntop(int af, const void *src, char *dst, socklen_t len)
00333 {
00334 struct sockaddr *sa;
00335 struct sockaddr_in sin;
00336 struct sockaddr_in6 sin6;
00337 size_t salen;
00338
00339 if (af == AF_INET) {
00340 memset(&sin, 0, sizeof(sin));
00341 sin.sin_family = af;
00342 memcpy(&sin.sin_addr, src, sizeof(sin.sin_addr));
00343 sa = (struct sockaddr *)&sin;
00344 salen = sizeof(sin);
00345 } else if (af == AF_INET6) {
00346 memset(&sin6, 0, sizeof(sin6));
00347 sin6.sin6_family = af;
00348 memcpy(&sin6.sin6_addr, src, sizeof(sin6.sin6_addr));
00349 sa = (struct sockaddr *)&sin6;
00350 salen = sizeof(sin6);
00351 } else {
00352 errno = EAFNOSUPPORT;
00353 return NULL;
00354 }
00355
00356 if (getnameinfo(sa, salen, dst, len, NULL, 0, NI_NUMERICHOST)) {
00357 errno = EAFNOSUPPORT;
00358 return NULL;
00359 }
00360
00361 return dst;
00362 }
00363 #endif
00364
00365 #define FILE_FUNCTION(type, expr) \
00366 int handle; \
00367 \
00368 if (!lookup_handle(fd, (type), EBADF, NULL, &handle)) \
00369 return -1; \
00370 \
00371 return (expr);
00372
00373
00374
00375
00376 int
00377 posix_close(int fd)
00378 {
00379 int result;
00380 int handle;
00381 enum fdmap_io_type type;
00382
00383 if (!lookup_handle(fd, FDMAP_IO_ANY, EBADF, &type, &handle))
00384 return -1;
00385
00386 free_fd(fd);
00387 switch (type) {
00388 case FDMAP_IO_SOCKET:
00389 result = closesocket(handle);
00390 if (result == SOCKET_ERROR) {
00391 errno = WSAGetLastError();
00392 return -1;
00393 }
00394 return result;
00395 case FDMAP_IO_FILE:
00396 return _close(handle);
00397 default:
00398 CANT_REACH();
00399 return -1;
00400 }
00401 }
00402
00403
00404
00405
00406
00407
00408
00409 int
00410 posix_fsync(int fd)
00411 {
00412 FILE_FUNCTION(FDMAP_IO_FILE, _commit(handle))
00413 }
00414
00415
00416
00417
00418
00419
00420
00421 #undef fstat
00422 int
00423 posix_fstat(int fd, struct stat *buffer)
00424 {
00425 FILE_FUNCTION(FDMAP_IO_ANY, fstat(handle, buffer))
00426 }
00427
00428
00429
00430
00431 off_t
00432 posix_lseek(int fd, off_t offset, int origin)
00433 {
00434 FILE_FUNCTION(FDMAP_IO_FILE, _lseek(handle, offset, origin))
00435 }
00436
00437
00438
00439
00440
00441
00442 int
00443 posix_open(const char *fname, int oflag, ...)
00444 {
00445 va_list ap;
00446 int pmode = 0, new_fd;
00447 int handle;
00448
00449 if (oflag & O_CREAT) {
00450 va_start(ap, oflag);
00451 pmode = va_arg(ap, int);
00452 va_end(ap);
00453 }
00454
00455 if ((new_fd = get_fd()) < 0)
00456 return -1;
00457
00458
00459
00460
00461
00462 handle = _sopen(fname, oflag,
00463 oflag & O_RDONLY ? SH_DENYNO : SH_DENYWR, pmode);
00464 if (handle == -1) {
00465 free_fd(new_fd);
00466 return -1;
00467 }
00468 set_fd(new_fd, FDMAP_IO_FILE, handle);
00469 return new_fd;
00470 }
00471
00472 #define SHARED_FUNCTION(socket_expr, file_expr) \
00473 int result; \
00474 int handle; \
00475 enum fdmap_io_type type; \
00476 \
00477 if (!lookup_handle(fd, FDMAP_IO_ANY, EBADF, &type, &handle)) \
00478 return -1; \
00479 \
00480 switch (type) { \
00481 case FDMAP_IO_SOCKET: \
00482 result = (socket_expr); \
00483 if (result == SOCKET_ERROR) { \
00484 errno = WSAGetLastError(); \
00485 return -1; \
00486 } \
00487 return result; \
00488 case FDMAP_IO_FILE: \
00489 return (file_expr); \
00490 default: \
00491 CANT_REACH(); \
00492 return -1; \
00493 }
00494
00495
00496
00497
00498 ssize_t
00499 posix_read(int fd, void *buffer, size_t count)
00500 {
00501 SHARED_FUNCTION(recv(handle, buffer, count, 0),
00502 _read(handle, buffer, count))
00503 }
00504
00505
00506
00507
00508
00509 ssize_t
00510 readv(int fd, const struct iovec *iov, int iovcnt)
00511 {
00512 int i;
00513 unsigned char *buffer, *buffer_location;
00514 size_t total_bytes = 0;
00515 int bytes_read;
00516 size_t bytes_left;
00517
00518 for (i = 0; i < iovcnt; i++) {
00519 total_bytes += iov[i].iov_len;
00520 }
00521
00522 buffer = malloc(total_bytes);
00523 if (buffer == NULL && total_bytes != 0) {
00524 errno = ENOMEM;
00525 return -1;
00526 }
00527
00528 bytes_read = posix_read(fd, buffer, total_bytes);
00529 if (bytes_read <= 0) {
00530 free(buffer);
00531 return -1;
00532 }
00533
00534 bytes_left = bytes_read;
00535 buffer_location = buffer;
00536 for (i = 0; i < iovcnt; i++) {
00537 size_t copy = MIN(iov[i].iov_len, bytes_left);
00538
00539 memcpy(iov[i].iov_base, buffer_location, copy);
00540
00541 buffer_location += copy;
00542 bytes_left -= copy;
00543 if (bytes_left == 0)
00544 break;
00545 }
00546
00547 free(buffer);
00548
00549 return bytes_read;
00550 }
00551
00552
00553
00554
00555 ssize_t
00556 posix_write(int fd, const void *buffer, size_t count)
00557 {
00558 SHARED_FUNCTION(send(handle, buffer, count, 0),
00559 _write(handle, buffer, count))
00560 }
00561
00562
00563
00564
00565
00566 ssize_t
00567 writev(int fd, const struct iovec *iov, int iovcnt)
00568 {
00569 int i;
00570 unsigned char *buffer, *buffer_location;
00571 size_t total_bytes = 0;
00572 int bytes_written;
00573
00574 for (i = 0; i < iovcnt; i++)
00575 total_bytes += iov[i].iov_len;
00576
00577 buffer = malloc(total_bytes);
00578 if (buffer == NULL && total_bytes != 0) {
00579 errno = ENOMEM;
00580 return -1;
00581 }
00582
00583 buffer_location = buffer;
00584 for (i = 0; i < iovcnt; i++) {
00585 memcpy(buffer_location, iov[i].iov_base, iov[i].iov_len);
00586 buffer_location += iov[i].iov_len;
00587 }
00588
00589 bytes_written = posix_write(fd, buffer, total_bytes);
00590
00591 free(buffer);
00592
00593 if (bytes_written <= 0)
00594 return -1;
00595 return bytes_written;
00596 }
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606 int
00607 fileno(FILE *stream)
00608 {
00609 int fd;
00610 int handle;
00611
00612 if (stream == NULL) {
00613 errno = EBADF;
00614 return -1;
00615 }
00616
00617 handle = _fileno(stream);
00618
00619 fd = lookup_fd(handle, FDMAP_IO_FILE);
00620 if (fd >= 0)
00621 return fd;
00622
00623 if ((fd = get_fd()) < 0) {
00624 errno = EBADF;
00625 return -1;
00626 }
00627
00628 set_fd(fd, FDMAP_IO_FILE, handle);
00629 return fd;
00630 }
00631
00632
00633
00634
00635
00636
00637
00638 int
00639 fcntl(int fd, int cmd, ...)
00640 {
00641 va_list ap;
00642 int value;
00643 unsigned int nonblocking;
00644 int result;
00645 long bytes_returned;
00646 int handle;
00647 enum fdmap_io_type type;
00648
00649 if (!lookup_handle(fd, FDMAP_IO_ANY, EBADF, &type, &handle))
00650 return -1;
00651
00652 switch (cmd)
00653 {
00654 case F_GETFL:
00655
00656
00657
00658
00659 if (type == FDMAP_IO_SOCKET) {
00660 result = WSAIoctl(handle, FIONBIO, NULL, 0,&nonblocking,
00661 sizeof (nonblocking), &bytes_returned, NULL, NULL);
00662
00663 if(result < 0) {
00664 errno = WSAGetLastError();
00665 return -1;
00666 }
00667
00668 if (nonblocking)
00669 return O_NONBLOCK;
00670 else
00671 return 0;
00672 }
00673 break;
00674 case F_SETFL:
00675 if (type == FDMAP_IO_SOCKET) {
00676 va_start(ap, cmd);
00677 value = va_arg(ap, int);
00678 va_end(ap);
00679 if (value & O_NONBLOCK)
00680 nonblocking = 1;
00681 else
00682 nonblocking = 0;
00683
00684 result = WSAIoctl(handle, FIONBIO, &nonblocking,
00685 sizeof (nonblocking), NULL, 0, &bytes_returned,
00686 NULL, NULL);
00687
00688 if(result < 0) {
00689 errno = WSAGetLastError();
00690 return -1;
00691 }
00692 return result;
00693 }
00694 break;
00695 case F_SETLK:
00696
00697
00698
00699
00700
00701 return 0;
00702 }
00703 errno = EINVAL;
00704 return -1;
00705 }