1 /* keybox-file.c - File operations
2 * Copyright (C) 2001, 2003 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <https://www.gnu.org/licenses/>.
27 #include "keybox-defs.h"
30 #define IMAGELEN_LIMIT (5*1024*1024)
33 #if !defined(HAVE_FTELLO) && !defined(ftello)
44 #endif /* !defined(HAVE_FTELLO) && !defined(ftello) */
48 /* Read a block at the current position and return it in r_blob.
49 r_blob may be NULL to simply skip the current block. */
51 _keybox_read_blob2 (KEYBOXBLOB *r_blob, FILE *fp, int *skipped_deleted)
55 int c1, c2, c3, c4, type;
65 return gpg_error_from_syserror ();
67 if ((c1 = getc (fp)) == EOF
68 || (c2 = getc (fp)) == EOF
69 || (c3 = getc (fp)) == EOF
70 || (c4 = getc (fp)) == EOF
71 || (type = getc (fp)) == EOF)
73 if ( c1 == EOF && !ferror (fp) )
76 return gpg_error (GPG_ERR_TOO_SHORT);
77 return gpg_error_from_syserror ();
80 imagelen = ((unsigned int) c1 << 24) | (c2 << 16) | (c3 << 8 ) | c4;
82 return gpg_error (GPG_ERR_TOO_SHORT);
86 /* Special treatment for empty blobs. */
87 if (fseek (fp, imagelen-5, SEEK_CUR))
88 return gpg_error_from_syserror ();
93 if (imagelen > IMAGELEN_LIMIT) /* Sanity check. */
95 /* Seek forward so that the caller may choose to ignore this
97 if (fseek (fp, imagelen-5, SEEK_CUR))
98 return gpg_error_from_syserror ();
99 return gpg_error (GPG_ERR_TOO_LARGE);
102 image = xtrymalloc (imagelen);
104 return gpg_error_from_syserror ();
106 image[0] = c1; image[1] = c2; image[2] = c3; image[3] = c4; image[4] = type;
107 if (fread (image+5, imagelen-5, 1, fp) != 1)
109 gpg_error_t tmperr = gpg_error_from_syserror ();
114 rc = r_blob? _keybox_new_blob (r_blob, image, imagelen, off) : 0;
121 _keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp)
124 return _keybox_read_blob2 (r_blob, fp, &dummy);
128 /* Write the block to the current file position */
130 _keybox_write_blob (KEYBOXBLOB blob, FILE *fp)
132 const unsigned char *image;
135 image = _keybox_get_blob_image (blob, &length);
137 if (length > IMAGELEN_LIMIT)
138 return gpg_error (GPG_ERR_TOO_LARGE);
140 if (fwrite (image, length, 1, fp) != 1)
141 return gpg_error_from_syserror ();
146 /* Write a fresh header type blob. */
148 _keybox_write_header_blob (FILE *fp, int for_openpgp)
150 unsigned char image[32];
153 memset (image, 0, sizeof image);
154 /* Length of this blob. */
157 image[4] = KEYBOX_BLOBTYPE_HEADER;
158 image[5] = 1; /* Version */
160 image[7] = 0x02; /* OpenPGP data may be available. */
162 memcpy (image+8, "KBXf", 4);
164 /* created_at and last maintenance run. */
165 image[16] = (val >> 24);
166 image[16+1] = (val >> 16);
167 image[16+2] = (val >> 8);
168 image[16+3] = (val );
169 image[20] = (val >> 24);
170 image[20+1] = (val >> 16);
171 image[20+2] = (val >> 8);
172 image[20+3] = (val );
174 if (fwrite (image, 32, 1, fp) != 1)
175 return gpg_error_from_syserror ();