Diff for /libaitio/src/aitio.c between versions 1.4 and 1.10.6.3

version 1.4, 2011/04/19 20:00:31 version 1.10.6.3, 2012/05/23 12:16:13
Line 1 Line 1
 /*************************************************************************  /*************************************************************************
* (C) 2010 AITNET ltd - Sofia/Bulgaria - <misho@aitbg.com>* (C) 2010 AITNET ltd - Sofia/Bulgaria - <misho@aitnet.org>
*  by Michael Pounov <misho@openbsd-bg.org>*  by Michael Pounov <misho@elwix.org>
 *  *
 * $Author$  * $Author$
 * $Id$  * $Id$
 *  *
*************************************************************************/**************************************************************************
 The ELWIX and AITNET software is distributed under the following
 terms:
 
 All of the documentation and software included in the ELWIX and AITNET
 Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
 
 Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
         by Michael Pounov <misho@elwix.org>.  All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions
 are met:
 1. Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
 2. Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
 3. All advertising materials mentioning features or use of this software
    must display the following acknowledgement:
 This product includes software developed by Michael Pounov <misho@elwix.org>
 ELWIX - Embedded LightWeight unIX and its contributors.
 4. Neither the name of AITNET nor the names of its contributors
    may be used to endorse or promote products derived from this software
    without specific prior written permission.
 
 THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 SUCH DAMAGE.
 */
 #include "global.h"  #include "global.h"
   
   
Line 14  int io_Debug; Line 51  int io_Debug;
   
 #pragma GCC visibility push(hidden)  #pragma GCC visibility push(hidden)
   
   int io_mpool;
   
 int io_Errno;  int io_Errno;
 char io_Error[STRSIZ];  char io_Error[STRSIZ];
   
Line 21  char io_Error[STRSIZ]; Line 60  char io_Error[STRSIZ];
   
   
 // io_GetErrno() Get error code of last operation  // io_GetErrno() Get error code of last operation
inline int io_GetErrno()inline int
 io_GetErrno()
 {  {
         return io_Errno;          return io_Errno;
 }  }
   
 // io_GetError() Get error text of last operation  // io_GetError() Get error text of last operation
inline const char *io_GetError()inline const char *
 io_GetError()
 {  {
         return io_Error;          return io_Error;
 }  }
   
 // io_SetErr() Set error to variables for internal use!!!  // io_SetErr() Set error to variables for internal use!!!
inline void io_SetErr(int eno, char *estr, ...)inline void
 io_SetErr(int eno, char *estr, ...)
 {  {
         va_list lst;          va_list lst;
   
Line 44  inline void io_SetErr(int eno, char *estr, ...) Line 86  inline void io_SetErr(int eno, char *estr, ...)
         va_end(lst);          va_end(lst);
 }  }
   
   // mpool_inuse() Check for mpool usage
   inline int
   mpool_inuse()
   {
           return io_mpool;
   }
   
   
   // init libaitio routine
   void
   _init()
   {
   #ifdef USE_MPOOL
           io_mpool = 42;
   #else
           io_mpool = 0;
   #endif
   }
   
   // fini libaitio routine
   void
   _fini()
   {
   }
   
   
 /*  /*
 * ioPromptRead() Read data from input h[0] with prompt to output h[1] * ioPromptRead() - Read data from input h[0] with prompt to output h[1]
  *
  * @h = file handles h[0] = input, h[1] = output, if NULL use stdin, stdout   * @h = file handles h[0] = input, h[1] = output, if NULL use stdin, stdout
  * @csPrompt = Prompt before input, may be NULL   * @csPrompt = Prompt before input, may be NULL
  * @psData = Readed data   * @psData = Readed data
  * @dataLen = Length of data   * @dataLen = Length of data
  * return: 0 EOF; -1 error:: can`t read; >0 count of readed chars   * return: 0 EOF; -1 error:: can`t read; >0 count of readed chars
 */  */
int ioPromptRead(int *h, const char *csPrompt, char * __restrict psData, int dataLen)int
 ioPromptRead(int *h, const char *csPrompt, char * __restrict psData, int dataLen)
 {  {
         int ok = 0;          int ok = 0;
         FILE *inp, *out;          FILE *inp, *out;
Line 98  int ioPromptRead(int *h, const char *csPrompt, char *  Line 167  int ioPromptRead(int *h, const char *csPrompt, char * 
 }  }
   
 /*  /*
 * ioPromptPassword() Read password from input h[0] with prompt to output h[1] * ioPromptPassword() - Read password from input h[0] with prompt to output h[1]
  *
  * @h = file handles h[0] = input, h[1] = output, if NULL use stdin, stdout   * @h = file handles h[0] = input, h[1] = output, if NULL use stdin, stdout
  * @csPrompt = Prompt before input, may be NULL   * @csPrompt = Prompt before input, may be NULL
  * @psPass = Readed password   * @psPass = Readed password
Line 106  int ioPromptRead(int *h, const char *csPrompt, char *  Line 176  int ioPromptRead(int *h, const char *csPrompt, char * 
  * @confirm = Confirm password, 0 - get password, !=0 Ask for confirmation   * @confirm = Confirm password, 0 - get password, !=0 Ask for confirmation
  * return: 0 EOF; -1 error:: can`t read; >0 count of readed chars   * return: 0 EOF; -1 error:: can`t read; >0 count of readed chars
 */  */
int ioPromptPassword(int *h, const char *csPrompt, char * __restrict psPass, int passLen, int confirm)int
 ioPromptPassword(int *h, const char *csPrompt, char * __restrict psPass, int passLen, int confirm)
 {  {
         int ret, ok = 0;          int ret, ok = 0;
         FILE *inp, *out;          FILE *inp, *out;
Line 183  next: Line 254  next:
 }  }
   
 /*  /*
 * ioRegexVerify() Function for verify data match in regex expression * ioRegexVerify() - Function for verify data match in regex expression
  *
  * @csRegex = Regulare expression pattern   * @csRegex = Regulare expression pattern
  * @csData = Data for check and verify   * @csData = Data for check and verify
  * @startPos = Return start positions   * @startPos = Return start positions
  * @endPos = Return end positions   * @endPos = Return end positions
  * return: NULL not match or error; !=NULL begin of matched data   * return: NULL not match or error; !=NULL begin of matched data
 */  */
const char *ioRegexVerify(const char *csRegex, const char *csData, int *startPos, int *endPos)const char *
 ioRegexVerify(const char *csRegex, const char *csData, int *startPos, int *endPos)
 {  {
         regex_t re;          regex_t re;
         regmatch_t match;          regmatch_t match;
Line 203  const char *ioRegexVerify(const char *csRegex, const c Line 276  const char *ioRegexVerify(const char *csRegex, const c
   
         if ((ret = regcomp(&re, csRegex, REG_EXTENDED))) {          if ((ret = regcomp(&re, csRegex, REG_EXTENDED))) {
                 regerror(ret, &re, szErr, STRSIZ);                  regerror(ret, &re, szErr, STRSIZ);
                io_SetErr(ret, "Error:: %s\n", szErr);                io_SetErr(ret, "%s", szErr);
                 regfree(&re);                  regfree(&re);
                 return NULL;                  return NULL;
         }          }
Line 221  const char *ioRegexVerify(const char *csRegex, const c Line 294  const char *ioRegexVerify(const char *csRegex, const c
   
         if (ret) {          if (ret) {
                 regerror(ret, &re, szErr, STRSIZ);                  regerror(ret, &re, szErr, STRSIZ);
                io_SetErr(ret, "Error:: %s\n", szErr);                io_SetErr(ret, "%s", szErr);
                 pos = NULL;                  pos = NULL;
         }          }
   
Line 230  const char *ioRegexVerify(const char *csRegex, const c Line 303  const char *ioRegexVerify(const char *csRegex, const c
 }  }
   
 /*  /*
 * ioRegexGet() Function for get data match in regex expression * ioRegexGet() - Function for get data match in regex expression
  *
  * @csRegex = Regulare expression pattern   * @csRegex = Regulare expression pattern
  * @csData = Data from get   * @csData = Data from get
  * @psString = Returned string if match   * @psString = Returned string if match
  * @strLen = Length of string   * @strLen = Length of string
  * return: 0 not match; >0 count of returned chars   * return: 0 not match; >0 count of returned chars
 */  */
int ioRegexGet(const char *csRegex, const char *csData, char * __restrict psString, int strLen)int
 ioRegexGet(const char *csRegex, const char *csData, char * __restrict psString, int strLen)
 {  {
         int sp, ep, len;          int sp, ep, len;
         const char *str;          const char *str;
Line 259  int ioRegexGet(const char *csRegex, const char *csData Line 334  int ioRegexGet(const char *csRegex, const char *csData
 }  }
   
 /*  /*
 * ioRegexReplace() Function for replace data match in regex expression with newdata * ioRegexReplace() - Function for replace data match in regex expression with newdata
  *
  * @csRegex = Regulare expression pattern   * @csRegex = Regulare expression pattern
  * @csData = Source data   * @csData = Source data
  * @csNew = Data for replace   * @csNew = Data for replace
 * return: NULL not match or error; !=NULL allocated new string, must be free after use! * return: NULL not match or error; !=NULL allocated new string, must be xfree after use!
 */  */
char *ioRegexReplace(const char *csRegex, const char *csData, const char *csNew)char *
 ioRegexReplace(const char *csRegex, const char *csData, const char *csNew)
 {  {
         int sp, ep, len;          int sp, ep, len;
         char *str = NULL;          char *str = NULL;
Line 278  char *ioRegexReplace(const char *csRegex, const char * Line 355  char *ioRegexReplace(const char *csRegex, const char *
   
         // ___ before match          // ___ before match
         len = sp + 1;          len = sp + 1;
        str = malloc(len);        str = xmalloc(len);
         if (!str) {          if (!str) {
                 LOGERR;                  LOGERR;
                 return NULL;                  return NULL;
Line 287  char *ioRegexReplace(const char *csRegex, const char * Line 364  char *ioRegexReplace(const char *csRegex, const char *
         // * replace match *          // * replace match *
         if (csNew) {          if (csNew) {
                 len += strlen(csNew);                  len += strlen(csNew);
                str = realloc(str, len);                str = xrealloc(str, len);
                 if (!str) {                  if (!str) {
                         LOGERR;                          LOGERR;
                         return NULL;                          return NULL;
Line 296  char *ioRegexReplace(const char *csRegex, const char * Line 373  char *ioRegexReplace(const char *csRegex, const char *
         }          }
         // after match ___          // after match ___
         len += strlen(csData) - ep;          len += strlen(csData) - ep;
        str = realloc(str, len);        str = xrealloc(str, len);
         if (!str) {          if (!str) {
                 LOGERR;                  LOGERR;
                 return NULL;                  return NULL;
Line 307  char *ioRegexReplace(const char *csRegex, const char * Line 384  char *ioRegexReplace(const char *csRegex, const char *
 }  }
   
 /*  /*
 * ioVarAst() Function for evaluate string like asterisk variable "{text[:[-]#[:#]]}" * ioStrAst() - Function for evaluate string like asterisk variable "{text[:[-]#[:#]]}"
  *
  * @csString = Input string   * @csString = Input string
 * return: NULL error, !=NULL Allocated new string evaluated from input string, must be free() * return: NULL error, !=NULL Allocated new string evaluated from input string, must be xfree()
 */  */
 char *  char *
ioVarAst(const char *csString)ioStrAst(const char *csString)
 {  {
         char *ext, *str, *out = NULL;          char *ext, *str, *out = NULL;
         int e[2] = { 0 };          int e[2] = { 0 };
Line 322  ioVarAst(const char *csString) Line 400  ioVarAst(const char *csString)
   
         if (!strchr(csString, '{') || !strrchr(csString, '}')) {          if (!strchr(csString, '{') || !strrchr(csString, '}')) {
                 memset(io_Error, 0, STRSIZ);                  memset(io_Error, 0, STRSIZ);
                snprintf(io_Error, STRSIZ, "Error:: Invalid input string format ... "                snprintf(io_Error, STRSIZ, "Invalid input string format ... "
                                 "must be like {text[:[-]#[:#]]}");                                  "must be like {text[:[-]#[:#]]}");
                 io_Errno = EINVAL;                  io_Errno = EINVAL;
                 return NULL;                  return NULL;
Line 350  ioVarAst(const char *csString) Line 428  ioVarAst(const char *csString)
                 ext = str;                  ext = str;
   
         out = strdup(ext);          out = strdup(ext);
        free(str);        xfree(str);
   
         return out;          return out;
 }  }
   
   
 /*  /*
 * ioMkDir() Function for racursive directory creation and validation * ioMkDir() - Function for racursive directory creation and validation
  *
  * @csDir = Full directory path   * @csDir = Full directory path
  * @mode = Mode for directory creation if missing dir   * @mode = Mode for directory creation if missing dir
  * return: -1 error, 0 directory path exist, >0 created missing dirs   * return: -1 error, 0 directory path exist, >0 created missing dirs
Line 399  ioMkDir(const char *csDir, int mode) Line 478  ioMkDir(const char *csDir, int mode)
         }          }
 end:  end:
         chdir(szOld);          chdir(szOld);
        free(str);        xfree(str);
         return cx;          return cx;
 }  }
   
 /*  /*
 * ioWatchDirLoop() Function for watching changes in directory and fire callback * ioWatchDirLoop() - Function for watching changes in directory and fire callback
  *
  * @csDir = Full directory path   * @csDir = Full directory path
  * @callback = Callback if raise event! nOp -1 delete, 0 change/move, 1 create   * @callback = Callback if raise event! nOp -1 delete, 0 change/move, 1 create
  * return: -1 error, !=-1 ok, number of total signaled events   * return: -1 error, !=-1 ok, number of total signaled events
Line 512  ioWatchDirLoop(const char *csDir, int (*callback)(cons Line 592  ioWatchDirLoop(const char *csDir, int (*callback)(cons
         close(d);          close(d);
         close(kq);          close(kq);
         return n;          return n;
   }
   
   /*
    * ioCreatePIDFile() - Create PID file
    *
    * @csName = PID filename
    * @ifExists = !=0 if filename exists return error
    * return: -1 error or 0 ok
    */
   inline int
   ioCreatePIDFile(const char *csName, int ifExists)
   {
           int fd;
           char str[STRSIZ] = { 0 };
   
           if (!csName)
                   return -1;
   
           fd = open(csName, O_WRONLY | O_CREAT | (ifExists ? O_EXCL : 0), 0644);
           if (fd == -1) {
                   LOGERR;
                   return -1;
           }
           snprintf(str, sizeof str, "%d", getpid());
           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
    * @sndbuf = SO_SNDBUF value, if 0 use default
    * return: 0 error, >0 ok, sended bytes
    */
   size_t
   ioSendFile(int s, const char *csFile, size_t sendLen, off_t offset, int sndbuf)
   {
           void *addr;
           int fd;
           size_t len = 0;
           register size_t off = 0;
   
           if (!csFile)
                   return 0;
   
           if (sndbuf)
                   if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof sndbuf) == -1) {
                           LOGERR;
                           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);
   
           while (off < sendLen && (len = write(s, addr + off, sendLen - off)) != -1)
                   off += len;
           if (len == -1) {
                   LOGERR;
                   munmap(addr, sendLen);
                   return 0;
           } else
                   len = off;
   
           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
    * @rcvbuf = SO_RCVBUF value, if 0 use default
    * return: 0 error, >0 ok, received bytes
    */
   size_t
   ioRecvFile(int s, const char *csFile, size_t recvLen, int over, int rcvbuf)
   {
           void *addr;
           int fd;
           size_t len = 0;
           register size_t off = 0;
           struct pollfd pfd = { s, POLLIN | POLLPRI, 0 };
   
           if (!csFile || !recvLen)
                   return 0;
           if (!over && !access(csFile, F_OK))
                   return 0;
   
           if (rcvbuf)
                   if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof rcvbuf) == -1) {
                           LOGERR;
                           return 0;
                   }
   
           fd = open(csFile, O_WRONLY | O_CREAT | O_TRUNC, over);
           if (fd == -1) {
                   LOGERR;
                   unlink(csFile);
                   return 0;
           }
           if (ftruncate(fd, recvLen) == -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);
   
           while (off < recvLen && poll(&pfd, 1, RECV_TIMEOUT) != -1)
                   while (off < recvLen && (len = read(s, addr + off, recvLen - off)) != -1)
                           off += len;
           if (len == -1) {
                   LOGERR;
                   munmap(addr, recvLen);
                   unlink(csFile);
                   return 0;
           } else
                   len = off;
   
           if (len != recvLen)
                   io_SetErr(EAGAIN, "Different sizes - request %u bytes, actually received %u bytes\n", 
                                   recvLen, len);
   
           munmap(addr, recvLen);
           return len;
 }  }

Removed from v.1.4  
changed lines
  Added in v.1.10.6.3


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>