source: zzuf/trunk/src/libzzuf/lib-fd.c @ 4809

Last change on this file since 4809 was 4809, checked in by Sam Hocevar, 8 years ago

Fix a weird problem with lib6 versioned symbols.

  • Property svn:keywords set to Id
File size: 19.7 KB
Line 
1/*
2 *  zzuf - general purpose fuzzer
3 *  Copyright (c) 2006-2010 Sam Hocevar <sam@hocevar.net>
4 *                2007 Rémi Denis-Courmont <rdenis#simphalempin:com>
5 *                2007 Clément Stenac <zorglub#diwi:org>
6 *                2007 Dominik Kuhlen <dominik.kuhlen#gmit-gmbh:de>
7 *                2009 Corentin Delorme <codelorme@gmail.com>
8 *                All Rights Reserved
9 *
10 *  This program is free software. It comes without any warranty, to
11 *  the extent permitted by applicable law. You can redistribute it
12 *  and/or modify it under the terms of the Do What The Fuck You Want
13 *  To Public License, Version 2, as published by Sam Hocevar. See
14 *  http://sam.zoy.org/wtfpl/COPYING for more details.
15 */
16
17/*
18 *  load-fd.c: loaded file descriptor functions
19 */
20
21#include "config.h"
22
23/* Use this to get lseek64() on glibc systems */
24#define _LARGEFILE64_SOURCE
25/* Use this to get off64_t() on Solaris systems */
26#define _LARGEFILE_SOURCE
27/* Use this to get proper prototypes on HP-UX systems */
28#define _XOPEN_SOURCE_EXTENDED
29#define _INCLUDE_POSIX_SOURCE
30
31#if defined HAVE_STDINT_H
32#   include <stdint.h>
33#elif defined HAVE_INTTYPES_H
34#   include <inttypes.h>
35#endif
36#include <stdlib.h>
37#include <string.h>
38#include <stdio.h>
39#include <errno.h>
40
41#if defined HAVE_WINSOCK2_H
42#   include <winsock2.h>
43#endif
44#include <sys/types.h>
45#if defined HAVE_SYS_SOCKET_H
46#   include <sys/socket.h>
47#endif
48#if defined HAVE_NETINET_IN_H
49#   include <netinet/in.h>
50#endif
51#if defined HAVE_ARPA_INET_H
52#   include <arpa/inet.h>
53#endif
54#if defined HAVE_SYS_UIO_H
55#   include <sys/uio.h>
56#endif
57#if defined HAVE_UNISTD_H
58#   include <unistd.h>
59#endif
60#include <fcntl.h>
61#include <stdarg.h>
62#if defined HAVE_AIO_H
63#   include <aio.h>
64#endif
65
66#include "libzzuf.h"
67#include "lib-load.h"
68#include "debug.h"
69#include "network.h"
70#include "fuzz.h"
71#include "fd.h"
72
73#if defined HAVE_SOCKLEN_T
74#   define SOCKLEN_T socklen_t
75#else
76#   define SOCKLEN_T int
77#endif
78
79#if defined CONNECT_USES_STRUCT_SOCKADDR
80#   define SOCKADDR_T struct sockaddr
81#else
82#   define SOCKADDR_T void
83#endif
84
85/* Local prototypes */
86#if defined HAVE_READV || defined HAVE_RECVMSG
87static void fuzz_iovec   (int fd, const struct iovec *iov, ssize_t ret);
88#endif
89static void offset_check (int fd);
90
91/* Library functions that we divert */
92static int     (*ORIG(open))    (const char *file, int oflag, ...);
93#if defined HAVE_OPEN64
94static int     (*ORIG(open64))  (const char *file, int oflag, ...);
95#endif
96#if defined HAVE___OPEN64
97static int     (*ORIG(__open64))(const char *file, int oflag, ...);
98#endif
99#if defined HAVE_DUP
100static int     (*ORIG(dup))     (int oldfd);
101#endif
102#if defined HAVE_DUP2
103static int     (*ORIG(dup2))    (int oldfd, int newfd);
104#endif
105#if defined HAVE_ACCEPT
106static int     (*ORIG(accept))  (int sockfd, SOCKADDR_T *addr,
107                                 SOCKLEN_T *addrlen);
108#endif
109#if defined HAVE_BIND
110static int     (*ORIG(bind))    (int sockfd, const SOCKADDR_T *my_addr,
111                                 SOCKLEN_T addrlen);
112#endif
113#if defined HAVE_CONNECT
114static int     (*ORIG(connect)) (int sockfd, const SOCKADDR_T *serv_addr,
115                                 SOCKLEN_T addrlen);
116#endif
117#if defined HAVE_SOCKET
118static int     (*ORIG(socket))  (int domain, int type, int protocol);
119#endif
120#if defined HAVE_RECV
121static RECV_T  (*ORIG(recv))    (int s, void *buf, size_t len, int flags);
122#endif
123#if defined HAVE___RECV_CHK
124static RECV_T  (*ORIG(__recv_chk)) (int s, void *buf, size_t len,
125                                    size_t buflen, int flags);
126#endif
127#if defined HAVE_RECVFROM
128static RECV_T  (*ORIG(recvfrom))(int s, void *buf, size_t len, int flags,
129                                 SOCKADDR_T *from, SOCKLEN_T *fromlen);
130#endif
131#if defined HAVE___RECVFROM_CHK
132static RECV_T  (*ORIG(__recvfrom_chk))(int s, void *buf, size_t len,
133                                       size_t buflen, int flags,
134                                       SOCKADDR_T *from, SOCKLEN_T *fromlen);
135#endif
136#if defined HAVE_RECVMSG
137static RECV_T  (*ORIG(recvmsg)) (int s,  struct msghdr *hdr, int flags);
138#endif
139#if defined READ_USES_SSIZE_T
140static ssize_t (*ORIG(read))    (int fd, void *buf, size_t count);
141#else
142static int     (*ORIG(read))    (int fd, void *buf, unsigned int count);
143#endif
144#if defined HAVE___READ_CHK
145static ssize_t (*ORIG(__read_chk)) (int fd, void *buf, size_t count,
146                                    size_t buflen);
147#endif
148#if defined HAVE_READV
149static ssize_t (*ORIG(readv))   (int fd, const struct iovec *iov, int count);
150#endif
151#if defined HAVE_PREAD
152static ssize_t (*ORIG(pread))   (int fd, void *buf, size_t count, off_t offset);
153#endif
154#if defined HAVE_AIO_READ
155static int     (*ORIG(aio_read))   (struct aiocb *aiocbp);
156static ssize_t (*ORIG(aio_return)) (struct aiocb *aiocbp);
157#endif
158static off_t   (*ORIG(lseek))   (int fd, off_t offset, int whence);
159#if defined HAVE_LSEEK64
160static off64_t (*ORIG(lseek64)) (int fd, off64_t offset, int whence);
161#endif
162#if defined HAVE___LSEEK64
163static off64_t (*ORIG(__lseek64)) (int fd, off64_t offset, int whence);
164#endif
165static int     (*ORIG(close))   (int fd);
166
167#define ZZ_OPEN(myopen) \
168    do \
169    { \
170        int mode = 0; \
171        LOADSYM(myopen); \
172        if(oflag & O_CREAT) \
173        { \
174            va_list va; \
175            va_start(va, oflag); \
176            mode = va_arg(va, int); \
177            va_end(va); \
178            ret = ORIG(myopen)(file, oflag, mode); \
179        } \
180        else \
181        { \
182            ret = ORIG(myopen)(file, oflag); \
183        } \
184        if(!_zz_ready || _zz_islocked(-1)) \
185            return ret; \
186        if(ret >= 0 \
187            && ((oflag & (O_RDONLY | O_RDWR | O_WRONLY)) != O_WRONLY) \
188            && _zz_mustwatch(file)) \
189        { \
190            if(oflag & O_CREAT) \
191                debug("%s(\"%s\", %i, %i) = %i", \
192                      __func__, file, oflag, mode, ret); \
193            else \
194                debug("%s(\"%s\", %i) = %i", __func__, file, oflag, ret); \
195            _zz_register(ret); \
196        } \
197    } while(0)
198
199#undef open
200int NEW(open)(const char *file, int oflag, ...)
201{
202    int ret; ZZ_OPEN(open); return ret;
203}
204
205#if defined HAVE_OPEN64
206#undef open64
207int NEW(open64)(const char *file, int oflag, ...)
208{
209    int ret; ZZ_OPEN(open64); return ret;
210}
211#endif
212
213#if defined HAVE___OPEN64
214#undef __open64
215int NEW(__open64)(const char *file, int oflag, ...)
216{
217    int ret; ZZ_OPEN(__open64); return ret;
218}
219#endif
220
221#if defined HAVE_DUP
222#undef dup
223int NEW(dup)(int oldfd)
224{
225    int ret;
226
227    LOADSYM(dup);
228    ret = ORIG(dup)(oldfd);
229    if(!_zz_ready || _zz_islocked(-1) || !_zz_iswatched(oldfd)
230         || !_zz_isactive(oldfd))
231        return ret;
232
233    if(ret >= 0)
234    {
235        debug("%s(%i) = %i", __func__, oldfd, ret);
236        _zz_register(ret);
237    }
238
239    return ret;
240}
241#endif
242
243#if defined HAVE_DUP2
244#undef dup2
245int NEW(dup2)(int oldfd, int newfd)
246{
247    int ret;
248
249    LOADSYM(dup2);
250    ret = ORIG(dup2)(oldfd, newfd);
251    if(!_zz_ready || _zz_islocked(-1) || !_zz_iswatched(oldfd)
252         || !_zz_isactive(oldfd))
253        return ret;
254
255    if(ret >= 0)
256    {
257        /* We must close newfd if it was open, but only if oldfd != newfd
258         * and if dup2() suceeded. */
259        if(oldfd != newfd && _zz_iswatched(newfd) && _zz_isactive(newfd))
260            _zz_unregister(newfd);
261
262        debug("%s(%i, %i) = %i", __func__, oldfd, newfd, ret);
263        _zz_register(ret);
264    }
265
266    return ret;
267}
268#endif
269
270#if defined HAVE_ACCEPT
271#undef accept
272int NEW(accept)(int sockfd, SOCKADDR_T *addr, SOCKLEN_T *addrlen)
273{
274    int ret;
275
276    LOADSYM(accept);
277    ret = ORIG(accept)(sockfd, addr, addrlen);
278    if(!_zz_ready || _zz_islocked(-1) || !_zz_network
279         || !_zz_iswatched(sockfd) || !_zz_isactive(sockfd))
280        return ret;
281
282    if(ret >= 0)
283    {
284        if(addrlen)
285            debug("%s(%i, %p, &%i) = %i", __func__,
286                  sockfd, addr, (int)*addrlen, ret);
287        else
288            debug("%s(%i, %p, NULL) = %i", __func__, sockfd, addr, ret);
289        _zz_register(ret);
290    }
291
292    return ret;
293}
294#endif
295
296#if defined AF_INET6
297#   define case_AF_INET6 case AF_INET6:
298#else
299#   define case_AF_INET6
300#endif
301
302#define ZZ_CONNECT(myconnect, addr) \
303    do \
304    { \
305        LOADSYM(myconnect); \
306        ret = ORIG(myconnect)(sockfd, addr, addrlen); \
307        if(!_zz_ready || _zz_islocked(-1) || !_zz_network) \
308            return ret; \
309        if(ret >= 0) \
310        { \
311            struct sockaddr_in in; \
312            long int port; \
313            switch(addr->sa_family) \
314            { \
315            case AF_INET: \
316            case_AF_INET6 \
317                /* We need to copy rather than cast sockaddr* to sockaddr_in* \
318                 * because sockaddr_in* has actually _larger_ alignment on \
319                 * eg. Linux alpha. And we only need sin_port so we only copy \
320                 * this member. */ \
321                memcpy(&in.sin_port, \
322                   (char const *)addr + ((char *)&in.sin_port - (char *)&in), \
323                   sizeof(in.sin_port)); \
324                port = ntohs(in.sin_port); \
325                if(_zz_portwatched(port)) \
326                    break; \
327                /* Fall through */ \
328            default: \
329                _zz_unregister(sockfd); \
330                return ret; \
331            } \
332            debug("%s(%i, %p, %i) = %i", __func__, \
333                  sockfd, addr, (int)addrlen, ret); \
334        } \
335    } while(0);
336
337#if defined HAVE_BIND
338#undef bind
339int NEW(bind)(int sockfd, const SOCKADDR_T *my_addr, SOCKLEN_T addrlen)
340{
341    int ret; ZZ_CONNECT(bind, my_addr); return ret;
342}
343#endif
344
345#if defined HAVE_CONNECT
346#undef connect
347int NEW(connect)(int sockfd, const SOCKADDR_T *serv_addr,
348                 SOCKLEN_T addrlen)
349{
350    int ret; ZZ_CONNECT(connect, serv_addr); return ret;
351}
352#endif
353
354#if defined HAVE_SOCKET
355#undef socket
356int NEW(socket)(int domain, int type, int protocol)
357{
358    int ret;
359
360    LOADSYM(socket);
361    ret = ORIG(socket)(domain, type, protocol);
362    if(!_zz_ready || _zz_islocked(-1) || !_zz_network)
363        return ret;
364
365    if(ret >= 0)
366    {
367        debug("%s(%i, %i, %i) = %i", __func__, domain, type, protocol, ret);
368        _zz_register(ret);
369    }
370
371    return ret;
372}
373#endif
374
375#define ZZ_RECV(myrecv, myargs) \
376    do \
377    { \
378        LOADSYM(myrecv); \
379        ret = ORIG(myrecv) myargs; \
380        if(!_zz_ready || !_zz_iswatched(s) || !_zz_hostwatched(s) \
381             || _zz_islocked(s) || !_zz_isactive(s)) \
382            return ret; \
383        if(ret > 0) \
384        { \
385            char *b = buf; \
386            _zz_fuzz(s, buf, ret); \
387            _zz_addpos(s, ret); \
388            if(ret >= 4) \
389                debug("%s(%i, %p, %li, 0x%x) = %i \"%c%c%c%c...", __func__, \
390                      s, buf, (long int)len, flags, ret, \
391                      b[0], b[1], b[2], b[3]); \
392            else \
393                debug("%s(%i, %p, %li, 0x%x) = %i \"%c...", __func__, \
394                      s, buf, (long int)len, flags, ret, b[0]); \
395        } \
396        else \
397            debug("%s(%i, %p, %li, 0x%x) = %i", __func__, \
398                  s, buf, (long int)len, flags, ret); \
399    } while(0);
400
401#if defined HAVE_RECV
402#undef recv
403RECV_T NEW(recv)(int s, void *buf, size_t len, int flags)
404{
405    int ret; ZZ_RECV(recv, (s, buf, len, flags)); return ret;
406}
407#endif
408
409#if defined HAVE___RECV_CHK
410#undef __recv_chk
411RECV_T NEW(__recv_chk)(int s, void *buf, size_t len, size_t buflen, int flags)
412{
413    int ret; ZZ_RECV(__recv_chk, (s, buf, len, buflen, flags)); return ret;
414}
415#endif
416
417#define ZZ_RECVFROM(myrecvfrom, myargs) \
418    do \
419    { \
420        LOADSYM(myrecvfrom); \
421        ret = ORIG(myrecvfrom) myargs; \
422        if(!_zz_ready || !_zz_iswatched(s) || !_zz_hostwatched(s) \
423             || _zz_islocked(s) || !_zz_isactive(s)) \
424            return ret; \
425        if(ret > 0) \
426        { \
427            char tmp[128]; \
428            char *b = buf; \
429            _zz_fuzz(s, buf, ret); \
430            _zz_addpos(s, ret); \
431            if (fromlen) \
432                sprintf(tmp, "&%i", (int)*fromlen); \
433            else \
434                strcpy(tmp, "NULL"); \
435            if (ret >= 4) \
436                debug("%s(%i, %p, %li, 0x%x, %p, %s) = %i \"%c%c%c%c...", \
437                      __func__, s, buf, (long int)len, flags, from, tmp, \
438                      ret, b[0], b[1], b[2], b[3]); \
439            else \
440                debug("%s(%i, %p, %li, 0x%x, %p, %s) = %i \"%c...", \
441                      __func__, s, buf, (long int)len, flags, from, tmp, \
442                      ret, b[0]); \
443        } \
444        else \
445            debug("%s(%i, %p, %li, 0x%x, %p, %p) = %i", __func__, \
446                  s, buf, (long int)len, flags, from, fromlen, ret); \
447    } while(0)
448
449#if defined HAVE_RECVFROM
450#undef recvfrom
451RECV_T NEW(recvfrom)(int s, void *buf, size_t len, int flags,
452                     SOCKADDR_T *from, SOCKLEN_T *fromlen)
453{
454    int ret;
455    ZZ_RECVFROM(recvfrom, (s, buf, len, flags, from, fromlen));
456    return ret;
457}
458#endif
459
460#if defined HAVE___RECVFROM_CHK
461#undef __recvfrom_chk
462RECV_T NEW(__recvfrom_chk)(int s, void *buf, size_t len, size_t buflen,
463                           int flags, SOCKADDR_T *from, SOCKLEN_T *fromlen)
464{
465    int ret;
466    ZZ_RECVFROM(__recvfrom_chk, (s, buf, len, buflen, flags, from, fromlen));
467    return ret;
468}
469#endif
470
471#if defined HAVE_RECVMSG
472#undef recvmsg
473RECV_T NEW(recvmsg)(int s, struct msghdr *hdr, int flags)
474{
475    ssize_t ret;
476
477    LOADSYM(recvmsg);
478    ret = ORIG(recvmsg)(s, hdr, flags);
479    if(!_zz_ready || !_zz_iswatched(s) || !_zz_hostwatched(s)
480         || _zz_islocked(s) || !_zz_isactive(s))
481        return ret;
482
483    fuzz_iovec(s, hdr->msg_iov, ret);
484    debug("%s(%i, %p, %x) = %li", __func__, s, hdr, flags, (long int)ret);
485
486    return ret;
487}
488#endif
489
490#define ZZ_READ(myread, myargs) \
491    do \
492    { \
493        LOADSYM(myread); \
494        ret = ORIG(myread) myargs; \
495        if(!_zz_ready || !_zz_iswatched(fd) || !_zz_hostwatched(fd) \
496             || _zz_islocked(fd) || !_zz_isactive(fd)) \
497            return ret; \
498        if(ret > 0) \
499        { \
500            char *b = buf; \
501            _zz_fuzz(fd, buf, ret); \
502            _zz_addpos(fd, ret); \
503            if(ret >= 4) \
504                debug("%s(%i, %p, %li) = %i \"%c%c%c%c...", __func__, fd, \
505                      buf, (long int)count, ret, b[0], b[1], b[2], b[3]); \
506            else \
507                debug("%s(%i, %p, %li) = %i \"%c...", __func__, fd, \
508                      buf, (long int)count, ret, b[0]); \
509        } \
510        else \
511            debug("%s(%i, %p, %li) = %i", __func__, fd, \
512                  buf, (long int)count, ret); \
513        offset_check(fd); \
514    } while(0)
515
516#if defined READ_USES_SSIZE_T
517#undef read
518ssize_t NEW(read)(int fd, void *buf, size_t count)
519{
520    int ret; ZZ_READ(read, (fd, buf, count)); return (ssize_t)ret;
521}
522#else
523#undef read
524int NEW(read)(int fd, void *buf, unsigned int count)
525{
526    int ret; ZZ_READ(read, (fd, buf, count)); return ret;
527}
528#endif
529
530#if defined HAVE___READ_CHK
531#undef __read_chk
532ssize_t NEW(__read_chk)(int fd, void *buf, size_t count, size_t buflen)
533{
534    int ret; ZZ_READ(__read_chk, (fd, buf, count, buflen)); return (ssize_t)ret;
535}
536#endif
537
538#if defined HAVE_READV
539#undef readv
540ssize_t NEW(readv)(int fd, const struct iovec *iov, int count)
541{
542    ssize_t ret;
543
544    LOADSYM(readv);
545    ret = ORIG(readv)(fd, iov, count);
546    if(!_zz_ready || !_zz_iswatched(fd) || _zz_islocked(fd)
547         || !_zz_isactive(fd))
548        return ret;
549
550    fuzz_iovec(fd, iov, ret);
551    debug("%s(%i, %p, %i) = %li", __func__, fd, iov, count, (long int)ret);
552
553    offset_check(fd);
554    return ret;
555}
556#endif
557
558#if defined HAVE_PREAD
559#undef pread
560ssize_t NEW(pread)(int fd, void *buf, size_t count, off_t offset)
561{
562    int ret;
563
564    LOADSYM(pread);
565    ret = ORIG(pread)(fd, buf, count, offset);
566    if(!_zz_ready || !_zz_iswatched(fd) || _zz_islocked(fd)
567         || !_zz_isactive(fd))
568        return ret;
569
570    if(ret > 0)
571    {
572        long int curoff = _zz_getpos(fd);
573        char *b = buf;
574
575        _zz_setpos(fd, offset);
576        _zz_fuzz(fd, buf, ret);
577        _zz_setpos(fd, curoff);
578
579        if(ret >= 4)
580            debug("%s(%i, %p, %li, %li) = %i \"%c%c%c%c...", __func__, fd, buf,
581                  (long int)count, (long int)offset, ret,
582                  b[0], b[1], b[2], b[3]);
583        else
584            debug("%s(%i, %p, %li, %li) = %i \"%c...", __func__, fd, buf,
585                  (long int)count, (long int)offset, ret, b[0]);
586    }
587    else
588        debug("%s(%i, %p, %li, %li) = %i", __func__, fd, buf,
589              (long int)count, (long int)offset, ret);
590
591    return ret;
592}
593#endif
594
595#define ZZ_LSEEK(mylseek, off_t) \
596    do \
597    { \
598        LOADSYM(mylseek); \
599        ret = ORIG(mylseek)(fd, offset, whence); \
600        if(!_zz_ready || !_zz_iswatched(fd) || _zz_islocked(fd) \
601             || !_zz_isactive(fd)) \
602            return ret; \
603        debug("%s(%i, %lli, %i) = %lli", __func__, fd, \
604              (long long int)offset, whence, (long long int)ret); \
605        if(ret != (off_t)-1) \
606            _zz_setpos(fd, ret); \
607    } while(0)
608
609#undef lseek
610off_t NEW(lseek)(int fd, off_t offset, int whence)
611{
612    off_t ret;
613    ZZ_LSEEK(lseek, off_t);
614    return ret;
615}
616
617#if defined HAVE_LSEEK64
618#undef lseek64
619off64_t NEW(lseek64)(int fd, off64_t offset, int whence)
620{
621    off64_t ret; ZZ_LSEEK(lseek64, off64_t); return ret;
622}
623#endif
624
625#if defined HAVE___LSEEK64
626#undef __lseek64
627off64_t NEW(__lseek64)(int fd, off64_t offset, int whence)
628{
629    off64_t ret; ZZ_LSEEK(__lseek64, off64_t); return ret;
630}
631#endif
632
633#if defined HAVE_AIO_READ
634#undef aio_read
635int NEW(aio_read)(struct aiocb *aiocbp)
636{
637    int ret;
638    int fd = aiocbp->aio_fildes;
639
640    LOADSYM(aio_read);
641    if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd))
642        return ORIG(aio_read)(aiocbp);
643
644    _zz_lock(fd);
645    ret = ORIG(aio_read)(aiocbp);
646
647    debug("%s({%i, %i, %i, %p, %li, ..., %li}) = %i", __func__,
648          fd, aiocbp->aio_lio_opcode, aiocbp->aio_reqprio, aiocbp->aio_buf,
649          (long int)aiocbp->aio_nbytes, (long int)aiocbp->aio_offset, ret);
650
651    return ret;
652}
653
654#undef aio_return
655ssize_t NEW(aio_return)(struct aiocb *aiocbp)
656{
657    ssize_t ret;
658    int fd = aiocbp->aio_fildes;
659
660    LOADSYM(aio_return);
661    if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd))
662        return ORIG(aio_return)(aiocbp);
663
664    ret = ORIG(aio_return)(aiocbp);
665    _zz_unlock(fd);
666
667    /* FIXME: make sure we’re actually *reading* */
668    if(ret > 0)
669    {
670        _zz_setpos(fd, aiocbp->aio_offset);
671        _zz_fuzz(fd, aiocbp->aio_buf, ret);
672        _zz_addpos(fd, ret);
673    }
674
675    debug("%s({%i, %i, %i, %p, %li, ..., %li}) = %li", __func__,
676          fd, aiocbp->aio_lio_opcode, aiocbp->aio_reqprio, aiocbp->aio_buf,
677          (long int)aiocbp->aio_nbytes, (long int)aiocbp->aio_offset,
678          (long int)ret);
679
680    return ret;
681}
682#endif
683
684#undef close
685int NEW(close)(int fd)
686{
687    int ret;
688
689    /* Hey, it’s our debug channel! Silently pretend we closed it. */
690    if(fd == _zz_debugfd)
691        return 0;
692
693    LOADSYM(close);
694    ret = ORIG(close)(fd);
695    if(!_zz_ready || !_zz_iswatched(fd) || _zz_islocked(fd))
696        return ret;
697
698    debug("%s(%i) = %i", __func__, fd, ret);
699    _zz_unregister(fd);
700
701    return ret;
702}
703
704/* XXX: the following functions are local */
705
706#if defined HAVE_READV || defined HAVE_RECVMSG
707static void fuzz_iovec(int fd, const struct iovec *iov, ssize_t ret)
708{
709    /* NOTE: We assume that iov countains at least <ret> bytes. */
710    while(ret > 0)
711    {
712        void *b = iov->iov_base;
713        size_t len = iov->iov_len;
714
715        if(len > (size_t)ret)
716            len = ret;
717
718        _zz_fuzz(fd, b, len);
719        _zz_addpos(fd, len);
720
721        iov++;
722        ret -= len;
723    }
724}
725#endif
726
727/* Sanity check, can be OK though (for instance with a character device) */
728static void offset_check(int fd)
729{
730    int orig_errno = errno;
731#if defined HAVE_LSEEK64
732    off64_t ret;
733    LOADSYM(lseek64);
734    ret = ORIG(lseek64)(fd, 0, SEEK_CUR);
735#else
736    off_t ret;
737    LOADSYM(lseek);
738    ret = ORIG(lseek)(fd, 0, SEEK_CUR);
739#endif
740    if(ret != -1 && ret != _zz_getpos(fd))
741        debug("warning: offset inconsistency");
742    errno = orig_errno;
743}
744
Note: See TracBrowser for help on using the repository browser.