* Added getc(), fgetc(), fgets(), ungetc(), getline() and getdelim().
* sed now works properly.
This commit is contained in:
+196
-22
@@ -18,8 +18,7 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
/* Can't remember what that's for */
|
||||
#define _GNU_SOURCE
|
||||
#define _GNU_SOURCE /* for getline() and getdelim() */
|
||||
|
||||
#if defined HAVE_STDINT_H
|
||||
# include <stdint.h>
|
||||
@@ -43,15 +42,34 @@ static FILE * (*fopen64_orig) (const char *path, const char *mode);
|
||||
static int (*fseek_orig) (FILE *stream, long offset, int whence);
|
||||
static size_t (*fread_orig) (void *ptr, size_t size, size_t nmemb,
|
||||
FILE *stream);
|
||||
static int (*getc_orig) (FILE *stream);
|
||||
static int (*fgetc_orig) (FILE *stream);
|
||||
static char * (*fgets_orig) (char *s, int size, FILE *stream);
|
||||
static int (*ungetc_orig) (int c, FILE *stream);
|
||||
static int (*fclose_orig) (FILE *fp);
|
||||
|
||||
/* Additional GNUisms */
|
||||
static ssize_t (*getline_orig) (char **lineptr, size_t *n, FILE *stream);
|
||||
static ssize_t (*getdelim_orig) (char **lineptr, size_t *n, int delim,
|
||||
FILE *stream);
|
||||
static ssize_t (*__getdelim_orig) (char **lineptr, size_t *n, int delim,
|
||||
FILE *stream);
|
||||
|
||||
void zzuf_load_stream(void)
|
||||
{
|
||||
LOADSYM(fopen);
|
||||
LOADSYM(fopen64);
|
||||
LOADSYM(fseek);
|
||||
LOADSYM(fread);
|
||||
LOADSYM(getc);
|
||||
LOADSYM(fgetc);
|
||||
LOADSYM(fgets);
|
||||
LOADSYM(ungetc);
|
||||
LOADSYM(fclose);
|
||||
|
||||
LOADSYM(getline);
|
||||
LOADSYM(getdelim);
|
||||
LOADSYM(__getdelim);
|
||||
}
|
||||
|
||||
/* Our function wrappers */
|
||||
@@ -59,10 +77,11 @@ void zzuf_load_stream(void)
|
||||
do \
|
||||
{ \
|
||||
if(!_zzuf_ready) \
|
||||
{ \
|
||||
LOADSYM(fn); \
|
||||
return ORIG(fn)(path, mode); \
|
||||
} \
|
||||
ret = ORIG(fn)(path, mode); \
|
||||
if(!_zzuf_ready) \
|
||||
return ret; \
|
||||
if(ret) \
|
||||
{ \
|
||||
if(_zzuf_include && \
|
||||
@@ -97,14 +116,11 @@ int fseek(FILE *stream, long offset, int whence)
|
||||
|
||||
if(!_zzuf_ready)
|
||||
LOADSYM(fseek);
|
||||
ret = fseek_orig(stream, offset, whence);
|
||||
if(!_zzuf_ready)
|
||||
return ret;
|
||||
|
||||
fd = fileno(stream);
|
||||
if(!files[fd].managed)
|
||||
return ret;
|
||||
if(!_zzuf_ready || !files[fd].managed)
|
||||
return fseek_orig(stream, offset, whence);
|
||||
|
||||
ret = fseek_orig(stream, offset, whence);
|
||||
debug("fseek(%p, %li, %i) = %i", stream, offset, whence, ret);
|
||||
if(ret == 0)
|
||||
{
|
||||
@@ -125,14 +141,11 @@ size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
|
||||
|
||||
if(!_zzuf_ready)
|
||||
LOADSYM(fread);
|
||||
ret = fread_orig(ptr, size, nmemb, stream);
|
||||
if(!_zzuf_ready)
|
||||
return ret;
|
||||
|
||||
fd = fileno(stream);
|
||||
if(!files[fd].managed)
|
||||
return ret;
|
||||
if(!_zzuf_ready || !files[fd].managed)
|
||||
return fread_orig(ptr, size, nmemb, stream);
|
||||
|
||||
ret = fread_orig(ptr, size, nmemb, stream);
|
||||
debug("fread(%p, %li, %li, %p) = %li",
|
||||
ptr, (long int)size, (long int)nmemb, stream, (long int)ret);
|
||||
if(ret > 0)
|
||||
@@ -143,6 +156,102 @@ size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define FGETC(fn) \
|
||||
do { \
|
||||
int fd; \
|
||||
if(!_zzuf_ready) \
|
||||
LOADSYM(fn); \
|
||||
fd = fileno(stream); \
|
||||
if(!_zzuf_ready || !files[fd].managed) \
|
||||
return ORIG(fn)(stream); \
|
||||
ret = ORIG(fn)(stream); \
|
||||
if(ret != EOF) \
|
||||
{ \
|
||||
uint8_t ch = ret; \
|
||||
zzuf_fuzz(fd, &ch, 1); \
|
||||
files[fd].pos += 1; \
|
||||
ret = ch; \
|
||||
} \
|
||||
debug(STR(fn)"(%p) = 0x%02x", stream, ret); \
|
||||
} while(0)
|
||||
|
||||
int getc(FILE *stream)
|
||||
{
|
||||
int ret; FGETC(getc); return ret;
|
||||
}
|
||||
|
||||
int fgetc(FILE *stream)
|
||||
{
|
||||
int ret; FGETC(fgetc); return ret;
|
||||
}
|
||||
|
||||
char *fgets(char *s, int size, FILE *stream)
|
||||
{
|
||||
char *ret = s;
|
||||
int i, fd;
|
||||
|
||||
if(!_zzuf_ready)
|
||||
LOADSYM(fgets);
|
||||
fd = fileno(stream);
|
||||
if(!_zzuf_ready || !files[fd].managed)
|
||||
return fgets_orig(s, size, stream);
|
||||
|
||||
if(size <= 0)
|
||||
ret = NULL;
|
||||
else if(size == 1)
|
||||
s[0] = '\0';
|
||||
else
|
||||
{
|
||||
for(i = 0; i < size - 1; i++)
|
||||
{
|
||||
int ch = fgetc_orig(stream);
|
||||
|
||||
if(ch == EOF)
|
||||
{
|
||||
s[i] = '\0';
|
||||
if(!i)
|
||||
ret = NULL;
|
||||
break;
|
||||
}
|
||||
s[i] = (char)(unsigned char)ch;
|
||||
zzuf_fuzz(fd, (uint8_t *)s + i, 1); /* rather inefficient */
|
||||
files[fd].pos++;
|
||||
if(s[i] == '\n')
|
||||
{
|
||||
s[i + 1] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
debug("fgets(%p, %i, %p) = %p", s, size, stream, ret);
|
||||
if(ret >= 0)
|
||||
files[fd].pos += 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ungetc(int c, FILE *stream)
|
||||
{
|
||||
unsigned char ch = c;
|
||||
int ret, fd;
|
||||
|
||||
if(!_zzuf_ready)
|
||||
LOADSYM(ungetc);
|
||||
fd = fileno(stream);
|
||||
if(!_zzuf_ready || !files[fd].managed)
|
||||
return ungetc_orig(c, stream);
|
||||
|
||||
files[fd].pos -= 1;
|
||||
zzuf_fuzz(fd, &ch, 1);
|
||||
ret = ungetc_orig((int)ch, stream);
|
||||
if(ret >= 0)
|
||||
ret = c;
|
||||
else
|
||||
files[fd].pos += 1; /* revert what we did */
|
||||
debug("ungetc(0x%02x, %p) = 0x%02x", c, stream, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int fclose(FILE *fp)
|
||||
{
|
||||
int ret, fd;
|
||||
@@ -150,16 +259,81 @@ int fclose(FILE *fp)
|
||||
if(!_zzuf_ready)
|
||||
LOADSYM(fclose);
|
||||
fd = fileno(fp);
|
||||
if(!_zzuf_ready || !files[fd].managed)
|
||||
return fclose_orig(fp);
|
||||
|
||||
ret = fclose_orig(fp);
|
||||
if(!_zzuf_ready)
|
||||
return ret;
|
||||
|
||||
if(!files[fd].managed)
|
||||
return ret;
|
||||
|
||||
debug("fclose(%p) = %i", fp, ret);
|
||||
files[fd].managed = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define GETDELIM(fn, delim, need_delim) \
|
||||
do { \
|
||||
char *line; \
|
||||
ssize_t done, size; \
|
||||
int fd, finished = 0; \
|
||||
if(!_zzuf_ready) \
|
||||
LOADSYM(fn); \
|
||||
fd = fileno(stream); \
|
||||
if(!_zzuf_ready || !files[fd].managed) \
|
||||
return getdelim_orig(lineptr, n, delim, stream); \
|
||||
line = *lineptr; \
|
||||
size = line ? *n : 0; \
|
||||
ret = done = finished = 0; \
|
||||
for(;;) \
|
||||
{ \
|
||||
int ch; \
|
||||
if(done >= size) /* highly inefficient but I don't care */ \
|
||||
line = realloc(line, size = done + 1); \
|
||||
if(finished) \
|
||||
{ \
|
||||
line[done] = '\0'; \
|
||||
*n = size; \
|
||||
*lineptr = line; \
|
||||
break; \
|
||||
} \
|
||||
ch = fgetc_orig(stream); \
|
||||
if(ch == EOF) \
|
||||
{ \
|
||||
finished = 1; \
|
||||
ret = done; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
unsigned char c = ch; \
|
||||
zzuf_fuzz(fd, &c, 1); /* even more inefficient */ \
|
||||
line[done++] = c; \
|
||||
files[fd].pos++; \
|
||||
if(c == delim) \
|
||||
{ \
|
||||
finished = 1; \
|
||||
ret = done; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
if(need_delim) \
|
||||
debug(STR(fn) "(%p, %p, 0x%02x, %p) = %li", \
|
||||
lineptr, n, delim, stream, (long int)ret); \
|
||||
else \
|
||||
debug(STR(fn) "(%p, %p, %p) = %li", \
|
||||
lineptr, n, stream, (long int)ret); \
|
||||
return ret; \
|
||||
} while(0)
|
||||
|
||||
ssize_t getline(char **lineptr, size_t *n, FILE *stream)
|
||||
{
|
||||
ssize_t ret; GETDELIM(getline, '\n', 0); return ret;
|
||||
}
|
||||
|
||||
ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream)
|
||||
{
|
||||
ssize_t ret; GETDELIM(getdelim, delim, 1); return ret;
|
||||
}
|
||||
|
||||
ssize_t __getdelim(char **lineptr, size_t *n, int delim, FILE *stream)
|
||||
{
|
||||
ssize_t ret; GETDELIM(__getdelim, delim, 1); return ret;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user