--- libaitio/src/aitio.c 2011/10/31 13:53:51 1.7 +++ libaitio/src/aitio.c 2011/11/02 13:13:48 1.7.2.1 @@ -3,7 +3,7 @@ * by Michael Pounov * * $Author: misho $ -* $Id: aitio.c,v 1.7 2011/10/31 13:53:51 misho Exp $ +* $Id: aitio.c,v 1.7.2.1 2011/11/02 13:13:48 misho Exp $ * ************************************************************************** The ELWIX and AITNET software is distributed under the following @@ -583,4 +583,124 @@ ioCreatePIDFile(const char *csName, int ifExists) write(fd, str, strlen(str)); close(fd); return 0; +} + + +/* + * ioSendFile() AITNET sendfile() userland implementation, not dependant from OS + * @s = socket + * @csFile = file for send + * @sendLen = bytes to send, if 0 send all data + * @offset = start file offset + * return: 0 error, >0 ok, sended bytes + */ +size_t +ioSendFile(int s, const char *csFile, size_t sendLen, off_t offset) +{ + void *addr; + int fd; + size_t len; + + if (!csFile) + return 0; + + fd = open(csFile, O_RDONLY); + if (fd == -1) { + LOGERR; + return 0; + } + if (!sendLen) { + sendLen = lseek(fd, 0, SEEK_END); + if (sendLen == -1) { + LOGERR; + close(fd); + return 0; + } + } + addr = mmap(NULL, sendLen, PROT_READ, MAP_SHARED, fd, offset); + if (addr == MAP_FAILED) { + LOGERR; + close(fd); + return 0; + } else + close(fd); + + len = write(s, addr, sendLen); + if (len == -1) { + LOGERR; + munmap(addr, sendLen); + return 0; + } + + if (len != sendLen) { + io_SetErr(ECANCELED, "Different sizes - request %u bytes, actually sended %u bytes\n", + sendLen, len); + len ^= len; + } + + munmap(addr, sendLen); + return len; +} + +/* + * ioRecvFile() Receive file from socket, fastest (zero-copy) way + * @s = socket + * @csFile = file for receive + * @recvLen = receive bytes + * @over = overwrite file if exists with mode like 0644 + * return: 0 error, >0 ok, received bytes + */ +size_t +ioRecvFile(int s, const char *csFile, size_t recvLen, int over) +{ + void *addr; + int fd; + size_t len; + + if (!csFile || !recvLen) + return 0; + if (!over && !access(csFile, F_OK)) + return 0; + + fd = open(csFile, O_WRONLY | O_CREAT | O_TRUNC, over); + if (fd == -1) { + LOGERR; + unlink(csFile); + return 0; + } + if (lseek(fd, recvLen - 1, SEEK_SET) == -1) { + LOGERR; + close(fd); + unlink(csFile); + return 0; + } + if (write(fd, "", 1) == -1) { + LOGERR; + close(fd); + unlink(csFile); + return 0; + } + addr = mmap(NULL, recvLen, PROT_WRITE, MAP_SHARED, fd, 0); + if (addr == MAP_FAILED) { + LOGERR; + close(fd); + unlink(csFile); + return 0; + } else + close(fd); + + len = read(s, addr, recvLen); + if (len == -1) { + LOGERR; + munmap(addr, recvLen); + unlink(csFile); + return 0; + } + + if (len != recvLen) + io_SetErr(EAGAIN, "Different sizes - request %u bytes, actually received %u bytes\n", + recvLen, len); + + munmap(addr, recvLen); + return len; }