-
+ C5DDDD9D52900BA3D847422F9DBA2799BE2954AD9CCA3B9AA6FB1654DD89EE00575C52D15BD65E98D3054D4646943372CA8AD591F610EA7761D21FE4C3AE6187
mpi/iobuf.c
(0 . 0)(1 . 2326)
2780 /* iobuf.c - file handling
2781 * Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2008,
2782 * 2009 Free Software Foundation, Inc.
2783 *
2784 * This file is part of GnuPG.
2785 *
2786 * GnuPG is free software; you can redistribute it and/or modify
2787 * it under the terms of the GNU General Public License as published by
2788 * the Free Software Foundation; either version 3 of the License, or
2789 * (at your option) any later version.
2790 *
2791 * GnuPG is distributed in the hope that it will be useful,
2792 * but WITHOUT ANY WARRANTY; without even the implied warranty of
2793 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2794 * GNU General Public License for more details.
2795 *
2796 * You should have received a copy of the GNU General Public License
2797 * along with this program; if not, see <http://www.gnu.org/licenses/>.
2798 */
2799
2800 #include <config.h>
2801 #include <stdio.h>
2802 #include <stdlib.h>
2803 #include <string.h>
2804 #include <errno.h>
2805 #include <ctype.h>
2806 #include <assert.h>
2807 #include <sys/types.h>
2808 #include <sys/stat.h>
2809 #include <fcntl.h>
2810 #include <unistd.h>
2811 #ifdef HAVE_DOSISH_SYSTEM
2812 #include <windows.h>
2813 #endif
2814 #ifdef __riscos__
2815 #include <kernel.h>
2816 #include <swis.h>
2817 #endif /* __riscos__ */
2818
2819 #include "memory.h"
2820 #include "util.h"
2821 #include "iobuf.h"
2822
2823 /* The size of the internal buffers.
2824 NOTE: If you change this value you MUST also adjust the regression
2825 test "armored_key_8192" in armor.test! */
2826 #define IOBUF_BUFFER_SIZE 8192
2827
2828
2829 #undef FILE_FILTER_USES_STDIO
2830
2831 #ifdef HAVE_DOSISH_SYSTEM
2832 #define USE_SETMODE 1
2833 #endif
2834
2835 #ifdef FILE_FILTER_USES_STDIO
2836 #define my_fileno(a) fileno ((a))
2837 #define my_fopen_ro(a,b) fopen ((a),(b))
2838 #define my_fopen(a,b) fopen ((a),(b))
2839 typedef FILE *FILEP_OR_FD;
2840 #define INVALID_FP NULL
2841 #define FILEP_OR_FD_FOR_STDIN (stdin)
2842 #define FILEP_OR_FD_FOR_STDOUT (stdout)
2843 typedef struct {
2844 FILE *fp; /* open file handle */
2845 int keep_open;
2846 int no_cache;
2847 int print_only_name; /* flags indicating that fname is not a real file*/
2848 char fname[1]; /* name of the file */
2849 } file_filter_ctx_t ;
2850 #else
2851 #define my_fileno(a) (a)
2852 #define my_fopen_ro(a,b) fd_cache_open ((a),(b))
2853 #define my_fopen(a,b) direct_open ((a),(b))
2854 #ifdef HAVE_DOSISH_SYSTEM
2855 typedef HANDLE FILEP_OR_FD;
2856 #define INVALID_FP ((HANDLE)-1)
2857 #define FILEP_OR_FD_FOR_STDIN (GetStdHandle (STD_INPUT_HANDLE))
2858 #define FILEP_OR_FD_FOR_STDOUT (GetStdHandle (STD_OUTPUT_HANDLE))
2859 #undef USE_SETMODE
2860 #else
2861 typedef int FILEP_OR_FD;
2862 #define INVALID_FP (-1)
2863 #define FILEP_OR_FD_FOR_STDIN (0)
2864 #define FILEP_OR_FD_FOR_STDOUT (1)
2865 #endif
2866 typedef struct {
2867 FILEP_OR_FD fp; /* open file handle */
2868 int keep_open;
2869 int no_cache;
2870 int eof_seen;
2871 int print_only_name; /* flags indicating that fname is not a real file*/
2872 char fname[1]; /* name of the file */
2873 } file_filter_ctx_t ;
2874
2875 struct close_cache_s {
2876 struct close_cache_s *next;
2877 FILEP_OR_FD fp;
2878 char fname[1];
2879 };
2880 typedef struct close_cache_s *CLOSE_CACHE;
2881 static CLOSE_CACHE close_cache;
2882 #endif
2883
2884 #ifdef _WIN32
2885 typedef struct {
2886 int sock;
2887 int keep_open;
2888 int no_cache;
2889 int eof_seen;
2890 int print_only_name; /* flags indicating that fname is not a real file*/
2891 char fname[1]; /* name of the file */
2892 } sock_filter_ctx_t ;
2893 #endif /*_WIN32*/
2894
2895 /* The first partial length header block must be of size 512
2896 * to make it easier (and efficienter) we use a min. block size of 512
2897 * for all chunks (but the last one) */
2898 #define OP_MIN_PARTIAL_CHUNK 512
2899 #define OP_MIN_PARTIAL_CHUNK_2POW 9
2900
2901 typedef struct {
2902 int use;
2903 size_t size;
2904 size_t count;
2905 int partial; /* 1 = partial header, 2 in last partial packet */
2906 char *buffer; /* used for partial header */
2907 size_t buflen; /* used size of buffer */
2908 int first_c; /* of partial header (which is > 0)*/
2909 int eof;
2910 } block_filter_ctx_t;
2911
2912 static int special_names_enabled;
2913
2914 static int underflow(IOBUF a);
2915 static int translate_file_handle ( int fd, int for_write );
2916
2917
2918
2919 #ifndef FILE_FILTER_USES_STDIO
2920
2921 /* This is a replacement for strcmp. Under W32 it does not
2922 distinguish between backslash and slash. */
2923 static int
2924 fd_cache_strcmp (const char *a, const char *b)
2925 {
2926 #ifdef HAVE_DOSISH_SYSTEM
2927 for (; *a && *b; a++, b++)
2928 {
2929 if (*a != *b && !((*a == '/' && *b == '\\')
2930 || (*a == '\\' && *b == '/')) )
2931 break;
2932 }
2933 return *(const unsigned char *)a - *(const unsigned char *)b;
2934 #else
2935 return strcmp (a, b);
2936 #endif
2937 }
2938
2939 /*
2940 * Invalidate (i.e. close) a cached iobuf or all iobufs if NULL is
2941 * used for FNAME.
2942 */
2943 static int
2944 fd_cache_invalidate (const char *fname)
2945 {
2946 CLOSE_CACHE cc;
2947 int err=0;
2948
2949 if (!fname) {
2950 if( DBG_IOBUF )
2951 log_debug ("fd_cache_invalidate (all)\n");
2952
2953 for (cc=close_cache; cc; cc = cc->next ) {
2954 if ( cc->fp != INVALID_FP ) {
2955 #ifdef HAVE_DOSISH_SYSTEM
2956 CloseHandle (cc->fp);
2957 #else
2958 close(cc->fp);
2959 #endif
2960 cc->fp = INVALID_FP;
2961 }
2962 }
2963 return err;
2964 }
2965
2966 if( DBG_IOBUF )
2967 log_debug ("fd_cache_invalidate (%s)\n", fname);
2968
2969 for (cc=close_cache; cc; cc = cc->next ) {
2970 if ( cc->fp != INVALID_FP && !fd_cache_strcmp (cc->fname, fname) ) {
2971 if( DBG_IOBUF )
2972 log_debug (" did (%s)\n", cc->fname);
2973 #ifdef HAVE_DOSISH_SYSTEM
2974 if(CloseHandle (cc->fp)==0)
2975 err=-1;
2976 #else
2977 err=close(cc->fp);
2978 #endif
2979 cc->fp = INVALID_FP;
2980 }
2981 }
2982
2983 return err;
2984 }
2985
2986 static int
2987 fd_cache_synchronize(const char *fname)
2988 {
2989 int err=0;
2990
2991 #ifndef HAVE_DOSISH_SYSTEM
2992 CLOSE_CACHE cc;
2993
2994 if( DBG_IOBUF )
2995 log_debug ("fd_cache_synchronize (%s)\n", fname);
2996
2997 for (cc=close_cache; cc; cc = cc->next )
2998 {
2999 if ( cc->fp != INVALID_FP && !fd_cache_strcmp (cc->fname, fname) )
3000 {
3001 if( DBG_IOBUF )
3002 log_debug (" did (%s)\n", cc->fname);
3003
3004 err=fsync(cc->fp);
3005 }
3006 }
3007 #endif
3008
3009 return err;
3010 }
3011
3012 static FILEP_OR_FD
3013 direct_open (const char *fname, const char *mode)
3014 {
3015 #ifdef HAVE_DOSISH_SYSTEM
3016 unsigned long da, cd, sm;
3017 HANDLE hfile;
3018
3019 /* Note, that we do not handle all mode combinations */
3020
3021 /* According to the ReactOS source it seems that open() of the
3022 * standard MSW32 crt does open the file in share mode which is
3023 * something new for MS applications ;-)
3024 */
3025 if ( strchr (mode, '+') ) {
3026 fd_cache_invalidate (fname);
3027 da = GENERIC_READ|GENERIC_WRITE;
3028 cd = OPEN_EXISTING;
3029 sm = FILE_SHARE_READ | FILE_SHARE_WRITE;
3030 }
3031 else if ( strchr (mode, 'w') ) {
3032 fd_cache_invalidate (fname);
3033 da = GENERIC_WRITE;
3034 cd = CREATE_ALWAYS;
3035 sm = FILE_SHARE_WRITE;
3036 }
3037 else {
3038 da = GENERIC_READ;
3039 cd = OPEN_EXISTING;
3040 sm = FILE_SHARE_READ;
3041 }
3042
3043 hfile = CreateFile (fname, da, sm, NULL, cd, FILE_ATTRIBUTE_NORMAL, NULL);
3044 return hfile;
3045 #else
3046 int oflag;
3047 int cflag = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
3048
3049 /* Note, that we do not handle all mode combinations */
3050 if ( strchr (mode, '+') ) {
3051 fd_cache_invalidate (fname);
3052 oflag = O_RDWR;
3053 }
3054 else if ( strchr (mode, 'w') ) {
3055 fd_cache_invalidate (fname);
3056 oflag = O_WRONLY | O_CREAT | O_TRUNC;
3057 }
3058 else {
3059 oflag = O_RDONLY;
3060 }
3061 #ifdef O_BINARY
3062 if (strchr (mode, 'b'))
3063 oflag |= O_BINARY;
3064 #endif
3065 #ifndef __riscos__
3066 return open (fname, oflag, cflag );
3067 #else
3068 {
3069 struct stat buf;
3070 int rc = stat( fname, &buf );
3071
3072 /* Don't allow iobufs on directories */
3073 if( !rc && S_ISDIR(buf.st_mode) && !S_ISREG(buf.st_mode) )
3074 return __set_errno( EISDIR );
3075 else
3076 return open( fname, oflag, cflag );
3077 }
3078 #endif
3079 #endif
3080 }
3081
3082
3083 /*
3084 * Instead of closing an FD we keep it open and cache it for later reuse
3085 * Note that this caching strategy only works if the process does not chdir.
3086 */
3087 static void
3088 fd_cache_close (const char *fname, FILEP_OR_FD fp)
3089 {
3090 CLOSE_CACHE cc;
3091
3092 assert (fp);
3093 if ( !fname || !*fname ) {
3094 #ifdef HAVE_DOSISH_SYSTEM
3095 CloseHandle (fp);
3096 #else
3097 close(fp);
3098 #endif
3099 if( DBG_IOBUF )
3100 log_debug ("fd_cache_close (%d) real\n", (int)fp);
3101 return;
3102 }
3103 /* try to reuse a slot */
3104 for (cc=close_cache; cc; cc = cc->next ) {
3105 if ( cc->fp == INVALID_FP && !fd_cache_strcmp (cc->fname, fname) ) {
3106 cc->fp = fp;
3107 if( DBG_IOBUF )
3108 log_debug ("fd_cache_close (%s) used existing slot\n", fname);
3109 return;
3110 }
3111 }
3112 /* add a new one */
3113 if( DBG_IOBUF )
3114 log_debug ("fd_cache_close (%s) new slot created\n", fname);
3115 cc = xmalloc_clear (sizeof *cc + strlen (fname));
3116 strcpy (cc->fname, fname);
3117 cc->fp = fp;
3118 cc->next = close_cache;
3119 close_cache = cc;
3120 }
3121
3122 /*
3123 * Do an direct_open on FNAME but first try to reuse one from the fd_cache
3124 */
3125 static FILEP_OR_FD
3126 fd_cache_open (const char *fname, const char *mode)
3127 {
3128 CLOSE_CACHE cc;
3129
3130 assert (fname);
3131 for (cc=close_cache; cc; cc = cc->next ) {
3132 if ( cc->fp != INVALID_FP && !fd_cache_strcmp (cc->fname, fname) ) {
3133 FILEP_OR_FD fp = cc->fp;
3134 cc->fp = INVALID_FP;
3135 if( DBG_IOBUF )
3136 log_debug ("fd_cache_open (%s) using cached fp\n", fname);
3137 #ifdef HAVE_DOSISH_SYSTEM
3138 if (SetFilePointer (fp, 0, NULL, FILE_BEGIN) == 0xffffffff ) {
3139 log_error ("rewind file failed on handle %p: %s\n",
3140 fp, w32_strerror (errno));
3141 fp = INVALID_FP;
3142 }
3143 #else
3144 if ( lseek (fp, 0, SEEK_SET) == (off_t)-1 ) {
3145 log_error("can't rewind fd %d: %s\n", fp, strerror(errno) );
3146 fp = INVALID_FP;
3147 }
3148 #endif
3149 return fp;
3150 }
3151 }
3152 if( DBG_IOBUF )
3153 log_debug ("fd_cache_open (%s) not cached\n", fname);
3154 return direct_open (fname, mode);
3155 }
3156
3157
3158 #endif /*FILE_FILTER_USES_STDIO*/
3159
3160
3161 /****************
3162 * Read data from a file into buf which has an allocated length of *LEN.
3163 * return the number of read bytes in *LEN. OPAQUE is the FILE * of
3164 * the stream. A is not used.
3165 * control may be:
3166 * IOBUFCTRL_INIT: called just before the function is linked into the
3167 * list of function. This can be used to prepare internal
3168 * data structures of the function.
3169 * IOBUFCTRL_FREE: called just before the function is removed from the
3170 * list of functions and can be used to release internal
3171 * data structures or close a file etc.
3172 * IOBUFCTRL_UNDERFLOW: called by iobuf_underflow to fill the buffer
3173 * with new stuff. *RET_LEN is the available size of the
3174 * buffer, and should be set to the number of bytes
3175 * which were put into the buffer. The function
3176 * returns 0 to indicate success, -1 on EOF and
3177 * G10ERR_xxxxx for other errors.
3178 *
3179 * IOBUFCTRL_FLUSH: called by iobuf_flush() to write out the collected stuff.
3180 * *RET_LAN is the number of bytes in BUF.
3181 *
3182 * IOBUFCTRL_CANCEL: send to all filters on behalf of iobuf_cancel. The
3183 * filter may take appropriate action on this message.
3184 */
3185 static int
3186 file_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
3187 {
3188 file_filter_ctx_t *a = opaque;
3189 FILEP_OR_FD f = a->fp;
3190 size_t size = *ret_len;
3191 size_t nbytes = 0;
3192 int rc = 0;
3193
3194 #ifdef FILE_FILTER_USES_STDIO
3195 if( control == IOBUFCTRL_UNDERFLOW ) {
3196 assert( size ); /* need a buffer */
3197 if ( feof(f)) { /* On terminals you could easiely read as many EOFs as you call */
3198 rc = -1; /* fread() or fgetc() repeatly. Every call will block until you press */
3199 *ret_len = 0; /* CTRL-D. So we catch this case before we call fread() again. */
3200 }
3201 else {
3202 clearerr( f );
3203 nbytes = fread( buf, 1, size, f );
3204 if( feof(f) && !nbytes ) {
3205 rc = -1; /* okay: we can return EOF now. */
3206 }
3207 else if( ferror(f) && errno != EPIPE ) {
3208 log_error("%s: read error: %s\n",
3209 a->fname, strerror(errno));
3210 rc = G10ERR_READ_FILE;
3211 }
3212 *ret_len = nbytes;
3213 }
3214 }
3215 else if( control == IOBUFCTRL_FLUSH ) {
3216 if( size ) {
3217 clearerr( f );
3218 nbytes = fwrite( buf, 1, size, f );
3219 if( ferror(f) ) {
3220 log_error("%s: write error: %s\n", a->fname, strerror(errno));
3221 rc = G10ERR_WRITE_FILE;
3222 }
3223 }
3224 *ret_len = nbytes;
3225 }
3226 else if( control == IOBUFCTRL_INIT ) {
3227 a->keep_open = a->no_cache = 0;
3228 }
3229 else if( control == IOBUFCTRL_DESC ) {
3230 *(char**)buf = "file_filter";
3231 }
3232 else if( control == IOBUFCTRL_FREE ) {
3233 if( f != stdin && f != stdout ) {
3234 if( DBG_IOBUF )
3235 log_debug("%s: close fd %d\n", a->fname, fileno(f) );
3236 if (!a->keep_open)
3237 fclose(f);
3238 }
3239 f = NULL;
3240 xfree(a); /* we can free our context now */
3241 }
3242 #else /* !stdio implementation */
3243
3244 if( control == IOBUFCTRL_UNDERFLOW ) {
3245 assert( size ); /* need a buffer */
3246 if ( a->eof_seen) {
3247 rc = -1;
3248 *ret_len = 0;
3249 }
3250 else {
3251 #ifdef HAVE_DOSISH_SYSTEM
3252 unsigned long nread;
3253
3254 nbytes = 0;
3255 if ( !ReadFile ( f, buf, size, &nread, NULL ) ) {
3256 if ((int)GetLastError () != ERROR_BROKEN_PIPE) {
3257 log_error ("%s: read error: %s\n", a->fname,
3258 w32_strerror (0));
3259 rc = G10ERR_READ_FILE;
3260 }
3261 }
3262 else if ( !nread ) {
3263 a->eof_seen = 1;
3264 rc = -1;
3265 }
3266 else {
3267 nbytes = nread;
3268 }
3269
3270 #else
3271
3272 int n;
3273
3274 nbytes = 0;
3275 do {
3276 n = read ( f, buf, size );
3277 } while (n == -1 && errno == EINTR );
3278 if ( n == -1 ) { /* error */
3279 if (errno != EPIPE) {
3280 log_error("%s: read error: %s\n",
3281 a->fname, strerror(errno));
3282 rc = G10ERR_READ_FILE;
3283 }
3284 }
3285 else if ( !n ) { /* eof */
3286 a->eof_seen = 1;
3287 rc = -1;
3288 }
3289 else {
3290 nbytes = n;
3291 }
3292 #endif
3293 *ret_len = nbytes;
3294 }
3295 }
3296 else if( control == IOBUFCTRL_FLUSH ) {
3297 if( size ) {
3298 #ifdef HAVE_DOSISH_SYSTEM
3299 byte *p = buf;
3300 unsigned long n;
3301
3302 nbytes = size;
3303 do {
3304 if (size && !WriteFile (f, p, nbytes, &n, NULL)) {
3305 log_error ("%s: write error: %s\n", a->fname,
3306 w32_strerror (0));
3307 rc = G10ERR_WRITE_FILE;
3308 break;
3309 }
3310 p += n;
3311 nbytes -= n;
3312 } while ( nbytes );
3313 nbytes = p - buf;
3314 #else
3315 byte *p = buf;
3316 int n;
3317
3318 nbytes = size;
3319 do {
3320 do {
3321 n = write ( f, p, nbytes );
3322 } while ( n == -1 && errno == EINTR );
3323 if ( n > 0 ) {
3324 p += n;
3325 nbytes -= n;
3326 }
3327 } while ( n != -1 && nbytes );
3328 if( n == -1 ) {
3329 log_error("%s: write error: %s\n", a->fname, strerror(errno));
3330 rc = G10ERR_WRITE_FILE;
3331 }
3332 nbytes = p - buf;
3333 #endif
3334 }
3335 *ret_len = nbytes;
3336 }
3337 else if ( control == IOBUFCTRL_INIT ) {
3338 a->eof_seen = 0;
3339 a->keep_open = 0;
3340 a->no_cache = 0;
3341 }
3342 else if ( control == IOBUFCTRL_DESC ) {
3343 *(char**)buf = "file_filter(fd)";
3344 }
3345 else if ( control == IOBUFCTRL_FREE ) {
3346 #ifdef HAVE_DOSISH_SYSTEM
3347 if ( f != FILEP_OR_FD_FOR_STDIN && f != FILEP_OR_FD_FOR_STDOUT ) {
3348 if( DBG_IOBUF )
3349 log_debug("%s: close handle %p\n", a->fname, f );
3350 if (!a->keep_open)
3351 fd_cache_close (a->no_cache?NULL:a->fname, f);
3352 }
3353 #else
3354 if ( (int)f != 0 && (int)f != 1 ) {
3355 if( DBG_IOBUF )
3356 log_debug("%s: close fd %d\n", a->fname, f );
3357 if (!a->keep_open)
3358 fd_cache_close (a->no_cache?NULL:a->fname, f);
3359 }
3360 f = INVALID_FP;
3361 #endif
3362 xfree (a); /* we can free our context now */
3363 }
3364 #endif /* !stdio implementation */
3365 return rc;
3366 }
3367
3368 #ifdef _WIN32
3369 /* Becuase sockets are an special object under Lose32 we have to
3370 * use a special filter */
3371 static int
3372 sock_filter (void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
3373 {
3374 sock_filter_ctx_t *a = opaque;
3375 size_t size = *ret_len;
3376 size_t nbytes = 0;
3377 int rc = 0;
3378
3379 if( control == IOBUFCTRL_UNDERFLOW ) {
3380 assert( size ); /* need a buffer */
3381 if ( a->eof_seen) {
3382 rc = -1;
3383 *ret_len = 0;
3384 }
3385 else {
3386 int nread;
3387
3388 nread = recv ( a->sock, buf, size, 0 );
3389 if ( nread == SOCKET_ERROR ) {
3390 int ec = (int)WSAGetLastError ();
3391 log_error("socket read error: ec=%d\n", ec);
3392 rc = G10ERR_READ_FILE;
3393 }
3394 else if ( !nread ) {
3395 a->eof_seen = 1;
3396 rc = -1;
3397 }
3398 else {
3399 nbytes = nread;
3400 }
3401 *ret_len = nbytes;
3402 }
3403 }
3404 else if( control == IOBUFCTRL_FLUSH ) {
3405 if( size ) {
3406 byte *p = buf;
3407 int n;
3408
3409 nbytes = size;
3410 do {
3411 n = send (a->sock, p, nbytes, 0);
3412 if ( n == SOCKET_ERROR ) {
3413 int ec = (int)WSAGetLastError ();
3414 log_error("socket write error: ec=%d\n", ec);
3415 rc = G10ERR_WRITE_FILE;
3416 break;
3417 }
3418 p += n;
3419 nbytes -= n;
3420 } while ( nbytes );
3421 nbytes = p - buf;
3422 }
3423 *ret_len = nbytes;
3424 }
3425 else if ( control == IOBUFCTRL_INIT ) {
3426 a->eof_seen = 0;
3427 a->keep_open = 0;
3428 a->no_cache = 0;
3429 }
3430 else if ( control == IOBUFCTRL_DESC ) {
3431 *(char**)buf = "sock_filter";
3432 }
3433 else if ( control == IOBUFCTRL_FREE ) {
3434 if (!a->keep_open)
3435 closesocket (a->sock);
3436 xfree (a); /* we can free our context now */
3437 }
3438 return rc;
3439 }
3440 #endif /*_WIN32*/
3441
3442 /****************
3443 * This is used to implement the block write mode.
3444 * Block reading is done on a byte by byte basis in readbyte(),
3445 * without a filter
3446 */
3447 static int
3448 block_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
3449 {
3450 block_filter_ctx_t *a = opaque;
3451 size_t size = *ret_len;
3452 int c, needed, rc = 0;
3453 char *p;
3454
3455 if( control == IOBUFCTRL_UNDERFLOW ) {
3456 size_t n=0;
3457
3458 p = buf;
3459 assert( size ); /* need a buffer */
3460 if( a->eof ) /* don't read any further */
3461 rc = -1;
3462 while( !rc && size ) {
3463 if( !a->size ) { /* get the length bytes */
3464 if( a->partial == 2 ) {
3465 a->eof = 1;
3466 if( !n )
3467 rc = -1;
3468 break;
3469 }
3470 else if( a->partial ) {
3471 /* These OpenPGP introduced huffman like encoded length
3472 * bytes are really a mess :-( */
3473 if( a->first_c ) {
3474 c = a->first_c;
3475 a->first_c = 0;
3476 }
3477 else if( (c = iobuf_get(chain)) == -1 ) {
3478 log_error("block_filter: 1st length byte missing\n");
3479 rc = G10ERR_READ_FILE;
3480 break;
3481 }
3482 if( c < 192 ) {
3483 a->size = c;
3484 a->partial = 2;
3485 if( !a->size ) {
3486 a->eof = 1;
3487 if( !n )
3488 rc = -1;
3489 break;
3490 }
3491 }
3492 else if( c < 224 ) {
3493 a->size = (c - 192) * 256;
3494 if( (c = iobuf_get(chain)) == -1 ) {
3495 log_error("block_filter: 2nd length byte missing\n");
3496 rc = G10ERR_READ_FILE;
3497 break;
3498 }
3499 a->size += c + 192;
3500 a->partial = 2;
3501 if( !a->size ) {
3502 a->eof = 1;
3503 if( !n )
3504 rc = -1;
3505 break;
3506 }
3507 }
3508 else if( c == 255 ) {
3509 a->size = iobuf_get(chain) << 24;
3510 a->size |= iobuf_get(chain) << 16;
3511 a->size |= iobuf_get(chain) << 8;
3512 if( (c = iobuf_get(chain)) == -1 ) {
3513 log_error("block_filter: invalid 4 byte length\n");
3514 rc = G10ERR_READ_FILE;
3515 break;
3516 }
3517 a->size |= c;
3518 a->partial = 2;
3519 if( !a->size ) {
3520 a->eof = 1;
3521 if( !n )
3522 rc = -1;
3523 break;
3524 }
3525 }
3526 else { /* next partial body length */
3527 a->size = 1 << (c & 0x1f);
3528 }
3529 /* log_debug("partial: ctx=%p c=%02x size=%u\n", a, c, a->size);*/
3530 }
3531 else
3532 BUG();
3533 }
3534
3535 while( !rc && size && a->size ) {
3536 needed = size < a->size ? size : a->size;
3537 c = iobuf_read( chain, p, needed );
3538 if( c < needed ) {
3539 if( c == -1 ) c = 0;
3540 log_error("block_filter %p: read error (size=%lu,a->size=%lu)\n",
3541 a, (ulong)size+c, (ulong)a->size+c);
3542 rc = G10ERR_READ_FILE;
3543 }
3544 else {
3545 size -= c;
3546 a->size -= c;
3547 p += c;
3548 n += c;
3549 }
3550 }
3551 }
3552 *ret_len = n;
3553 }
3554 else if( control == IOBUFCTRL_FLUSH ) {
3555 if( a->partial ) { /* the complicated openpgp scheme */
3556 size_t blen, n, nbytes = size + a->buflen;
3557
3558 assert( a->buflen <= OP_MIN_PARTIAL_CHUNK );
3559 if( nbytes < OP_MIN_PARTIAL_CHUNK ) {
3560 /* not enough to write a partial block out; so we store it*/
3561 if( !a->buffer )
3562 a->buffer = xmalloc( OP_MIN_PARTIAL_CHUNK );
3563 memcpy( a->buffer + a->buflen, buf, size );
3564 a->buflen += size;
3565 }
3566 else { /* okay, we can write out something */
3567 /* do this in a loop to use the most efficient block lengths */
3568 p = buf;
3569 do {
3570 /* find the best matching block length - this is limited
3571 * by the size of the internal buffering */
3572 for( blen=OP_MIN_PARTIAL_CHUNK*2,
3573 c=OP_MIN_PARTIAL_CHUNK_2POW+1; blen <= nbytes;
3574 blen *=2, c++ )
3575 ;
3576 blen /= 2; c--;
3577 /* write the partial length header */
3578 assert( c <= 0x1f ); /*;-)*/
3579 c |= 0xe0;
3580 iobuf_put( chain, c );
3581 if( (n=a->buflen) ) { /* write stuff from the buffer */
3582 assert( n == OP_MIN_PARTIAL_CHUNK);
3583 if( iobuf_write(chain, a->buffer, n ) )
3584 rc = G10ERR_WRITE_FILE;
3585 a->buflen = 0;
3586 nbytes -= n;
3587 }
3588 if( (n = nbytes) > blen )
3589 n = blen;
3590 if( n && iobuf_write(chain, p, n ) )
3591 rc = G10ERR_WRITE_FILE;
3592 p += n;
3593 nbytes -= n;
3594 } while( !rc && nbytes >= OP_MIN_PARTIAL_CHUNK );
3595 /* store the rest in the buffer */
3596 if( !rc && nbytes ) {
3597 assert( !a->buflen );
3598 assert( nbytes < OP_MIN_PARTIAL_CHUNK );
3599 if( !a->buffer )
3600 a->buffer = xmalloc( OP_MIN_PARTIAL_CHUNK );
3601 memcpy( a->buffer, p, nbytes );
3602 a->buflen = nbytes;
3603 }
3604 }
3605 }
3606 else
3607 BUG();
3608 }
3609 else if( control == IOBUFCTRL_INIT ) {
3610 if( DBG_IOBUF )
3611 log_debug("init block_filter %p\n", a );
3612 if( a->partial )
3613 a->count = 0;
3614 else if( a->use == 1 )
3615 a->count = a->size = 0;
3616 else
3617 a->count = a->size; /* force first length bytes */
3618 a->eof = 0;
3619 a->buffer = NULL;
3620 a->buflen = 0;
3621 }
3622 else if( control == IOBUFCTRL_DESC ) {
3623 *(char**)buf = "block_filter";
3624 }
3625 else if( control == IOBUFCTRL_FREE ) {
3626 if( a->use == 2 ) { /* write the end markers */
3627 if( a->partial ) {
3628 u32 len;
3629 /* write out the remaining bytes without a partial header
3630 * the length of this header may be 0 - but if it is
3631 * the first block we are not allowed to use a partial header
3632 * and frankly we can't do so, because this length must be
3633 * a power of 2. This is _really_ complicated because we
3634 * have to check the possible length of a packet prior
3635 * to it's creation: a chain of filters becomes complicated
3636 * and we need a lot of code to handle compressed packets etc.
3637 * :-(((((((
3638 */
3639 /* construct header */
3640 len = a->buflen;
3641 /*log_debug("partial: remaining length=%u\n", len );*/
3642 if( len < 192 )
3643 rc = iobuf_put(chain, len );
3644 else if( len < 8384 ) {
3645 if( !(rc=iobuf_put( chain, ((len-192) / 256) + 192)) )
3646 rc = iobuf_put( chain, ((len-192) % 256));
3647 }
3648 else { /* use a 4 byte header */
3649 if( !(rc=iobuf_put( chain, 0xff )) )
3650 if( !(rc=iobuf_put( chain, (len >> 24)&0xff )) )
3651 if( !(rc=iobuf_put( chain, (len >> 16)&0xff )) )
3652 if( !(rc=iobuf_put( chain, (len >> 8)&0xff )))
3653 rc=iobuf_put( chain, len & 0xff );
3654 }
3655 if( !rc && len )
3656 rc = iobuf_write(chain, a->buffer, len );
3657 if( rc ) {
3658 log_error("block_filter: write error: %s\n",strerror(errno));
3659 rc = G10ERR_WRITE_FILE;
3660 }
3661 xfree( a->buffer ); a->buffer = NULL; a->buflen = 0;
3662 }
3663 else
3664 BUG();
3665 }
3666 else if( a->size ) {
3667 log_error("block_filter: pending bytes!\n");
3668 }
3669 if( DBG_IOBUF )
3670 log_debug("free block_filter %p\n", a );
3671 xfree(a); /* we can free our context now */
3672 }
3673
3674 return rc;
3675 }
3676
3677
3678 static void
3679 print_chain( IOBUF a )
3680 {
3681 if( !DBG_IOBUF )
3682 return;
3683 for(; a; a = a->chain ) {
3684 size_t dummy_len = 0;
3685 const char *desc = "[none]";
3686
3687 if( a->filter )
3688 a->filter( a->filter_ov, IOBUFCTRL_DESC, NULL,
3689 (byte*)&desc, &dummy_len );
3690
3691 log_debug("iobuf chain: %d.%d `%s' filter_eof=%d start=%d len=%d\n",
3692 a->no, a->subno, desc?desc:"?", a->filter_eof,
3693 (int)a->d.start, (int)a->d.len );
3694 }
3695 }
3696
3697 int
3698 iobuf_print_chain( IOBUF a )
3699 {
3700 print_chain(a);
3701 return 0;
3702 }
3703
3704 /****************
3705 * Allocate a new io buffer, with no function assigned.
3706 * Use is the desired usage: 1 for input, 2 for output, 3 for temp buffer
3707 * BUFSIZE is a suggested buffer size.
3708 */
3709 IOBUF
3710 iobuf_alloc(int use, size_t bufsize)
3711 {
3712 IOBUF a;
3713 static int number=0;
3714
3715 a = xmalloc_clear(sizeof *a);
3716 a->use = use;
3717 a->d.buf = xmalloc( bufsize );
3718 a->d.size = bufsize;
3719 a->no = ++number;
3720 a->subno = 0;
3721 a->opaque = NULL;
3722 a->real_fname = NULL;
3723 return a;
3724 }
3725
3726 int
3727 iobuf_close ( IOBUF a )
3728 {
3729 IOBUF a2;
3730 size_t dummy_len=0;
3731 int rc=0;
3732
3733 if( a && a->directfp ) {
3734 fclose( a->directfp );
3735 xfree( a->real_fname );
3736 if( DBG_IOBUF )
3737 log_debug("iobuf_close -> %p\n", a->directfp );
3738 return 0;
3739 }
3740
3741 for( ; a && !rc ; a = a2 ) {
3742 a2 = a->chain;
3743 if( a->use == 2 && (rc=iobuf_flush(a)) )
3744 log_error("iobuf_flush failed on close: %s\n", g10_errstr(rc));
3745
3746 if( DBG_IOBUF )
3747 log_debug("iobuf-%d.%d: close `%s'\n", a->no, a->subno,
3748 a->desc?a->desc:"?");
3749 if( a->filter && (rc = a->filter(a->filter_ov, IOBUFCTRL_FREE,
3750 a->chain, NULL, &dummy_len)) )
3751 log_error("IOBUFCTRL_FREE failed on close: %s\n", g10_errstr(rc) );
3752 xfree(a->real_fname);
3753 if (a->d.buf) {
3754 memset (a->d.buf, 0, a->d.size); /* erase the buffer */
3755 xfree(a->d.buf);
3756 }
3757 xfree(a);
3758 }
3759 return rc;
3760 }
3761
3762 int
3763 iobuf_cancel( IOBUF a )
3764 {
3765 const char *s;
3766 IOBUF a2;
3767 int rc;
3768 #if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
3769 char *remove_name = NULL;
3770 #endif
3771
3772 if( a && a->use == 2 ) {
3773 s = iobuf_get_real_fname(a);
3774 if( s && *s ) {
3775 #if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
3776 remove_name = xstrdup ( s );
3777 #else
3778 remove(s);
3779 #endif
3780 }
3781 }
3782
3783 /* send a cancel message to all filters */
3784 for( a2 = a; a2 ; a2 = a2->chain ) {
3785 size_t dummy;
3786 if( a2->filter )
3787 a2->filter( a2->filter_ov, IOBUFCTRL_CANCEL, a2->chain,
3788 NULL, &dummy );
3789 }
3790
3791 rc = iobuf_close(a);
3792 #if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
3793 if ( remove_name ) {
3794 /* Argg, MSDOS does not allow to remove open files. So
3795 * we have to do it here */
3796 remove ( remove_name );
3797 xfree ( remove_name );
3798 }
3799 #endif
3800 return rc;
3801 }
3802
3803
3804 /****************
3805 * create a temporary iobuf, which can be used to collect stuff
3806 * in an iobuf and later be written by iobuf_write_temp() to another
3807 * iobuf.
3808 */
3809 IOBUF
3810 iobuf_temp()
3811 {
3812 IOBUF a;
3813
3814 a = iobuf_alloc(3, IOBUF_BUFFER_SIZE );
3815
3816 return a;
3817 }
3818
3819 IOBUF
3820 iobuf_temp_with_content( const char *buffer, size_t length )
3821 {
3822 IOBUF a;
3823
3824 a = iobuf_alloc(3, length );
3825 memcpy( a->d.buf, buffer, length );
3826 a->d.len = length;
3827
3828 return a;
3829 }
3830
3831 void
3832 iobuf_enable_special_filenames ( int yes )
3833 {
3834 special_names_enabled = yes;
3835 }
3836
3837 /*
3838 * see whether the filename has the for "-&nnnn", where n is a
3839 * non-zero number.
3840 * Returns this number or -1 if it is not the case.
3841 */
3842 static int
3843 check_special_filename ( const char *fname )
3844 {
3845 if ( special_names_enabled
3846 && fname && *fname == '-' && fname[1] == '&' ) {
3847 int i;
3848
3849 fname += 2;
3850 for (i=0; digitp (fname+i); i++ )
3851 ;
3852 if ( !fname[i] )
3853 return atoi (fname);
3854 }
3855 return -1;
3856 }
3857
3858 /* This fucntion returns true if FNAME indicates a PIPE (stdout or
3859 stderr) or a special file name if those are enabled. */
3860 int
3861 iobuf_is_pipe_filename (const char *fname)
3862 {
3863 if (!fname || (*fname=='-' && !fname[1]) )
3864 return 1;
3865 return check_special_filename (fname) != -1;
3866 }
3867
3868 /****************
3869 * Create a head iobuf for reading from a file
3870 * returns: NULL if an error occures and sets errno
3871 */
3872 IOBUF
3873 iobuf_open( const char *fname )
3874 {
3875 IOBUF a;
3876 FILEP_OR_FD fp;
3877 file_filter_ctx_t *fcx;
3878 size_t len;
3879 int print_only = 0;
3880 int fd;
3881
3882 if( !fname || (*fname=='-' && !fname[1]) ) {
3883 fp = FILEP_OR_FD_FOR_STDIN;
3884 #ifdef USE_SETMODE
3885 setmode ( my_fileno(fp) , O_BINARY );
3886 #endif
3887 fname = "[stdin]";
3888 print_only = 1;
3889 }
3890 else if ( (fd = check_special_filename ( fname )) != -1 )
3891 return iobuf_fdopen ( translate_file_handle (fd,0), "rb" );
3892 else if( (fp = my_fopen_ro(fname, "rb")) == INVALID_FP )
3893 return NULL;
3894 a = iobuf_alloc(1, IOBUF_BUFFER_SIZE );
3895 fcx = xmalloc( sizeof *fcx + strlen(fname) );
3896 fcx->fp = fp;
3897 fcx->print_only_name = print_only;
3898 strcpy(fcx->fname, fname );
3899 if( !print_only )
3900 a->real_fname = xstrdup( fname );
3901 a->filter = file_filter;
3902 a->filter_ov = fcx;
3903 file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
3904 file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
3905 if( DBG_IOBUF )
3906 log_debug("iobuf-%d.%d: open `%s' fd=%d\n",
3907 a->no, a->subno, fname, (int)my_fileno(fcx->fp) );
3908
3909 return a;
3910 }
3911
3912 /****************
3913 * Create a head iobuf for reading from a file
3914 * returns: NULL if an error occures and sets errno
3915 */
3916 IOBUF
3917 iobuf_fdopen( int fd, const char *mode )
3918 {
3919 IOBUF a;
3920 FILEP_OR_FD fp;
3921 file_filter_ctx_t *fcx;
3922 size_t len;
3923
3924 #ifdef FILE_FILTER_USES_STDIO
3925 if( !(fp = fdopen(fd, mode)) )
3926 return NULL;
3927 #else
3928 fp = (FILEP_OR_FD)fd;
3929 #endif
3930 a = iobuf_alloc( strchr( mode, 'w')? 2:1, IOBUF_BUFFER_SIZE );
3931 fcx = xmalloc( sizeof *fcx + 20 );
3932 fcx->fp = fp;
3933 fcx->print_only_name = 1;
3934 sprintf(fcx->fname, "[fd %d]", fd );
3935 a->filter = file_filter;
3936 a->filter_ov = fcx;
3937 file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
3938 file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
3939 if( DBG_IOBUF )
3940 log_debug("iobuf-%d.%d: fdopen `%s'\n", a->no, a->subno, fcx->fname );
3941 iobuf_ioctl (a,3,1,NULL); /* disable fd caching */
3942 return a;
3943 }
3944
3945
3946 IOBUF
3947 iobuf_sockopen ( int fd, const char *mode )
3948 {
3949 IOBUF a;
3950 #ifdef _WIN32
3951 sock_filter_ctx_t *scx;
3952 size_t len;
3953
3954 a = iobuf_alloc( strchr( mode, 'w')? 2:1, IOBUF_BUFFER_SIZE );
3955 scx = xmalloc( sizeof *scx + 25 );
3956 scx->sock = fd;
3957 scx->print_only_name = 1;
3958 sprintf(scx->fname, "[sock %d]", fd );
3959 a->filter = sock_filter;
3960 a->filter_ov = scx;
3961 sock_filter( scx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
3962 sock_filter( scx, IOBUFCTRL_INIT, NULL, NULL, &len );
3963 if( DBG_IOBUF )
3964 log_debug("iobuf-%d.%d: sockopen `%s'\n", a->no, a->subno, scx->fname);
3965 iobuf_ioctl (a,3,1,NULL); /* disable fd caching */
3966 #else
3967 a = iobuf_fdopen (fd, mode);
3968 #endif
3969 return a;
3970 }
3971
3972 /****************
3973 * create an iobuf for writing to a file; the file will be created.
3974 */
3975 IOBUF
3976 iobuf_create( const char *fname )
3977 {
3978 IOBUF a;
3979 FILEP_OR_FD fp;
3980 file_filter_ctx_t *fcx;
3981 size_t len;
3982 int print_only = 0;
3983 int fd;
3984
3985 if( !fname || (*fname=='-' && !fname[1]) ) {
3986 fp = FILEP_OR_FD_FOR_STDOUT;
3987 #ifdef USE_SETMODE
3988 setmode ( my_fileno(fp) , O_BINARY );
3989 #endif
3990 fname = "[stdout]";
3991 print_only = 1;
3992 }
3993 else if ( (fd = check_special_filename ( fname )) != -1 )
3994 return iobuf_fdopen ( translate_file_handle (fd, 1), "wb" );
3995 else if( (fp = my_fopen(fname, "wb")) == INVALID_FP )
3996 return NULL;
3997 a = iobuf_alloc(2, IOBUF_BUFFER_SIZE );
3998 fcx = xmalloc( sizeof *fcx + strlen(fname) );
3999 fcx->fp = fp;
4000 fcx->print_only_name = print_only;
4001 strcpy(fcx->fname, fname );
4002 if( !print_only )
4003 a->real_fname = xstrdup( fname );
4004 a->filter = file_filter;
4005 a->filter_ov = fcx;
4006 file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
4007 file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
4008 if( DBG_IOBUF )
4009 log_debug("iobuf-%d.%d: create `%s'\n", a->no, a->subno,
4010 a->desc?a->desc:"?" );
4011
4012 return a;
4013 }
4014
4015 /****************
4016 * append to an iobuf; if the file does not exist, create it.
4017 * cannot be used for stdout.
4018 * Note: This is not used.
4019 */
4020 #if 0 /* not used */
4021 IOBUF
4022 iobuf_append( const char *fname )
4023 {
4024 IOBUF a;
4025 FILE *fp;
4026 file_filter_ctx_t *fcx;
4027 size_t len;
4028
4029 if( !fname )
4030 return NULL;
4031 else if( !(fp = my_fopen(fname, "ab")) )
4032 return NULL;
4033 a = iobuf_alloc(2, IOBUF_BUFFER_SIZE );
4034 fcx = xmalloc( sizeof *fcx + strlen(fname) );
4035 fcx->fp = fp;
4036 strcpy(fcx->fname, fname );
4037 a->real_fname = xstrdup( fname );
4038 a->filter = file_filter;
4039 a->filter_ov = fcx;
4040 file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
4041 file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
4042 if( DBG_IOBUF )
4043 log_debug("iobuf-%d.%d: append `%s'\n", a->no, a->subno,
4044 a->desc?a->desc:"?" );
4045
4046 return a;
4047 }
4048 #endif
4049
4050 IOBUF
4051 iobuf_openrw( const char *fname )
4052 {
4053 IOBUF a;
4054 FILEP_OR_FD fp;
4055 file_filter_ctx_t *fcx;
4056 size_t len;
4057
4058 if( !fname )
4059 return NULL;
4060 else if( (fp = my_fopen(fname, "r+b")) == INVALID_FP )
4061 return NULL;
4062 a = iobuf_alloc(2, IOBUF_BUFFER_SIZE );
4063 fcx = xmalloc( sizeof *fcx + strlen(fname) );
4064 fcx->fp = fp;
4065 strcpy(fcx->fname, fname );
4066 a->real_fname = xstrdup( fname );
4067 a->filter = file_filter;
4068 a->filter_ov = fcx;
4069 file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
4070 file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
4071 if( DBG_IOBUF )
4072 log_debug("iobuf-%d.%d: openrw `%s'\n", a->no, a->subno,
4073 a->desc?a->desc:"?");
4074
4075 return a;
4076 }
4077
4078
4079 int
4080 iobuf_ioctl ( IOBUF a, int cmd, int intval, void *ptrval )
4081 {
4082 if ( cmd == 1 ) { /* keep system filepointer/descriptor open */
4083 if( DBG_IOBUF )
4084 log_debug("iobuf-%d.%d: ioctl `%s' keep=%d\n",
4085 a? a->no:-1, a?a->subno:-1,
4086 a&&a->desc?a->desc:"?", intval );
4087 for( ; a; a = a->chain )
4088 if( !a->chain && a->filter == file_filter ) {
4089 file_filter_ctx_t *b = a->filter_ov;
4090 b->keep_open = intval;
4091 return 0;
4092 }
4093 #ifdef _WIN32
4094 else if( !a->chain && a->filter == sock_filter ) {
4095 sock_filter_ctx_t *b = a->filter_ov;
4096 b->keep_open = intval;
4097 return 0;
4098 }
4099 #endif
4100 }
4101 else if ( cmd == 2 ) { /* invalidate cache */
4102 if( DBG_IOBUF )
4103 log_debug("iobuf-*.*: ioctl `%s' invalidate\n",
4104 ptrval? (char*)ptrval:"[all]");
4105 if ( !a && !intval ) {
4106 #ifndef FILE_FILTER_USES_STDIO
4107 return fd_cache_invalidate (ptrval);
4108 #endif
4109 return 0;
4110 }
4111 }
4112 else if ( cmd == 3 ) { /* disallow/allow caching */
4113 if( DBG_IOBUF )
4114 log_debug("iobuf-%d.%d: ioctl `%s' no_cache=%d\n",
4115 a? a->no:-1, a?a->subno:-1,
4116 a&&a->desc?a->desc:"?", intval );
4117 for( ; a; a = a->chain )
4118 if( !a->chain && a->filter == file_filter ) {
4119 file_filter_ctx_t *b = a->filter_ov;
4120 b->no_cache = intval;
4121 return 0;
4122 }
4123 #ifdef _WIN32
4124 else if( !a->chain && a->filter == sock_filter ) {
4125 sock_filter_ctx_t *b = a->filter_ov;
4126 b->no_cache = intval;
4127 return 0;
4128 }
4129 #endif
4130 }
4131 else if(cmd==4)
4132 {
4133 /* Do a fsync on the open fd and return any errors to the
4134 caller of iobuf_ioctl */
4135 if( DBG_IOBUF )
4136 log_debug("iobuf-*.*: ioctl `%s' fsync\n",
4137 ptrval? (char*)ptrval:"<null>");
4138
4139 if(!a && !intval && ptrval)
4140 {
4141 #ifndef FILE_FILTER_USES_STDIO
4142 return fd_cache_synchronize (ptrval);
4143 #else
4144 return 0;
4145 #endif
4146 }
4147 }
4148
4149 return -1;
4150 }
4151
4152
4153 /****************
4154 * Register an i/o filter.
4155 */
4156 int
4157 iobuf_push_filter( IOBUF a,
4158 int (*f)(void *opaque, int control,
4159 IOBUF chain, byte *buf, size_t *len), void *ov )
4160 {
4161 return iobuf_push_filter2( a, f, ov, 0 );
4162 }
4163
4164 int
4165 iobuf_push_filter2( IOBUF a,
4166 int (*f)(void *opaque, int control,
4167 IOBUF chain, byte *buf, size_t *len),
4168 void *ov, int rel_ov )
4169 {
4170 IOBUF b;
4171 size_t dummy_len=0;
4172 int rc=0;
4173
4174 if( a->directfp )
4175 BUG();
4176
4177 if( a->use == 2 && (rc=iobuf_flush(a)) )
4178 return rc;
4179 /* make a copy of the current stream, so that
4180 * A is the new stream and B the original one.
4181 * The contents of the buffers are transferred to the
4182 * new stream.
4183 */
4184 b = xmalloc(sizeof *b);
4185 memcpy(b, a, sizeof *b );
4186 /* fixme: it is stupid to keep a copy of the name at every level
4187 * but we need the name somewhere because the name known by file_filter
4188 * may have been released when we need the name of the file */
4189 b->real_fname = a->real_fname? xstrdup(a->real_fname):NULL;
4190 /* remove the filter stuff from the new stream */
4191 a->filter = NULL;
4192 a->filter_ov = NULL;
4193 a->filter_ov_owner = 0;
4194 a->filter_eof = 0;
4195 if( a->use == 3 )
4196 a->use = 2; /* make a write stream from a temp stream */
4197
4198 if( a->use == 2 ) { /* allocate a fresh buffer for the original stream */
4199 b->d.buf = xmalloc( a->d.size );
4200 b->d.len = 0;
4201 b->d.start = 0;
4202 }
4203 else { /* allocate a fresh buffer for the new stream */
4204 a->d.buf = xmalloc( a->d.size );
4205 a->d.len = 0;
4206 a->d.start = 0;
4207 }
4208 /* disable nlimit for the new stream */
4209 a->ntotal = b->ntotal + b->nbytes;
4210 a->nlimit = a->nbytes = 0;
4211 a->nofast &= ~1;
4212 /* make a link from the new stream to the original stream */
4213 a->chain = b;
4214 a->opaque = b->opaque;
4215
4216 /* setup the function on the new stream */
4217 a->filter = f;
4218 a->filter_ov = ov;
4219 a->filter_ov_owner = rel_ov;
4220
4221 a->subno = b->subno + 1;
4222 f( ov, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &dummy_len );
4223
4224 if( DBG_IOBUF ) {
4225 log_debug("iobuf-%d.%d: push `%s'\n", a->no, a->subno,
4226 a->desc?a->desc:"?" );
4227 print_chain( a );
4228 }
4229
4230 /* now we can initialize the new function if we have one */
4231 if( a->filter && (rc = a->filter(a->filter_ov, IOBUFCTRL_INIT, a->chain,
4232 NULL, &dummy_len)) )
4233 log_error("IOBUFCTRL_INIT failed: %s\n", g10_errstr(rc) );
4234 return rc;
4235 }
4236
4237 /****************
4238 * Remove an i/o filter.
4239 */
4240 static int
4241 pop_filter( IOBUF a, int (*f)(void *opaque, int control,
4242 IOBUF chain, byte *buf, size_t *len), void *ov )
4243 {
4244 IOBUF b;
4245 size_t dummy_len=0;
4246 int rc=0;
4247
4248 if( a->directfp )
4249 BUG();
4250
4251 if( DBG_IOBUF )
4252 log_debug("iobuf-%d.%d: pop `%s'\n", a->no, a->subno,
4253 a->desc?a->desc:"?" );
4254 if( !a->filter ) { /* this is simple */
4255 b = a->chain;
4256 assert(b);
4257 xfree(a->d.buf);
4258 xfree(a->real_fname);
4259 memcpy(a,b, sizeof *a);
4260 xfree(b);
4261 return 0;
4262 }
4263 for(b=a ; b; b = b->chain )
4264 if( b->filter == f && (!ov || b->filter_ov == ov) )
4265 break;
4266 if( !b )
4267 log_bug("pop_filter(): filter function not found\n");
4268
4269 /* flush this stream if it is an output stream */
4270 if( a->use == 2 && (rc=iobuf_flush(b)) ) {
4271 log_error("iobuf_flush failed in pop_filter: %s\n", g10_errstr(rc));
4272 return rc;
4273 }
4274 /* and tell the filter to free it self */
4275 if( b->filter && (rc = b->filter(b->filter_ov, IOBUFCTRL_FREE, b->chain,
4276 NULL, &dummy_len)) ) {
4277 log_error("IOBUFCTRL_FREE failed: %s\n", g10_errstr(rc) );
4278 return rc;
4279 }
4280 if( b->filter_ov && b->filter_ov_owner ) {
4281 xfree( b->filter_ov );
4282 b->filter_ov = NULL;
4283 }
4284
4285
4286 /* and see how to remove it */
4287 if( a == b && !b->chain )
4288 log_bug("can't remove the last filter from the chain\n");
4289 else if( a == b ) { /* remove the first iobuf from the chain */
4290 /* everything from b is copied to a. This is save because
4291 * a flush has been done on the to be removed entry
4292 */
4293 b = a->chain;
4294 xfree(a->d.buf);
4295 xfree(a->real_fname);
4296 memcpy(a,b, sizeof *a);
4297 xfree(b);
4298 if( DBG_IOBUF )
4299 log_debug("iobuf-%d.%d: popped filter\n", a->no, a->subno );
4300 }
4301 else if( !b->chain ) { /* remove the last iobuf from the chain */
4302 log_bug("Ohh jeee, trying to remove a head filter\n");
4303 }
4304 else { /* remove an intermediate iobuf from the chain */
4305 log_bug("Ohh jeee, trying to remove an intermediate filter\n");
4306 }
4307
4308 return rc;
4309 }
4310
4311
4312 /****************
4313 * read underflow: read more bytes into the buffer and return
4314 * the first byte or -1 on EOF.
4315 */
4316 static int
4317 underflow(IOBUF a)
4318 {
4319 size_t len;
4320 int rc;
4321
4322 assert( a->d.start == a->d.len );
4323 if( a->use == 3 )
4324 return -1; /* EOF because a temp buffer can't do an underflow */
4325
4326 if( a->filter_eof ) {
4327 if( a->chain ) {
4328 IOBUF b = a->chain;
4329 if( DBG_IOBUF )
4330 log_debug("iobuf-%d.%d: pop `%s' in underflow\n",
4331 a->no, a->subno, a->desc?a->desc:"?" );
4332 xfree(a->d.buf);
4333 xfree(a->real_fname);
4334 memcpy(a, b, sizeof *a);
4335 xfree(b);
4336 print_chain(a);
4337 }
4338 else
4339 a->filter_eof = 0; /* for the top level filter */
4340 if( DBG_IOBUF )
4341 log_debug("iobuf-%d.%d: underflow: eof (due to filter eof)\n",
4342 a->no, a->subno );
4343 return -1; /* return one(!) EOF */
4344 }
4345 if( a->error ) {
4346 if( DBG_IOBUF )
4347 log_debug("iobuf-%d.%d: error\n", a->no, a->subno );
4348 return -1;
4349 }
4350
4351 if( a->directfp ) {
4352 FILE *fp = a->directfp;
4353
4354 len = fread( a->d.buf, 1, a->d.size, fp);
4355 if( len < a->d.size ) {
4356 if( ferror(fp) )
4357 a->error = 1;
4358 }
4359 a->d.len = len;
4360 a->d.start = 0;
4361 return len? a->d.buf[a->d.start++] : -1;
4362 }
4363
4364
4365 if( a->filter ) {
4366 len = a->d.size;
4367 if( DBG_IOBUF )
4368 log_debug("iobuf-%d.%d: underflow: req=%lu\n",
4369 a->no, a->subno, (ulong)len );
4370 rc = a->filter( a->filter_ov, IOBUFCTRL_UNDERFLOW, a->chain,
4371 a->d.buf, &len );
4372 if( DBG_IOBUF ) {
4373 log_debug("iobuf-%d.%d: underflow: got=%lu rc=%d\n",
4374 a->no, a->subno, (ulong)len, rc );
4375 /* if( a->no == 1 ) */
4376 /* log_hexdump (" data:", a->d.buf, len); */
4377 }
4378 if( a->use == 1 && rc == -1 ) { /* EOF: we can remove the filter */
4379 size_t dummy_len=0;
4380
4381 /* and tell the filter to free itself */
4382 if( (rc = a->filter(a->filter_ov, IOBUFCTRL_FREE, a->chain,
4383 NULL, &dummy_len)) )
4384 log_error("IOBUFCTRL_FREE failed: %s\n", g10_errstr(rc) );
4385 if( a->filter_ov && a->filter_ov_owner ) {
4386 xfree( a->filter_ov );
4387 a->filter_ov = NULL;
4388 }
4389 a->filter = NULL;
4390 a->desc = NULL;
4391 a->filter_ov = NULL;
4392 a->filter_eof = 1;
4393 if( !len && a->chain ) {
4394 IOBUF b = a->chain;
4395 if( DBG_IOBUF )
4396 log_debug("iobuf-%d.%d: pop in underflow (!len)\n",
4397 a->no, a->subno);
4398 xfree(a->d.buf);
4399 xfree(a->real_fname);
4400 memcpy(a,b, sizeof *a);
4401 xfree(b);
4402 print_chain(a);
4403 }
4404 }
4405 else if( rc )
4406 a->error = 1;
4407
4408 if( !len ) {
4409 if( DBG_IOBUF )
4410 log_debug("iobuf-%d.%d: underflow: eof\n", a->no, a->subno );
4411 return -1;
4412 }
4413 a->d.len = len;
4414 a->d.start = 0;
4415 return a->d.buf[a->d.start++];
4416 }
4417 else {
4418 if( DBG_IOBUF )
4419 log_debug("iobuf-%d.%d: underflow: eof (no filter)\n",
4420 a->no, a->subno );
4421 return -1; /* no filter; return EOF */
4422 }
4423 }
4424
4425
4426 int
4427 iobuf_flush(IOBUF a)
4428 {
4429 size_t len;
4430 int rc;
4431
4432 if( a->directfp )
4433 return 0;
4434
4435 if( a->use == 3 ) { /* increase the temp buffer */
4436 char *newbuf;
4437 size_t newsize = a->d.size + IOBUF_BUFFER_SIZE;
4438
4439 if( DBG_IOBUF )
4440 log_debug("increasing temp iobuf from %lu to %lu\n",
4441 (ulong)a->d.size, (ulong)newsize );
4442 newbuf = xmalloc( newsize );
4443 memcpy( newbuf, a->d.buf, a->d.len );
4444 xfree(a->d.buf);
4445 a->d.buf = newbuf;
4446 a->d.size = newsize;
4447 return 0;
4448 }
4449 else if( a->use != 2 )
4450 log_bug("flush on non-output iobuf\n");
4451 else if( !a->filter )
4452 log_bug("iobuf_flush: no filter\n");
4453 len = a->d.len;
4454 rc = a->filter( a->filter_ov, IOBUFCTRL_FLUSH, a->chain, a->d.buf, &len );
4455 if( !rc && len != a->d.len ) {
4456 log_info("iobuf_flush did not write all!\n");
4457 rc = G10ERR_WRITE_FILE;
4458 }
4459 else if( rc )
4460 a->error = 1;
4461 a->d.len = 0;
4462
4463 return rc;
4464 }
4465
4466
4467 /****************
4468 * Read a byte from the iobuf; returns -1 on EOF
4469 */
4470 int
4471 iobuf_readbyte(IOBUF a)
4472 {
4473 int c;
4474
4475 /* nlimit does not work together with unget */
4476 /* nbytes is also not valid! */
4477 if( a->unget.buf ) {
4478 if( a->unget.start < a->unget.len )
4479 return a->unget.buf[a->unget.start++];
4480 xfree(a->unget.buf);
4481 a->unget.buf = NULL;
4482 a->nofast &= ~2;
4483 }
4484
4485 if( a->nlimit && a->nbytes >= a->nlimit )
4486 return -1; /* forced EOF */
4487
4488 if( a->d.start < a->d.len ) {
4489 c = a->d.buf[a->d.start++];
4490 }
4491 else if( (c=underflow(a)) == -1 )
4492 return -1; /* EOF */
4493
4494 a->nbytes++;
4495 return c;
4496 }
4497
4498
4499 int
4500 iobuf_read(IOBUF a, byte *buf, unsigned buflen )
4501 {
4502 int c, n;
4503
4504 if( a->unget.buf || a->nlimit ) {
4505 /* handle special cases */
4506 for(n=0 ; n < buflen; n++ ) {
4507 if( (c = iobuf_readbyte(a)) == -1 ) {
4508 if( !n )
4509 return -1; /* eof */
4510 break;
4511 }
4512 else
4513 if( buf ) *buf = c;
4514 if( buf ) buf++;
4515 }
4516 return n;
4517 }
4518
4519 n = 0;
4520 do {
4521 if( n < buflen && a->d.start < a->d.len ) {
4522 unsigned size = a->d.len - a->d.start;
4523 if( size > buflen - n )
4524 size = buflen - n;
4525 if( buf )
4526 memcpy( buf, a->d.buf + a->d.start, size );
4527 n += size;
4528 a->d.start += size;
4529 if( buf )
4530 buf += size;
4531 }
4532 if( n < buflen ) {
4533 if( (c=underflow(a)) == -1 ) {
4534 a->nbytes += n;
4535 return n? n : -1/*EOF*/;
4536 }
4537 if( buf )
4538 *buf++ = c;
4539 n++;
4540 }
4541 } while( n < buflen );
4542 a->nbytes += n;
4543 return n;
4544 }
4545
4546
4547 /****************
4548 * Have a look at the iobuf.
4549 * NOTE: This only works in special cases.
4550 */
4551 int
4552 iobuf_peek(IOBUF a, byte *buf, unsigned buflen )
4553 {
4554 int n=0;
4555
4556 if( a->filter_eof )
4557 return -1;
4558
4559 if( !(a->d.start < a->d.len) ) {
4560 if( underflow(a) == -1 )
4561 return -1;
4562 /* and unget this character */
4563 assert(a->d.start == 1);
4564 a->d.start = 0;
4565 }
4566
4567 for(n=0 ; n < buflen && (a->d.start+n) < a->d.len ; n++, buf++ )
4568 *buf = a->d.buf[n];
4569 return n;
4570 }
4571
4572
4573
4574
4575 int
4576 iobuf_writebyte(IOBUF a, unsigned c)
4577 {
4578
4579 if( a->directfp )
4580 BUG();
4581
4582 if( a->d.len == a->d.size )
4583 if( iobuf_flush(a) )
4584 return -1;
4585
4586 assert( a->d.len < a->d.size );
4587 a->d.buf[a->d.len++] = c;
4588 return 0;
4589 }
4590
4591
4592 int
4593 iobuf_write(IOBUF a, byte *buf, unsigned buflen )
4594 {
4595
4596 if( a->directfp )
4597 BUG();
4598
4599 do {
4600 if( buflen && a->d.len < a->d.size ) {
4601 unsigned size = a->d.size - a->d.len;
4602 if( size > buflen ) size = buflen;
4603 memcpy( a->d.buf + a->d.len, buf, size );
4604 buflen -= size;
4605 buf += size;
4606 a->d.len += size;
4607 }
4608 if( buflen ) {
4609 if( iobuf_flush(a) )
4610 return -1;
4611 }
4612 } while( buflen );
4613 return 0;
4614 }
4615
4616
4617 int
4618 iobuf_writestr(IOBUF a, const char *buf )
4619 {
4620 for( ; *buf; buf++ )
4621 if( iobuf_writebyte(a, *buf) )
4622 return -1;
4623 return 0;
4624 }
4625
4626
4627
4628 /****************
4629 * copy the contents of TEMP to A.
4630 */
4631 int
4632 iobuf_write_temp( IOBUF a, IOBUF temp )
4633 {
4634 while( temp->chain )
4635 pop_filter( temp, temp->filter, NULL );
4636 return iobuf_write(a, temp->d.buf, temp->d.len );
4637 }
4638
4639 /****************
4640 * copy the contents of the temp io stream to BUFFER.
4641 */
4642 size_t
4643 iobuf_temp_to_buffer( IOBUF a, byte *buffer, size_t buflen )
4644 {
4645 size_t n = a->d.len;
4646
4647 if( n > buflen )
4648 n = buflen;
4649 memcpy( buffer, a->d.buf, n );
4650 return n;
4651 }
4652
4653
4654 /****************
4655 * Call this function to terminate processing of the temp stream
4656 * without closing it. This removes all filters from the stream
4657 * makes sure that iobuf_get_temp_{buffer,length}() returns correct
4658 * values.
4659 */
4660 void
4661 iobuf_flush_temp( IOBUF temp )
4662 {
4663 while( temp->chain )
4664 pop_filter( temp, temp->filter, NULL );
4665 }
4666
4667
4668 /****************
4669 * Set a limit on how many bytes may be read from the input stream A.
4670 * Setting the limit to 0 disables this feature.
4671 */
4672 void
4673 iobuf_set_limit( IOBUF a, off_t nlimit )
4674 {
4675 if( nlimit )
4676 a->nofast |= 1;
4677 else
4678 a->nofast &= ~1;
4679 a->nlimit = nlimit;
4680 a->ntotal += a->nbytes;
4681 a->nbytes = 0;
4682 }
4683
4684
4685
4686 /* Return the length of an open file A. IF OVERFLOW is not NULL it
4687 will be set to true if the file is larger than what off_t can cope
4688 with. The function return 0 on error or on overflow condition. */
4689 off_t
4690 iobuf_get_filelength (IOBUF a, int *overflow )
4691 {
4692 struct stat st;
4693
4694 if (overflow)
4695 *overflow = 0;
4696
4697 if( a->directfp ) {
4698 FILE *fp = a->directfp;
4699
4700 if( !fstat(fileno(fp), &st) )
4701 return st.st_size;
4702 log_error("fstat() failed: %s\n", strerror(errno) );
4703 return 0;
4704 }
4705
4706 /* Hmmm: file_filter may have already been removed */
4707 for( ; a; a = a->chain )
4708 if( !a->chain && a->filter == file_filter ) {
4709 file_filter_ctx_t *b = a->filter_ov;
4710 FILEP_OR_FD fp = b->fp;
4711
4712 #if defined(HAVE_DOSISH_SYSTEM) && !defined(FILE_FILTER_USES_STDIO)
4713 ulong size;
4714 static int (* __stdcall get_file_size_ex)
4715 (void *handle, LARGE_INTEGER *size);
4716 static int get_file_size_ex_initialized;
4717
4718 if (!get_file_size_ex_initialized)
4719 {
4720 void *handle;
4721
4722 handle = dlopen ("kernel32.dll", RTLD_LAZY);
4723 if (handle)
4724 {
4725 get_file_size_ex = dlsym (handle, "GetFileSizeEx");
4726 if (!get_file_size_ex)
4727 dlclose (handle);
4728 }
4729 get_file_size_ex_initialized = 1;
4730 }
4731
4732 if (get_file_size_ex)
4733 {
4734 /* This is a newer system with GetFileSizeEx; we use
4735 this then becuase it seem that GetFileSize won't
4736 return a proper error in case a file is larger than
4737 4GB. */
4738 LARGE_INTEGER size;
4739
4740 if (get_file_size_ex (fp, &size))
4741 {
4742 if (!size.u.HighPart)
4743 return size.u.LowPart;
4744 if (overflow)
4745 *overflow = 1;
4746 return 0;
4747 }
4748 }
4749 else
4750 {
4751 if ((size=GetFileSize (fp, NULL)) != 0xffffffff)
4752 return size;
4753 }
4754 log_error ("GetFileSize for handle %p failed: %s\n",
4755 fp, w32_strerror (0));
4756 #else
4757 if( !fstat(my_fileno(fp), &st) )
4758 return st.st_size;
4759 log_error("fstat() failed: %s\n", strerror(errno) );
4760 #endif
4761 break;
4762 }
4763
4764 return 0;
4765 }
4766
4767
4768 /* Return the file descriptor of the underlying file or -1 if it is
4769 not available. */
4770 int
4771 iobuf_get_fd (IOBUF a)
4772 {
4773 if (a->directfp)
4774 return fileno ( (FILE*)a->directfp );
4775
4776 for ( ; a; a = a->chain )
4777 if (!a->chain && a->filter == file_filter)
4778 {
4779 file_filter_ctx_t *b = a->filter_ov;
4780 FILEP_OR_FD fp = b->fp;
4781
4782 return my_fileno (fp);
4783 }
4784
4785 return -1;
4786 }
4787
4788
4789 /****************
4790 * Tell the file position, where the next read will take place
4791 */
4792 off_t
4793 iobuf_tell( IOBUF a )
4794 {
4795 return a->ntotal + a->nbytes;
4796 }
4797
4798
4799 #if !defined(HAVE_FSEEKO) && !defined(fseeko)
4800
4801 #ifdef HAVE_LIMITS_H
4802 # include <limits.h>
4803 #endif
4804 #ifndef LONG_MAX
4805 # define LONG_MAX ((long) ((unsigned long) -1 >> 1))
4806 #endif
4807 #ifndef LONG_MIN
4808 # define LONG_MIN (-1 - LONG_MAX)
4809 #endif
4810
4811 /****************
4812 * A substitute for fseeko, for hosts that don't have it.
4813 */
4814 static int
4815 fseeko( FILE *stream, off_t newpos, int whence )
4816 {
4817 while( newpos != (long) newpos ) {
4818 long pos = newpos < 0 ? LONG_MIN : LONG_MAX;
4819 if( fseek( stream, pos, whence ) != 0 )
4820 return -1;
4821 newpos -= pos;
4822 whence = SEEK_CUR;
4823 }
4824 return fseek( stream, (long)newpos, whence );
4825 }
4826 #endif
4827
4828 /****************
4829 * This is a very limited implementation. It simply discards all internal
4830 * buffering and removes all filters but the first one.
4831 */
4832 int
4833 iobuf_seek( IOBUF a, off_t newpos )
4834 {
4835 file_filter_ctx_t *b = NULL;
4836
4837 if( a->directfp ) {
4838 FILE *fp = a->directfp;
4839 if( fseeko( fp, newpos, SEEK_SET ) ) {
4840 log_error("can't seek: %s\n", strerror(errno) );
4841 return -1;
4842 }
4843 clearerr(fp);
4844 }
4845 else {
4846 for( ; a; a = a->chain ) {
4847 if( !a->chain && a->filter == file_filter ) {
4848 b = a->filter_ov;
4849 break;
4850 }
4851 }
4852 if( !a )
4853 return -1;
4854 #ifdef FILE_FILTER_USES_STDIO
4855 if( fseeko( b->fp, newpos, SEEK_SET ) ) {
4856 log_error("can't fseek: %s\n", strerror(errno) );
4857 return -1;
4858 }
4859 #else
4860 #ifdef HAVE_DOSISH_SYSTEM
4861 if (SetFilePointer (b->fp, newpos, NULL, FILE_BEGIN) == 0xffffffff ) {
4862 log_error ("SetFilePointer failed on handle %p: %s\n",
4863 b->fp, w32_strerror (0));
4864 return -1;
4865 }
4866 #else
4867 if ( lseek (b->fp, newpos, SEEK_SET) == (off_t)-1 ) {
4868 log_error("can't lseek: %s\n", strerror(errno) );
4869 return -1;
4870 }
4871 #endif
4872 #endif
4873 }
4874 a->d.len = 0; /* discard buffer */
4875 a->d.start = 0;
4876 a->nbytes = 0;
4877 a->nlimit = 0;
4878 a->nofast &= ~1;
4879 a->ntotal = newpos;
4880 a->error = 0;
4881 /* remove filters, but the last */
4882 if( a->chain )
4883 log_debug("pop_filter called in iobuf_seek - please report\n");
4884 while( a->chain )
4885 pop_filter( a, a->filter, NULL );
4886
4887 return 0;
4888 }
4889
4890
4891
4892
4893
4894
4895 /****************
4896 * Retrieve the real filename
4897 */
4898 const char *
4899 iobuf_get_real_fname( IOBUF a )
4900 {
4901 if( a->real_fname )
4902 return a->real_fname;
4903
4904 /* the old solution */
4905 for( ; a; a = a->chain )
4906 if( !a->chain && a->filter == file_filter ) {
4907 file_filter_ctx_t *b = a->filter_ov;
4908 return b->print_only_name? NULL : b->fname;
4909 }
4910
4911 return NULL;
4912 }
4913
4914
4915 /****************
4916 * Retrieve the filename
4917 */
4918 const char *
4919 iobuf_get_fname( IOBUF a )
4920 {
4921 for( ; a; a = a->chain )
4922 if( !a->chain && a->filter == file_filter ) {
4923 file_filter_ctx_t *b = a->filter_ov;
4924 return b->fname;
4925 }
4926
4927 return NULL;
4928 }
4929
4930
4931 /****************
4932 * enable partial block mode as described in the OpenPGP draft.
4933 * LEN is the first length byte on read, but ignored on writes.
4934 */
4935 void
4936 iobuf_set_partial_block_mode( IOBUF a, size_t len )
4937 {
4938 block_filter_ctx_t *ctx = xmalloc_clear( sizeof *ctx );
4939
4940 assert( a->use == 1 || a->use == 2 );
4941 ctx->use = a->use;
4942 if( !len ) {
4943 if( a->use == 1 )
4944 log_debug("pop_filter called in set_partial_block_mode"
4945 " - please report\n");
4946 pop_filter(a, block_filter, NULL );
4947 }
4948 else {
4949 ctx->partial = 1;
4950 ctx->size = 0;
4951 ctx->first_c = len;
4952 iobuf_push_filter(a, block_filter, ctx );
4953 }
4954 }
4955
4956
4957 /****************
4958 * Same as fgets() but if the buffer is too short a larger one will
4959 * be allocated up to some limit *max_length.
4960 * A line is considered a byte stream ending in a LF.
4961 * Returns the length of the line. EOF is indicated by a line of
4962 * length zero. The last LF may be missing due to an EOF.
4963 * is max_length is zero on return, the line has been truncated.
4964 *
4965 * Note: The buffer is allocated with enough space to append a CR,LF,EOL
4966 */
4967 unsigned
4968 iobuf_read_line( IOBUF a, byte **addr_of_buffer,
4969 unsigned *length_of_buffer, unsigned *max_length )
4970 {
4971 int c;
4972 char *buffer = *addr_of_buffer;
4973 unsigned length = *length_of_buffer;
4974 unsigned nbytes = 0;
4975 unsigned maxlen = *max_length;
4976 char *p;
4977
4978 if( !buffer ) { /* must allocate a new buffer */
4979 length = 256;
4980 buffer = xmalloc( length );
4981 *addr_of_buffer = buffer;
4982 *length_of_buffer = length;
4983 }
4984
4985 length -= 3; /* reserve 3 bytes (cr,lf,eol) */
4986 p = buffer;
4987 while( (c=iobuf_get(a)) != -1 ) {
4988 if( nbytes == length ) { /* increase the buffer */
4989 if( length > maxlen ) { /* this is out limit */
4990 /* skip the rest of the line */
4991 while( c != '\n' && (c=iobuf_get(a)) != -1 )
4992 ;
4993 *p++ = '\n'; /* always append a LF (we have reserved space) */
4994 nbytes++;
4995 *max_length = 0; /* indicate truncation */
4996 break;
4997 }
4998 length += 3; /* correct for the reserved byte */
4999 length += length < 1024? 256 : 1024;
5000 buffer = xrealloc( buffer, length );
5001 *addr_of_buffer = buffer;
5002 *length_of_buffer = length;
5003 length -= 3; /* and reserve again */
5004 p = buffer + nbytes;
5005 }
5006 *p++ = c;
5007 nbytes++;
5008 if( c == '\n' )
5009 break;
5010 }
5011 *p = 0; /* make sure the line is a string */
5012
5013 return nbytes;
5014 }
5015
5016 /* This is the non iobuf specific function */
5017 int
5018 iobuf_translate_file_handle ( int fd, int for_write )
5019 {
5020 #ifdef _WIN32
5021 {
5022 int x;
5023
5024 if ( fd <= 2 )
5025 return fd; /* do not do this for error, stdin, stdout, stderr */
5026
5027 x = _open_osfhandle ( fd, for_write? 1:0 );
5028 if (x==-1 )
5029 log_error ("failed to translate osfhandle %p\n", (void*)fd );
5030 else {
5031 /*log_info ("_open_osfhandle %p yields %d%s\n",
5032 (void*)fd, x, for_write? " for writing":"" );*/
5033 fd = x;
5034 }
5035 }
5036 #endif
5037 return fd;
5038 }
5039
5040 static int
5041 translate_file_handle ( int fd, int for_write )
5042 {
5043 #ifdef _WIN32
5044 #ifdef FILE_FILTER_USES_STDIO
5045 fd = iobuf_translate_file_handle (fd, for_write);
5046 #else
5047 {
5048 int x;
5049
5050 if ( fd == 0 )
5051 x = (int)GetStdHandle (STD_INPUT_HANDLE);
5052 else if (fd == 1)
5053 x = (int)GetStdHandle (STD_OUTPUT_HANDLE);
5054 else if (fd == 2)
5055 x = (int)GetStdHandle (STD_ERROR_HANDLE);
5056 else
5057 x = fd;
5058
5059 if (x == -1)
5060 log_debug ("GetStdHandle(%d) failed: %s\n",
5061 fd, w32_strerror (0));
5062
5063 fd = x;
5064 }
5065 #endif
5066 #endif
5067 return fd;
5068 }
5069
5070
5071 void
5072 iobuf_skip_rest(IOBUF a, unsigned long n, int partial)
5073 {
5074 if ( partial ) {
5075 for (;;) {
5076 if (a->nofast || a->d.start >= a->d.len) {
5077 if (iobuf_readbyte (a) == -1) {
5078 break;
5079 }
5080 } else {
5081 unsigned long count = a->d.len - a->d.start;
5082 a->nbytes += count;
5083 a->d.start = a->d.len;
5084 }
5085 }
5086 } else {
5087 unsigned long remaining = n;
5088 while (remaining > 0) {
5089 if (a->nofast || a->d.start >= a->d.len) {
5090 if (iobuf_readbyte (a) == -1) {
5091 break;
5092 }
5093 --remaining;
5094 } else {
5095 unsigned long count = a->d.len - a->d.start;
5096 if (count > remaining) {
5097 count = remaining;
5098 }
5099 a->nbytes += count;
5100 a->d.start += count;
5101 remaining -= count;
5102 }
5103 }
5104 }
5105 }