--- libaitio/src/aitio.c 2011/12/13 02:23:08 1.8 +++ libaitio/src/aitio.c 2016/08/10 14:19:50 1.17.8.3 @@ -3,7 +3,7 @@ * by Michael Pounov * * $Author: misho $ -* $Id: aitio.c,v 1.8 2011/12/13 02:23:08 misho Exp $ +* $Id: aitio.c,v 1.17.8.3 2016/08/10 14:19:50 misho Exp $ * ************************************************************************** The ELWIX and AITNET software is distributed under the following @@ -12,7 +12,7 @@ terms: All of the documentation and software included in the ELWIX and AITNET Releases is copyrighted by ELWIX - Sofia/Bulgaria -Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 +Copyright 2004 - 2016 by Michael Pounov . All rights reserved. Redistribution and use in source and binary forms, with or without @@ -46,9 +46,6 @@ SUCH DAMAGE. #include "global.h" -int io_Debug; - - #pragma GCC visibility push(hidden) int io_Errno; @@ -58,35 +55,36 @@ char io_Error[STRSIZ]; // io_GetErrno() Get error code of last operation -inline int +int io_GetErrno() { return io_Errno; } // io_GetError() Get error text of last operation -inline const char * +const char * io_GetError() { return io_Error; } // io_SetErr() Set error to variables for internal use!!! -inline void +void io_SetErr(int eno, char *estr, ...) { va_list lst; io_Errno = eno; - memset(io_Error, 0, STRSIZ); + memset(io_Error, 0, sizeof io_Error); va_start(lst, estr); - vsnprintf(io_Error, STRSIZ, estr, lst); + vsnprintf(io_Error, sizeof io_Error, estr, lst); va_end(lst); } /* - * 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 * @csPrompt = Prompt before input, may be NULL * @psData = Readed data @@ -123,7 +121,11 @@ ioPromptRead(int *h, const char *csPrompt, char * __re memset(szLine, 0, BUFSIZ); if (!fgets(szLine, BUFSIZ, inp)) { clearerr(inp); +#ifdef HAVE_FPURGE fpurge(out); +#else + __fpurge(out); +#endif fflush(out); return 0; } @@ -139,7 +141,8 @@ ioPromptRead(int *h, const char *csPrompt, char * __re } /* - * 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 * @csPrompt = Prompt before input, may be NULL * @psPass = Readed password @@ -153,7 +156,11 @@ ioPromptPassword(int *h, const char *csPrompt, char * int ret, ok = 0; FILE *inp, *out; char szLine[2][STRSIZ]; +#ifndef __linux__ struct sgttyb tty_state; +#else + struct termios o; +#endif if (!psPass || !passLen) return -1; @@ -169,6 +176,7 @@ ioPromptPassword(int *h, const char *csPrompt, char * return -1; } +#ifndef __linux__ if (ioctl(fileno(inp), TIOCGETP, &tty_state) == -1) { LOGERR; return -1; @@ -179,6 +187,18 @@ ioPromptPassword(int *h, const char *csPrompt, char * return -1; } } +#else + if (tcgetattr(fileno(inp), &o) == -1) { + LOGERR; + return -1; + } else { + o.c_lflag &= ~ECHO; + if (tcsetattr(fileno(inp), TCSANOW, &o) == -1) { + LOGERR; + return -1; + } + } +#endif while (!ok) { switch ((ret = ioPromptRead(h, (!csPrompt || !*csPrompt) ? "Password:" : csPrompt, @@ -215,194 +235,26 @@ ioPromptPassword(int *h, const char *csPrompt, char * } next: +#ifndef __linux__ tty_state.sg_flags |= ECHO; if (ioctl(fileno(inp), TIOCSETP, &tty_state) == -1) { LOGERR; return -1; } - - return ok; -} - -/* - * ioRegexVerify() Function for verify data match in regex expression - * @csRegex = Regulare expression pattern - * @csData = Data for check and verify - * @startPos = Return start positions - * @endPos = Return end positions - * return: NULL not match or error; !=NULL begin of matched data -*/ -const char * -ioRegexVerify(const char *csRegex, const char *csData, int *startPos, int *endPos) -{ - regex_t re; - regmatch_t match; - char szErr[STRSIZ]; - int ret, flg; - const char *pos; - - if (!csRegex || !csData) - return NULL; - - if ((ret = regcomp(&re, csRegex, REG_EXTENDED))) { - regerror(ret, &re, szErr, STRSIZ); - io_SetErr(ret, "Error:: %s\n", szErr); - regfree(&re); - return NULL; - } - - for (ret = flg = 0, pos = csData; !(ret = regexec(&re, pos, 1, &match, flg)); - pos += match.rm_eo, flg = REG_NOTBOL) { - if (startPos) - *startPos = match.rm_so; - if (endPos) - *endPos = match.rm_eo; - - pos += match.rm_so; - break; - } - - if (ret) { - regerror(ret, &re, szErr, STRSIZ); - io_SetErr(ret, "Error:: %s\n", szErr); - pos = NULL; - } - - regfree(&re); - return pos; -} - -/* - * ioRegexGet() Function for get data match in regex expression - * @csRegex = Regulare expression pattern - * @csData = Data from get - * @psString = Returned string if match - * @strLen = Length of string - * return: 0 not match; >0 count of returned chars -*/ -int -ioRegexGet(const char *csRegex, const char *csData, char * __restrict psString, int strLen) -{ - int sp, ep, len; - const char *str; - - if (!csRegex || !csData) +#else + o.c_lflag |= ECHO; + if (tcsetattr(fileno(inp), TCSANOW, &o) == -1) { + LOGERR; return -1; - - str = ioRegexVerify(csRegex, csData, &sp, &ep); - if (!str) - return 0; - - len = ep - sp; - if (psString && strLen) { - memset(psString, 0, strLen); - strncpy(psString, str, strLen <= len ? strLen - 1 : len); } +#endif - return len; + return ok; } /* - * ioRegexReplace() Function for replace data match in regex expression with newdata - * @csRegex = Regulare expression pattern - * @csData = Source data - * @csNew = Data for replace - * return: NULL not match or error; !=NULL allocated new string, must be free after use! -*/ -char * -ioRegexReplace(const char *csRegex, const char *csData, const char *csNew) -{ - int sp, ep, len; - char *str = NULL; - - if (!csRegex || !csData) - return NULL; - - if (!ioRegexVerify(csRegex, csData, &sp, &ep)) - return NULL; - - // ___ before match - len = sp + 1; - str = malloc(len); - if (!str) { - LOGERR; - return NULL; - } else - strlcpy(str, csData, len); - // * replace match * - if (csNew) { - len += strlen(csNew); - str = realloc(str, len); - if (!str) { - LOGERR; - return NULL; - } else - strlcat(str, csNew, len); - } - // after match ___ - len += strlen(csData) - ep; - str = realloc(str, len); - if (!str) { - LOGERR; - return NULL; - } else - strlcat(str, csData + ep, len); - - return str; -} - -/* - * ioStrAst() Function for evaluate string like asterisk variable "{text[:[-]#[:#]]}" - * @csString = Input string - * return: NULL error, !=NULL Allocated new string evaluated from input string, must be free() -*/ -char * -ioStrAst(const char *csString) -{ - char *ext, *str, *out = NULL; - int e[2] = { 0 }; - - if (!csString) - return NULL; - - if (!strchr(csString, '{') || !strrchr(csString, '}')) { - memset(io_Error, 0, STRSIZ); - snprintf(io_Error, STRSIZ, "Error:: Invalid input string format ... " - "must be like {text[:[-]#[:#]]}"); - io_Errno = EINVAL; - return NULL; - } else { - str = strdup(strchr(csString, '{') + 1); - *strrchr(str, '}') = 0; - } - - if ((ext = strchr(str, ':'))) { - *ext++ = 0; - e[0] = strtol(ext, NULL, 0); - if ((ext = strchr(ext, ':'))) - e[1] = strtol(++ext, NULL, 0); - - /* make cut prefix */ - if (e[0] >= 0) - ext = str + e[0]; - else - ext = str + strlen(str) + e[0]; - /* make cut suffix */ - if (e[1] > 0) - *(ext + e[1]) = 0; - } else - /* ok, clear show */ - ext = str; - - out = strdup(ext); - free(str); - - return out; -} - - -/* - * ioMkDir() Function for racursive directory creation and validation + * ioMkDir() - Function for racursive directory creation and validation + * * @csDir = Full directory path * @mode = Mode for directory creation if missing dir * return: -1 error, 0 directory path exist, >0 created missing dirs @@ -416,7 +268,7 @@ ioMkDir(const char *csDir, int mode) if (!csDir) return cx; - str = strdup(csDir); + str = e_strdup(csDir); if (!str) { LOGERR; return cx; @@ -444,12 +296,13 @@ ioMkDir(const char *csDir, int mode) } end: chdir(szOld); - free(str); + e_free(str); 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 * @callback = Callback if raise event! nOp -1 delete, 0 change/move, 1 create * return: -1 error, !=-1 ok, number of total signaled events @@ -458,9 +311,12 @@ int ioWatchDirLoop(const char *csDir, int (*callback)(const char *csName, int nOp)) { glob_t g[2] = {{ 0 }, { 0 }}; - int d, kq, n = 0; + int d, n = 0; register int j, i; +#ifndef __linux__ + int kq; struct kevent req, chg; +#endif char wrk[MAXPATHLEN * 2], str[MAXPATHLEN] = { 0 }; if (!csDir || !callback) @@ -469,28 +325,34 @@ ioWatchDirLoop(const char *csDir, int (*callback)(cons strlcpy(str, csDir, MAXPATHLEN); strlcat(str, "/*", MAXPATHLEN); - kq = kqueue(); - if (kq == -1) { + d = open(csDir, O_RDONLY); + if (d == -1) { LOGERR; return -1; } - d = open(csDir, O_RDONLY); - if (d == -1) { + +#ifndef __linux__ + kq = kqueue(); + if (kq == -1) { LOGERR; - close(kq); + close(d); return -1; } EV_SET(&req, d, EVFILT_VNODE, EV_ADD | EV_CLEAR, NOTE_WRITE, 0, 0); +#endif if ((n = glob(str, GLOB_NOCHECK, NULL, &g[0]))) { LOGERR; close(d); +#ifndef __linux__ close(kq); +#endif return -1; } /*else ioDEBUG(3, "Start files %d in %s\n", g[0].gl_matchc, str);*/ +#ifndef __linux__ while (kevent(kq, &req, 1, &chg, 1, NULL) > 0) { /*ioDEBUG(1, "Event:: req=0x%x -> chg=0x%x data=%x\n", req.fflags, chg.fflags, chg.data);*/ @@ -552,20 +414,24 @@ ioWatchDirLoop(const char *csDir, int (*callback)(cons g[0] = g[1]; } } +#endif globfree(&g[0]); - close(d); +#ifndef __linux__ close(kq); +#endif + close(d); return n; } /* - * ioCreatePIDFile() Create PID file + * ioCreatePIDFile() - Create PID file + * * @csName = PID filename * @ifExists = !=0 if filename exists return error * return: -1 error or 0 ok */ -inline int +int ioCreatePIDFile(const char *csName, int ifExists) { int fd; @@ -587,7 +453,8 @@ ioCreatePIDFile(const char *csName, int ifExists) /* - * ioSendFile() AITNET sendfile() userland implementation, not dependant from OS + * ioSendFile() - AITNET sendfile() userland implementation, not dependant from OS + * * @s = socket * @csFile = file for send * @sendLen = bytes to send, if 0 send all data @@ -653,7 +520,8 @@ ioSendFile(int s, const char *csFile, size_t sendLen, } /* - * ioRecvFile() Receive file from socket, fastest (zero-copy) way + * ioRecvFile() - Receive file from socket, fastest (zero-copy) way + * * @s = socket * @csFile = file for receive * @recvLen = receive bytes @@ -687,18 +555,12 @@ ioRecvFile(int s, const char *csFile, size_t recvLen, unlink(csFile); return 0; } - if (lseek(fd, recvLen - 1, SEEK_SET) == -1) { + if (ftruncate(fd, recvLen) == -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; @@ -725,4 +587,37 @@ ioRecvFile(int s, const char *csFile, size_t recvLen, munmap(addr, recvLen); return len; +} + +/* + * ioRealFileName() - Get real file name + * + * @fname = filename + * return: =NULL error or !=NULL real filename, should be free with e_free() + */ +char * +ioRealFileName(const char *fname) +{ + char *str = NULL; + struct stat sb; + + if (!fname) + return NULL; + + str = e_malloc(MAXPATHLEN); + if (!str) { + io_SetErr(elwix_GetErrno(), "%s", elwix_GetError()); + return NULL; + } else + memset(str, 0, MAXPATHLEN); + if (readlink(fname, str, MAXPATHLEN) == -1) { + if (stat(fname, &sb) == -1) { + LOGERR; + e_free(str); + return NULL; + } else + strlcpy(str, fname, MAXPATHLEN); + } + + return str; }