"Fossies" - the Fresh Open Source Software Archive

Member "s-nail-14.9.11/fio.c" (8 Aug 2018, 8978 Bytes) of package /linux/misc/s-nail-14.9.11.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "fio.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 14.9.10_vs_14.9.11.

    1 /*@ S-nail - a mail user agent derived from Berkeley Mail.
    2  *@ File operations.
    3  *
    4  * Copyright (c) 2000-2004 Gunnar Ritter, Freiburg i. Br., Germany.
    5  * Copyright (c) 2012 - 2018 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>.
    6  * SPDX-License-Identifier: BSD-3-Clause
    7  */
    8 /*
    9  * Copyright (c) 1980, 1993
   10  *      The Regents of the University of California.  All rights reserved.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. Neither the name of the University nor the names of its contributors
   21  *    may be used to endorse or promote products derived from this software
   22  *    without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34  * SUCH DAMAGE.
   35  */
   36 #undef n_FILE
   37 #define n_FILE fio
   38 
   39 #ifndef HAVE_AMALGAMATION
   40 # include "nail.h"
   41 #endif
   42 
   43 /* line is a buffer with the result of fgets(). Returns the first newline or
   44  * the last character read */
   45 static size_t     _length_of_line(char const *line, size_t linesize);
   46 
   47 /* Read a line, one character at a time */
   48 static char *     _fgetline_byone(char **line, size_t *linesize, size_t *llen,
   49                      FILE *fp, int appendnl, size_t n n_MEMORY_DEBUG_ARGS);
   50 
   51 /* Workhorse */
   52 static bool_t a_file_lock(int fd, enum n_file_lock_type ft, off_t off,
   53                off_t len);
   54 
   55 static size_t
   56 _length_of_line(char const *line, size_t linesize)
   57 {
   58    size_t i;
   59    NYD2_ENTER;
   60 
   61    /* Last character is always '\0' and was added by fgets() */
   62    for (--linesize, i = 0; i < linesize; i++)
   63       if (line[i] == '\n')
   64          break;
   65    i = (i < linesize) ? i + 1 : linesize;
   66    NYD2_LEAVE;
   67    return i;
   68 }
   69 
   70 static char *
   71 _fgetline_byone(char **line, size_t *linesize, size_t *llen, FILE *fp,
   72    int appendnl, size_t n n_MEMORY_DEBUG_ARGS)
   73 {
   74    char *rv;
   75    int c;
   76    NYD2_ENTER;
   77 
   78    assert(*linesize == 0 || *line != NULL);
   79    n_pstate &= ~n_PS_READLINE_NL;
   80 
   81    for (rv = *line;;) {
   82       if (*linesize <= LINESIZE || n >= *linesize - 128) {
   83          *linesize += ((rv == NULL) ? LINESIZE + n + 1 : 256);
   84          *line = rv = (n_realloc)(rv, *linesize n_MEMORY_DEBUG_ARGSCALL);
   85       }
   86       c = getc(fp);
   87       if (c != EOF) {
   88          rv[n++] = c;
   89          rv[n] = '\0';
   90          if (c == '\n') {
   91             n_pstate |= n_PS_READLINE_NL;
   92             break;
   93          }
   94       } else {
   95          if (n > 0) {
   96             if (appendnl) {
   97                rv[n++] = '\n';
   98                rv[n] = '\0';
   99             }
  100             break;
  101          } else {
  102             rv = NULL;
  103             goto jleave;
  104          }
  105       }
  106    }
  107    if (llen)
  108       *llen = n;
  109 jleave:
  110    NYD2_LEAVE;
  111    return rv;
  112 }
  113 
  114 static bool_t
  115 a_file_lock(int fd, enum n_file_lock_type flt, off_t off, off_t len)
  116 {
  117    struct flock flp;
  118    bool_t rv;
  119    NYD2_ENTER;
  120 
  121    memset(&flp, 0, sizeof flp);
  122 
  123    switch (flt) {
  124    default:
  125    case FLT_READ:    rv = F_RDLCK;  break;
  126    case FLT_WRITE:   rv = F_WRLCK;  break;
  127    }
  128    flp.l_type = rv;
  129    flp.l_start = off;
  130    flp.l_whence = SEEK_SET;
  131    flp.l_len = len;
  132 
  133    if (!(rv = (fcntl(fd, F_SETLK, &flp) != -1)))
  134       switch (n_err_no) {
  135       case n_ERR_BADF:
  136       case n_ERR_INVAL:
  137          rv = TRUM1;
  138          break;
  139       }
  140    NYD2_LEAVE;
  141    return rv;
  142 }
  143 
  144 FL char *
  145 (fgetline)(char **line, size_t *linesize, size_t *cnt, size_t *llen, FILE *fp,
  146    int appendnl n_MEMORY_DEBUG_ARGS)
  147 {
  148    size_t i_llen, sz;
  149    char *rv;
  150    NYD2_ENTER;
  151 
  152    if (cnt == NULL) {
  153       /* Without count, we can't determine where the chars returned by fgets()
  154        * end if there's no newline.  We have to read one character by one */
  155       rv = _fgetline_byone(line, linesize, llen, fp, appendnl, 0
  156             n_MEMORY_DEBUG_ARGSCALL);
  157       goto jleave;
  158    }
  159 
  160    n_pstate &= ~n_PS_READLINE_NL;
  161 
  162    if ((rv = *line) == NULL || *linesize < LINESIZE)
  163       *line = rv = (n_realloc)(rv, *linesize = LINESIZE
  164             n_MEMORY_DEBUG_ARGSCALL);
  165    sz = (*linesize <= *cnt) ? *linesize : *cnt + 1;
  166    if (sz <= 1 || fgets(rv, sz, fp) == NULL) {
  167       /* Leave llen untouched; it is used to determine whether the last line
  168        * was \n-terminated in some callers */
  169       rv = NULL;
  170       goto jleave;
  171    }
  172 
  173    i_llen = _length_of_line(rv, sz);
  174    *cnt -= i_llen;
  175    while (rv[i_llen - 1] != '\n') {
  176       *line = rv = (n_realloc)(rv, *linesize += 256 n_MEMORY_DEBUG_ARGSCALL);
  177       sz = *linesize - i_llen;
  178       sz = (sz <= *cnt) ? sz : *cnt + 1;
  179       if (sz <= 1 || fgets(rv + i_llen, sz, fp) == NULL) {
  180          if (appendnl) {
  181             rv[i_llen++] = '\n';
  182             rv[i_llen] = '\0';
  183          }
  184          break;
  185       }
  186       sz = _length_of_line(rv + i_llen, sz);
  187       i_llen += sz;
  188       *cnt -= sz;
  189    }
  190    if (llen)
  191       *llen = i_llen;
  192 jleave:
  193    NYD2_LEAVE;
  194    return rv;
  195 }
  196 
  197 FL int
  198 (readline_restart)(FILE *ibuf, char **linebuf, size_t *linesize, size_t n
  199    n_MEMORY_DEBUG_ARGS)
  200 {
  201    /* TODO readline_restart(): always *appends* LF just to strip it again;
  202     * TODO should be configurable just as for fgetline(); ..or whatever..
  203     * TODO intwrap */
  204    int rv = -1;
  205    long sz;
  206    NYD2_ENTER;
  207 
  208    clearerr(ibuf);
  209 
  210    /* Interrupts will cause trouble if we are inside a stdio call. As this is
  211     * only relevant if input is from tty, bypass it by read(), then */
  212    if ((n_psonce & n_PSO_TTYIN) && fileno(ibuf) == 0) {
  213       assert(*linesize == 0 || *linebuf != NULL);
  214       n_pstate &= ~n_PS_READLINE_NL;
  215       for (;;) {
  216          if (*linesize <= LINESIZE || n >= *linesize - 128) {
  217             *linesize += ((*linebuf == NULL) ? LINESIZE + n + 1 : 256);
  218             *linebuf = (n_realloc)(*linebuf, *linesize n_MEMORY_DEBUG_ARGSCALL);
  219          }
  220 jagain:
  221          sz = read(0, *linebuf + n, *linesize - n - 1);
  222          if (sz > 0) {
  223             n += sz;
  224             (*linebuf)[n] = '\0';
  225             if ((*linebuf)[n - 1] == '\n') {
  226                n_pstate |= n_PS_READLINE_NL;
  227                break;
  228             }
  229          } else {
  230             if (sz < 0 && n_err_no == n_ERR_INTR)
  231                goto jagain;
  232             /* TODO eh.  what is this?  that now supposed to be a line?!? */
  233             if (n > 0) {
  234                if ((*linebuf)[n - 1] != '\n') {
  235                   (*linebuf)[n++] = '\n';
  236                   (*linebuf)[n] = '\0';
  237                } else
  238                   n_pstate |= n_PS_READLINE_NL;
  239                break;
  240             } else
  241                goto jleave;
  242          }
  243       }
  244    } else {
  245       /* Not reading from standard input or standard input not a terminal. We
  246        * read one char at a time as it is the only way to get lines with
  247        * embedded NUL characters in standard stdio */
  248       if (_fgetline_byone(linebuf, linesize, &n, ibuf, 1, n
  249             n_MEMORY_DEBUG_ARGSCALL) == NULL)
  250          goto jleave;
  251    }
  252    if (n > 0 && (*linebuf)[n - 1] == '\n')
  253       (*linebuf)[--n] = '\0';
  254    rv = (int)n;
  255 jleave:
  256    NYD2_LEAVE;
  257    return rv;
  258 }
  259 
  260 FL off_t
  261 fsize(FILE *iob)
  262 {
  263    struct stat sbuf;
  264    off_t rv;
  265    NYD_ENTER;
  266 
  267    rv = (fstat(fileno(iob), &sbuf) == -1) ? 0 : sbuf.st_size;
  268    NYD_LEAVE;
  269    return rv;
  270 }
  271 
  272 FL bool_t
  273 n_file_lock(int fd, enum n_file_lock_type flt, off_t off, off_t len,
  274    size_t pollmsecs)
  275 {
  276    size_t tries;
  277    bool_t didmsg, rv;
  278    NYD_ENTER;
  279 
  280    if(pollmsecs == UIZ_MAX)
  281       pollmsecs = FILE_LOCK_MILLIS;
  282 
  283    n_UNINIT(rv, 0);
  284    for (didmsg = FAL0, tries = 0; tries <= FILE_LOCK_TRIES; ++tries) {
  285       rv = a_file_lock(fd, flt, off, len);
  286 
  287       if (rv == TRUM1) {
  288          rv = FAL0;
  289          break;
  290       }
  291       if (rv || pollmsecs == 0)
  292          break;
  293       else {
  294          if(!didmsg){
  295             n_err(_("Failed to create a file lock, waiting %lu milliseconds "),
  296                pollmsecs);
  297             didmsg = TRU1;
  298          }else
  299             n_err(".");
  300          n_msleep(pollmsecs, FAL0);
  301       }
  302    }
  303    if(didmsg)
  304       n_err(" %s\n", (rv ? _("ok") : _("failure")));
  305    NYD_LEAVE;
  306    return rv;
  307 }
  308 
  309 /* s-it-mode */