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