iofd.c

00001 /*
00002  * Copyright (c) 2005-2012 by KoanLogic s.r.l. <http://www.koanlogic.com>
00003  * All rights reserved.
00004  *
00005  * This file is part of KLone, and as such it is subject to the license stated
00006  * in the LICENSE file which you have received as part of this distribution.
00007  *
00008  * $Id: iofd.c,v 1.14 2007/07/20 14:12:30 tat Exp $
00009  */
00010 
00011 #include "klone_conf.h"
00012 #include <fcntl.h>
00013 #include <unistd.h>
00014 #include <u/libu.h>
00015 #include <klone/io.h>
00016 #include <klone/io.h>
00017 #include <klone/ioprv.h>
00018 
00019 struct io_fd_s
00020 {
00021     struct io_s io; /* must be the first item */
00022     int fd;
00023     int flags;
00024     int issock;     /* >0 if fd is a SOCKET (win32 only) */
00025 };
00026 
00027 typedef struct io_fd_s io_fd_t;
00028 
00029 static ssize_t io_fd_read(io_fd_t *io, char *buf, size_t size);
00030 static ssize_t io_fd_write(io_fd_t *io, const char *buf, size_t size);
00031 static ssize_t io_fd_seek(io_fd_t *io, size_t off);
00032 static ssize_t io_fd_tell(io_fd_t *io);
00033 static int io_fd_close(io_fd_t *io);
00034 static int io_fd_free(io_fd_t *io);
00035 
00036 static ssize_t io_fd_read(io_fd_t *ifd, char *buf, size_t size)
00037 {
00038     ssize_t c;
00039 
00040     dbg_return_if (ifd == NULL, ~0);
00041     dbg_return_if (buf == NULL, ~0);
00042     
00043 again:
00044     if(!ifd->issock)
00045         c = read(ifd->fd, buf, size);
00046     else
00047         c = recv(ifd->fd, buf, size, 0);
00048     /* if(c < 0 && (errno == EINTR || errno == EAGAIN)) */
00049     if(c < 0 && errno == EINTR)
00050         goto again; 
00051 
00052     dbg_err_sif(c == -1); 
00053 
00054     return c;
00055 err:
00056     return -1;
00057 }
00058 
00059 static ssize_t io_fd_write(io_fd_t *ifd, const char *buf, size_t size)
00060 {
00061     ssize_t c;
00062 
00063     dbg_return_if (ifd == NULL, ~0);
00064     dbg_return_if (buf == NULL, ~0);
00065  
00066 again:
00067     if(!ifd->issock)
00068         c = write(ifd->fd, buf, size);
00069     else
00070         c = send(ifd->fd, buf, size, 0);
00071     /* if(c < 0 && (errno == EINTR || errno == EAGAIN)) */
00072     if(c < 0 && errno == EINTR)
00073         goto again; 
00074 
00075     dbg_err_sif(c == -1); 
00076 
00077     return c;
00078 err:
00079     return -1;
00080 }
00081 
00082 static ssize_t io_fd_seek(io_fd_t *ifd, size_t off)
00083 {
00084     dbg_return_if (ifd == NULL, -1);
00085 
00086     return lseek(ifd->fd, off, SEEK_SET);
00087 }
00088 
00089 static ssize_t io_fd_tell(io_fd_t *ifd)
00090 {
00091     dbg_return_if (ifd == NULL, -1);
00092 
00093     return lseek(ifd->fd, 0, SEEK_CUR);
00094 }
00095 
00096 /* close the underlaying fd (may be called more then once) */
00097 static int io_fd_close(io_fd_t *ifd)
00098 {
00099     dbg_return_if (ifd == NULL, ~0);
00100     
00101     if(ifd->flags & IO_FD_CLOSE && ifd->fd != -1)
00102     {
00103 #ifdef OS_WIN
00104         if(ifd->issock)
00105         {
00106             closesocket(ifd->fd);
00107         } else
00108             close(ifd->fd);
00109 #else
00110             close(ifd->fd);
00111 #endif
00112         ifd->fd = -1;
00113     }
00114 
00115     return 0;
00116 }
00117 
00118 static int io_fd_free(io_fd_t *ifd)
00119 {
00120     dbg_if(io_fd_close(ifd));
00121 
00122     return 0;
00123 }
00124 
00125 int io_fd_get_d(io_t *io)
00126 {
00127     io_fd_t *ifd = (io_fd_t*)io;
00128     dbg_err_if(io == NULL);
00129     dbg_err_if(ifd->io.type != IO_TYPE_FD);
00130 
00131     return ifd->fd;
00132 err:
00133     return -1;
00134 }
00135 
00136 int io_fd_create(int fd, int flags, io_t **pio)
00137 {
00138     io_fd_t *ifd = NULL;
00139 
00140     dbg_err_if (pio == NULL);
00141 
00142     dbg_err_if(io_create(io_fd_t, (io_t**)&ifd));
00143 
00144     ifd->io.type = IO_TYPE_FD;
00145 
00146     ifd->fd = fd;
00147     ifd->flags = flags;
00148     ifd->io.read = (io_read_op) io_fd_read;
00149     ifd->io.write = (io_write_op) io_fd_write;
00150     ifd->io.seek = (io_seek_op) io_fd_seek;
00151     ifd->io.tell = (io_tell_op) io_fd_tell;
00152     ifd->io.close = (io_close_op) io_fd_close; 
00153     ifd->io.free = (io_free_op) io_fd_free; 
00154     
00155 #ifdef OS_WIN
00156     u_long ret;
00157     if(ioctlsocket(fd, FIONREAD, &ret) == 0)
00158         ifd->issock++; /* is a socket, use recv/send instead of read/write  */
00159     _setmode(fd, _O_BINARY); /* we never want Windows CR/LF translation */
00160 #endif
00161 
00162     *pio = (io_t*)ifd;
00163 
00164     return 0;
00165 err:
00166     if(ifd)
00167         io_free((io_t*)ifd);
00168     return ~0;
00169 }

←Products
Copyright © 2005-2012 - KoanLogic S.r.l. - All rights reserved