Changeset 2331 for zzuf/trunk/src


Ignore:
Timestamp:
May 18, 2008, 1:10:47 AM (12 years ago)
Author:
Sam Hocevar
Message:
  • Implement fgets_unlocked() and fread_unlocked().
File:
1 edited

Legend:

Unmodified
Added
Removed
  • zzuf/trunk/src/lib-stream.c

    r2330 r2331  
    5858static size_t  (*ORIG(fread))    (void *ptr, size_t size, size_t nmemb,
    5959                                  FILE *stream);
     60#if defined HAVE_FREAD_UNLOCKED
     61static size_t  (*ORIG(fread_unlocked))  (void *ptr, size_t size, size_t nmemb,
     62                                         FILE *stream);
     63#endif
    6064static int     (*ORIG(getc))     (FILE *stream);
    6165static int     (*ORIG(fgetc))    (FILE *stream);
     
    7074#endif
    7175static char *  (*ORIG(fgets))    (char *s, int size, FILE *stream);
     76#if defined HAVE_FGETS_UNLOCKED
     77static char *  (*ORIG(fgets_unlocked)) (char *s, int size, FILE *stream);
     78#endif
    7279static int     (*ORIG(ungetc))   (int c, FILE *stream);
    7380static int     (*ORIG(fclose))   (FILE *fp);
     
    228235}
    229236
     237#if defined HAVE___SREFILL /* Don't fuzz or seek if we have __srefill() */
     238#   define FREAD_FUZZ() \
     239    do \
     240    { \
     241        debug("%s(%p, %li, %li, [%i]) = %li", __func__, ptr, \
     242              (long int)size, (long int)nmemb, fd, (long int)ret); \
     243    } while(0)
     244#else
     245#   define FREAD_FUZZ() \
     246    do \
     247    { \
     248        int64_t newpos = ftell(stream); \
     249        /* XXX: the number of bytes read is not ret * size, because \
     250         * a partial read may have advanced the stream pointer. However, \
     251         * when reading from a pipe ftell() will return 0, and ret * size \
     252         * is then better than nothing. */ \
     253        if(newpos <= 0) \
     254        { \
     255            pos = _zz_getpos(fd); \
     256            newpos = pos + ret * size; \
     257        } \
     258        if(newpos != pos) \
     259        { \
     260            char *b = ptr; \
     261            _zz_fuzz(fd, ptr, newpos - pos); \
     262            _zz_setpos(fd, newpos); \
     263            if(newpos >= pos + 4) \
     264                debug("%s(%p, %li, %li, [%i]) = %li \"%c%c%c%c...", __func__, \
     265                      ptr, (long int)size, (long int)nmemb, fd, \
     266                      (long int)ret, b[0], b[1], b[2], b[3]); \
     267            else \
     268                debug("%s(%p, %li, %li, [%i]) = %li \"%c...", __func__, ptr, \
     269                      (long int)size, (long int)nmemb, fd, \
     270                      (long int)ret, b[0]); \
     271        } \
     272        else \
     273            debug("%s(%p, %li, %li, [%i]) = %li", __func__, ptr, \
     274                  (long int)size, (long int)nmemb, fd, (long int)ret); \
     275    } while(0)
     276#endif
     277
     278#define FREAD(fn) \
     279    do \
     280    { \
     281        int64_t pos; \
     282        int fd; \
     283        LOADSYM(fn); \
     284        fd = fileno(stream); \
     285        if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
     286            return ORIG(fn)(ptr, size, nmemb, stream); \
     287        pos = ftell(stream); \
     288        _zz_lock(fd); \
     289        ret = ORIG(fn)(ptr, size, nmemb, stream); \
     290        _zz_unlock(fd); \
     291        FREAD_FUZZ(); \
     292    } while(0)
     293
    230294size_t NEW(fread)(void *ptr, size_t size, size_t nmemb, FILE *stream)
    231295{
    232     int64_t pos;
    233 #if defined HAVE___SREFILL /* Don't fuzz or seek if we have __srefill() */
    234 #else
    235     int64_t newpos;
    236 #endif
    237     size_t ret;
    238     int fd;
    239 
    240     LOADSYM(fread);
    241     fd = fileno(stream);
    242     if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd))
    243         return ORIG(fread)(ptr, size, nmemb, stream);
    244 
    245     pos = ftell(stream);
    246     _zz_lock(fd);
    247     ret = ORIG(fread)(ptr, size, nmemb, stream);
    248     _zz_unlock(fd);
    249 
    250 #if defined HAVE___SREFILL /* Don't fuzz or seek if we have __srefill() */
    251 #else
    252     newpos = ftell(stream);
    253     /* XXX: the number of bytes read is not ret * size, because
    254      * a partial read may have advanced the stream pointer. However,
    255      * when reading from a pipe ftell() will return 0, and ret * size
    256      * is then better than nothing. */
    257     if(newpos <= 0)
    258     {
    259         pos = _zz_getpos(fd);
    260         newpos = pos + ret * size;
    261     }
    262     if(newpos != pos)
    263     {
    264         char *b = ptr;
    265 
    266         _zz_fuzz(fd, ptr, newpos - pos);
    267         _zz_setpos(fd, newpos);
    268 
    269         if(newpos >= pos + 4)
    270             debug("%s(%p, %li, %li, [%i]) = %li \"%c%c%c%c...", __func__, ptr,
    271                   (long int)size, (long int)nmemb, fd, (long int)ret,
    272                   b[0], b[1], b[2], b[3]);
    273         else
    274             debug("%s(%p, %li, %li, [%i]) = %li \"%c...", __func__, ptr,
    275                   (long int)size, (long int)nmemb, fd, (long int)ret, b[0]);
    276     }
    277     else
    278 #endif
    279         debug("%s(%p, %li, %li, [%i]) = %li", __func__, ptr,
    280               (long int)size, (long int)nmemb, fd, (long int)ret);
    281 
    282     return ret;
    283 }
     296    size_t ret; FREAD(fread); return ret;
     297}
     298
     299#if defined HAVE_FREAD_UNLOCKED
     300#undef fread_unlocked /* can be a macro; we don’t want that */
     301size_t NEW(fread_unlocked)(void *ptr, size_t size, size_t nmemb, FILE *stream)
     302{
     303    size_t ret; FREAD(fread_unlocked); return ret;
     304}
     305#endif
    284306
    285307#if defined HAVE___SREFILL /* Don't fuzz or seek if we have __srefill() */
     
    332354
    333355#if defined HAVE_GETC_UNLOCKED
     356#undef getc_unlocked /* can be a macro; we don’t want that */
    334357int NEW(getc_unlocked)(FILE *stream)
    335358{
     
    339362
    340363#if defined HAVE_FGETC_UNLOCKED
     364#undef fgetc_unlocked /* can be a macro; we don’t want that */
    341365int NEW(fgetc_unlocked)(FILE *stream)
    342366{
     
    345369#endif
    346370
     371#if defined HAVE___SREFILL /* Don't fuzz or seek if we have __srefill() */
     372#   define FGETS_FUZZ \
     373        _zz_lock(fd); \
     374        ret = ORIG(fgets)(s, size, stream); \
     375        _zz_unlock(fd);
     376#else
     377#   define FGETS_FUZZ \
     378        if(size <= 0) \
     379            ret = NULL; \
     380        else if(size == 1) \
     381            s[0] = '\0'; \
     382        else \
     383        { \
     384            int i; \
     385            for(i = 0; i < size - 1; i++) \
     386            { \
     387                int ch; \
     388                _zz_lock(fd); \
     389                ch = ORIG(fgetc)(stream); \
     390                _zz_unlock(fd); \
     391                if(ch == EOF) \
     392                { \
     393                    s[i] = '\0'; \
     394                    if(!i) \
     395                        ret = NULL; \
     396                    break; \
     397                } \
     398                s[i] = (char)(unsigned char)ch; \
     399                _zz_fuzz(fd, (uint8_t *)s + i, 1); /* rather inefficient */ \
     400                _zz_addpos(fd, 1); \
     401                if(s[i] == '\n') \
     402                { \
     403                    s[i + 1] = '\0'; \
     404                    break; \
     405                } \
     406            } \
     407        }
     408#endif
     409
     410#define FGETS(fn) \
     411    do \
     412    { \
     413        int fd; \
     414        ret = s; \
     415        LOADSYM(fn); \
     416        LOADSYM(fgetc); \
     417        fd = fileno(stream); \
     418        if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
     419            return ORIG(fn)(s, size, stream); \
     420        FGETS_FUZZ \
     421        debug("%s(%p, %i, [%i]) = %p", __func__, s, size, fd, ret); \
     422    } while(0)
     423
    347424char *NEW(fgets)(char *s, int size, FILE *stream)
    348425{
    349     char *ret = s;
    350     int fd;
    351 
    352     LOADSYM(fgets);
    353     LOADSYM(fgetc);
    354     fd = fileno(stream);
    355     if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd))
    356         return ORIG(fgets)(s, size, stream);
    357 
    358 #if defined HAVE___SREFILL /* Don't fuzz or seek if we have __srefill() */
    359     _zz_lock(fd);
    360     ret = ORIG(fgets)(s, size, stream);
    361     _zz_unlock(fd);
    362 #else
    363     if(size <= 0)
    364         ret = NULL;
    365     else if(size == 1)
    366         s[0] = '\0';
    367     else
    368     {
    369         int i;
    370 
    371         for(i = 0; i < size - 1; i++)
    372         {
    373             int ch;
    374 
    375             _zz_lock(fd);
    376             ch = ORIG(fgetc)(stream);
    377             _zz_unlock(fd);
    378 
    379             if(ch == EOF)
    380             {
    381                 s[i] = '\0';
    382                 if(!i)
    383                     ret = NULL;
    384                 break;
    385             }
    386             s[i] = (char)(unsigned char)ch;
    387             _zz_fuzz(fd, (uint8_t *)s + i, 1); /* rather inefficient */
    388             _zz_addpos(fd, 1);
    389             if(s[i] == '\n')
    390             {
    391                 s[i + 1] = '\0';
    392                 break;
    393             }
    394         }
    395     }
    396 #endif
    397 
    398     debug("%s(%p, %i, [%i]) = %p", __func__, s, size, fd, ret);
    399     return ret;
    400 }
     426    char *ret; FGETS(fgets); return ret;
     427}
     428
     429#if defined HAVE_FGETS_UNLOCKED
     430char *NEW(fgets_unlocked)(char *s, int size, FILE *stream)
     431{
     432    char *ret; FGETS(fgets_unlocked); return ret;
     433}
     434#endif
    401435
    402436int NEW(ungetc)(int c, FILE *stream)
Note: See TracChangeset for help on using the changeset viewer.