static int test_gzip_header (grub_file_t file) { struct { grub_uint16_t magic; grub_uint8_t method; grub_uint8_t flags; grub_uint32_t timestamp; grub_uint8_t extra_flags; grub_uint8_t os_type; } hdr; grub_uint16_t extra_len; grub_uint32_t orig_len; grub_gzio_t gzio = file->data; if (grub_file_tell (gzio->file) != 0) grub_file_seek (gzio->file, 0); /* * This checks if the file is gzipped. If a problem occurs here * (other than a real error with the disk) then we don't think it * is a compressed file, and simply mark it as such. */ if (grub_file_read (gzio->file, &hdr, 10) != 10 || ((hdr.magic != GZIP_MAGIC) && (hdr.magic != OLD_GZIP_MAGIC))) return 0; /* * This does consistency checking on the header data. If a * problem occurs from here on, then we have corrupt or otherwise * bad data, and the error should be reported to the user. */ if (hdr.method != DEFLATED || (hdr.flags & UNSUPPORTED_FLAGS) || ((hdr.flags & EXTRA_FIELD) && (grub_file_read (gzio->file, &extra_len, 2) != 2 || eat_field (gzio->file, grub_le_to_cpu16 (extra_len)))) || ((hdr.flags & ORIG_NAME) && eat_field (gzio->file, -1)) || ((hdr.flags & COMMENT) && eat_field (gzio->file, -1))) return 0; gzio->data_offset = grub_file_tell (gzio->file); /* FIXME: don't do this on not easily seekable files. */ { grub_file_seek (gzio->file, grub_file_size (gzio->file) - 4); if (grub_file_read (gzio->file, &orig_len, 4) != 4) return 0; /* FIXME: this does not handle files whose original size is over 4GB. But how can we know the real original size? */ file->size = grub_le_to_cpu32 (orig_len); } initialize_tables (gzio); return 1; }
long ftell(FILE *stream) { grub_errno = GRUB_ERR_NONE; if (stream == stdin || stream == stdout || stream == stderr) return 0; return grub_file_tell(stream); }
static int get_byte (grub_file_t file) { grub_gzio_t gzio = file->data; if (grub_file_tell (gzio->file) == (grub_off_t) gzio->data_offset || gzio->inbuf_d == INBUFSIZ) { gzio->inbuf_d = 0; grub_file_read (gzio->file, gzio->inbuf, INBUFSIZ); } return gzio->inbuf[gzio->inbuf_d++]; }
/* Jump to next block and read its header. */ static int jump_block (struct grub_lzopio *lzopio) { /* only jump if block was not decompressed (and read from disk) */ if (!lzopio->block.udata) { grub_off_t off = grub_file_tell (lzopio->file) + lzopio->block.csize; if (grub_file_seek (lzopio->file, off) == ((grub_off_t) - 1)) return -1; } return read_block_header (lzopio); }
static int get_byte (grub_gzio_t gzio) { if (gzio->mem_input) { if (gzio->mem_input_off < gzio->mem_input_size) return gzio->mem_input[gzio->mem_input_off++]; return 0; } if (grub_file_tell (gzio->file) == (grub_off_t) gzio->data_offset || gzio->inbuf_d == INBUFSIZ) { gzio->inbuf_d = 0; grub_file_read (gzio->file, gzio->inbuf, INBUFSIZ); } return gzio->inbuf[gzio->inbuf_d++]; }
static grub_file_t grub_xzio_open (grub_file_t io) { grub_file_t file; grub_xzio_t xzio; file = (grub_file_t) grub_zalloc (sizeof (*file)); if (!file) return 0; xzio = grub_zalloc (sizeof (*xzio)); if (!xzio) { grub_free (file); return 0; } xzio->file = io; xzio->saved_offset = 0; file->device = io->device; file->offset = 0; file->data = xzio; file->read_hook = 0; file->fs = &grub_xzio_fs; file->size = GRUB_FILE_SIZE_UNKNOWN; file->not_easly_seekable = 1; if (grub_file_tell (xzio->file) != 0) grub_file_seek (xzio->file, 0); /* Allocated 64KiB for dictionary. * Decoder will relocate if bigger is needed. */ xzio->dec = xz_dec_init (1 << 16); if (!xzio->dec) { grub_free (file); grub_free (xzio); return 0; } xzio->buf.in = xzio->inbuf; xzio->buf.in_pos = 0; xzio->buf.in_size = 0; xzio->buf.out = xzio->outbuf; xzio->buf.out_pos = 0; xzio->buf.out_size = XZBUFSIZ; /* FIXME: don't test footer on not easily seekable files. */ if (!test_header (file) || !test_footer (file)) { grub_errno = GRUB_ERR_NONE; grub_file_seek (io, 0); xz_dec_end (xzio->dec); grub_free (xzio); grub_free (file); return io; } return file; }
/* Load a font and add it to the beginning of the global font list. Returns 0 upon success, nonzero upon failure. */ grub_font_t grub_font_load (const char *filename) { grub_file_t file = 0; struct font_file_section section; char magic[4]; grub_font_t font = 0; #if FONT_DEBUG >= 1 grub_dprintf ("font", "add_font(%s)\n", filename); #endif if (filename[0] == '(' || filename[0] == '/' || filename[0] == '+') file = grub_buffile_open (filename, 1024); else { const char *prefix = grub_env_get ("prefix"); char *fullname, *ptr; if (!prefix) { grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), "prefix"); goto fail; } fullname = grub_malloc (grub_strlen (prefix) + grub_strlen (filename) + 1 + sizeof ("/fonts/") + sizeof (".pf2")); if (!fullname) goto fail; ptr = grub_stpcpy (fullname, prefix); ptr = grub_stpcpy (ptr, "/fonts/"); ptr = grub_stpcpy (ptr, filename); ptr = grub_stpcpy (ptr, ".pf2"); *ptr = 0; file = grub_buffile_open (fullname, 1024); grub_free (fullname); } if (!file) goto fail; #if FONT_DEBUG >= 3 grub_dprintf ("font", "file opened\n"); #endif /* Read the FILE section. It indicates the file format. */ if (open_section (file, §ion) != 0) goto fail; #if FONT_DEBUG >= 3 grub_dprintf ("font", "opened FILE section\n"); #endif if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_FILE, sizeof (FONT_FORMAT_SECTION_NAMES_FILE) - 1) != 0) { grub_error (GRUB_ERR_BAD_FONT, "font file format error: 1st section must be FILE"); goto fail; } #if FONT_DEBUG >= 3 grub_dprintf ("font", "section name ok\n"); #endif if (section.length != 4) { grub_error (GRUB_ERR_BAD_FONT, "font file format error (file type ID length is %d " "but should be 4)", section.length); goto fail; } #if FONT_DEBUG >= 3 grub_dprintf ("font", "section length ok\n"); #endif /* Check the file format type code. */ if (grub_file_read (file, magic, 4) != 4) goto fail; #if FONT_DEBUG >= 3 grub_dprintf ("font", "read magic ok\n"); #endif if (grub_memcmp (magic, FONT_FORMAT_PFF2_MAGIC, 4) != 0) { grub_error (GRUB_ERR_BAD_FONT, "invalid font magic %x %x %x %x", magic[0], magic[1], magic[2], magic[3]); goto fail; } #if FONT_DEBUG >= 3 grub_dprintf ("font", "compare magic ok\n"); #endif /* Allocate the font object. */ font = (grub_font_t) grub_zalloc (sizeof (struct grub_font)); if (!font) goto fail; font_init (font); font->file = file; #if FONT_DEBUG >= 3 grub_dprintf ("font", "allocate font ok; loading font info\n"); #endif /* Load the font information. */ while (1) { if (open_section (file, §ion) != 0) { if (section.eof) break; /* Done reading the font file. */ else goto fail; } #if FONT_DEBUG >= 2 grub_dprintf ("font", "opened section %c%c%c%c ok\n", section.name[0], section.name[1], section.name[2], section.name[3]); #endif if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_FONT_NAME, sizeof (FONT_FORMAT_SECTION_NAMES_FONT_NAME) - 1) == 0) { font->name = read_section_as_string (§ion); if (!font->name) goto fail; } else if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_POINT_SIZE, sizeof (FONT_FORMAT_SECTION_NAMES_POINT_SIZE) - 1) == 0) { if (read_section_as_short (§ion, &font->point_size) != 0) goto fail; } else if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_WEIGHT, sizeof (FONT_FORMAT_SECTION_NAMES_WEIGHT) - 1) == 0) { char *wt; wt = read_section_as_string (§ion); if (!wt) continue; /* Convert the weight string 'normal' or 'bold' into a number. */ if (grub_strcmp (wt, "normal") == 0) font->weight = FONT_WEIGHT_NORMAL; else if (grub_strcmp (wt, "bold") == 0) font->weight = FONT_WEIGHT_BOLD; grub_free (wt); } else if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_MAX_CHAR_WIDTH, sizeof (FONT_FORMAT_SECTION_NAMES_MAX_CHAR_WIDTH) - 1) == 0) { if (read_section_as_short (§ion, &font->max_char_width) != 0) goto fail; } else if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_MAX_CHAR_HEIGHT, sizeof (FONT_FORMAT_SECTION_NAMES_MAX_CHAR_HEIGHT) - 1) == 0) { if (read_section_as_short (§ion, &font->max_char_height) != 0) goto fail; } else if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_ASCENT, sizeof (FONT_FORMAT_SECTION_NAMES_ASCENT) - 1) == 0) { if (read_section_as_short (§ion, &font->ascent) != 0) goto fail; } else if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_DESCENT, sizeof (FONT_FORMAT_SECTION_NAMES_DESCENT) - 1) == 0) { if (read_section_as_short (§ion, &font->descent) != 0) goto fail; } else if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_CHAR_INDEX, sizeof (FONT_FORMAT_SECTION_NAMES_CHAR_INDEX) - 1) == 0) { if (load_font_index (file, section.length, font) != 0) goto fail; } else if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_DATA, sizeof (FONT_FORMAT_SECTION_NAMES_DATA) - 1) == 0) { /* When the DATA section marker is reached, we stop reading. */ break; } else { /* Unhandled section type, simply skip past it. */ #if FONT_DEBUG >= 3 grub_dprintf ("font", "Unhandled section type, skipping.\n"); #endif grub_off_t section_end = grub_file_tell (file) + section.length; if ((int) grub_file_seek (file, section_end) == -1) goto fail; } } if (!font->name) { grub_dprintf ("font", "Font has no name.\n"); font->name = grub_strdup ("Unknown"); } #if FONT_DEBUG >= 1 grub_dprintf ("font", "Loaded font `%s'.\n" "Ascent=%d Descent=%d MaxW=%d MaxH=%d Number of characters=%d.\n", font->name, font->ascent, font->descent, font->max_char_width, font->max_char_height, font->num_chars); #endif if (font->max_char_width == 0 || font->max_char_height == 0 || font->num_chars == 0 || font->char_index == 0 || font->ascent == 0 || font->descent == 0) { grub_error (GRUB_ERR_BAD_FONT, "invalid font file: missing some required data"); goto fail; } /* Add the font to the global font registry. */ if (register_font (font) != 0) goto fail; return font; fail: if (file) grub_file_close (file); if (font) font->file = 0; free_font (font); return 0; }
static grub_err_t grub_video_reader_tga (struct grub_video_bitmap **bitmap, const char *filename) { grub_file_t file; grub_ssize_t pos; struct grub_tga_header header; int has_alpha; file = grub_buffile_open (filename, 0); if (! file) return grub_errno; /* TGA Specification states that we SHOULD start by reading ID from end of file, but we really don't care about that as we are not going to support developer area & extensions at this point. */ /* Read TGA header from beginning of file. */ if (grub_file_read (file, &header, sizeof (header)) != sizeof (header)) { grub_file_close (file); return grub_errno; } /* Skip ID field. */ pos = grub_file_tell (file); pos += header.id_length; grub_file_seek (file, pos); if (grub_errno != GRUB_ERR_NONE) { grub_file_close (file); return grub_errno; } #if defined(TGA_DEBUG) grub_printf("tga: header\n"); dump_int_field(header.id_length); dump_int_field(header.color_map_type); dump_int_field(header.image_type); dump_int_field(header.color_map_first_index); dump_int_field(header.color_map_length); dump_int_field(header.color_map_bpp); dump_int_field(header.image_x_origin); dump_int_field(header.image_y_origin); dump_int_field(header.image_width); dump_int_field(header.image_height); dump_int_field(header.image_bpp); dump_int_field(header.image_descriptor); #endif /* Check that bitmap encoding is supported. */ switch (header.image_type) { case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_TRUECOLOR: case GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR: break; default: grub_file_close (file); return grub_error (GRUB_ERR_BAD_FILE_TYPE, "unsupported bitmap format (unknown encoding)"); } /* Check that bitmap depth is supported. */ switch (header.image_bpp) { case 24: has_alpha = 0; break; case 32: has_alpha = 1; break; default: grub_file_close (file); return grub_error (GRUB_ERR_BAD_FILE_TYPE, "unsupported bitmap format (bpp=%d)", header.image_bpp); } /* Allocate bitmap. If there is alpha information store it too. */ if (has_alpha) { grub_video_bitmap_create (bitmap, header.image_width, header.image_height, GRUB_VIDEO_BLIT_FORMAT_RGBA_8888); if (grub_errno != GRUB_ERR_NONE) { grub_file_close (file); return grub_errno; } /* Load bitmap data. */ switch (header.image_type) { case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_TRUECOLOR: tga_load_truecolor_R8G8B8A8 (*bitmap, &header, file); break; case GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR: tga_load_truecolor_rle_R8G8B8A8 (*bitmap, &header, file); break; } } else { grub_video_bitmap_create (bitmap, header.image_width, header.image_height, GRUB_VIDEO_BLIT_FORMAT_RGB_888); if (grub_errno != GRUB_ERR_NONE) { grub_file_close (file); return grub_errno; } /* Load bitmap data. */ switch (header.image_type) { case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_TRUECOLOR: tga_load_truecolor_R8G8B8 (*bitmap, &header, file); break; case GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR: tga_load_truecolor_rle_R8G8B8 (*bitmap, &header, file); break; } } /* If there was a loading problem, destroy bitmap. */ if (grub_errno != GRUB_ERR_NONE) { grub_video_bitmap_destroy (*bitmap); *bitmap = 0; } grub_file_close (file); return grub_errno; }
/* Read block header from file, after successful exit file points to * beginning of block data. */ static int read_block_header (struct grub_lzopio *lzopio) { lzopio->saved_off += lzopio->block.usize; /* Free cached block data if any. */ grub_free (lzopio->block.udata); grub_free (lzopio->block.cdata); lzopio->block.udata = NULL; lzopio->block.cdata = NULL; if (grub_file_read (lzopio->file, &lzopio->block.usize, sizeof (lzopio->block.usize)) != sizeof (lzopio->block.usize)) return -1; lzopio->block.usize = grub_be_to_cpu32 (lzopio->block.usize); /* Last block has uncompressed data size == 0 and no other fields. */ if (lzopio->block.usize == 0) { if (grub_file_tell (lzopio->file) == grub_file_size (lzopio->file)) return 0; else return -1; } /* Read compressed data block size. */ if (grub_file_read (lzopio->file, &lzopio->block.csize, sizeof (lzopio->block.csize)) != sizeof (lzopio->block.csize)) return -1; lzopio->block.csize = grub_be_to_cpu32 (lzopio->block.csize); /* Corrupted. */ if (lzopio->block.csize > lzopio->block.usize) return -1; /* Read checksum of uncompressed data. */ if (lzopio->has_ucheck) { if (grub_file_read (lzopio->file, &lzopio->block.ucheck, sizeof (lzopio->block.ucheck)) != sizeof (lzopio->block.ucheck)) return -1; lzopio->block.ucheck = lzopio->block.ucheck; } /* Read checksum of compressed data. */ if (lzopio->has_ccheck) { /* Incompressible data block. */ if (lzopio->block.csize == lzopio->block.usize) { lzopio->block.ccheck = lzopio->block.ucheck; } else { if (grub_file_read (lzopio->file, &lzopio->block.ccheck, sizeof (lzopio->block.ccheck)) != sizeof (lzopio->block.ccheck)) return -1; lzopio->block.ccheck = lzopio->block.ccheck; } } return 0; }
static grub_err_t grub_video_reader_tga (struct grub_video_bitmap **bitmap, const char *filename) { grub_ssize_t pos; struct tga_data data; grub_memset (&data, 0, sizeof (data)); data.file = grub_buffile_open (filename, 0); if (! data.file) return grub_errno; /* TGA Specification states that we SHOULD start by reading ID from end of file, but we really don't care about that as we are not going to support developer area & extensions at this point. */ /* Read TGA header from beginning of file. */ if (grub_file_read (data.file, &data.hdr, sizeof (data.hdr)) != sizeof (data.hdr)) { grub_file_close (data.file); return grub_errno; } /* Skip ID field. */ pos = grub_file_tell (data.file); pos += data.hdr.id_length; grub_file_seek (data.file, pos); if (grub_errno != GRUB_ERR_NONE) { grub_file_close (data.file); return grub_errno; } grub_dprintf("tga", "tga: header\n"); dump_int_field(data.hdr.id_length); dump_int_field(data.hdr.color_map_type); dump_int_field(data.hdr.image_type); dump_int_field(data.hdr.color_map_first_index); dump_int_field(data.hdr.color_map_length); dump_int_field(data.hdr.color_map_bpp); dump_int_field(data.hdr.image_x_origin); dump_int_field(data.hdr.image_y_origin); dump_int_field(data.hdr.image_width); dump_int_field(data.hdr.image_height); dump_int_field(data.hdr.image_bpp); dump_int_field(data.hdr.image_descriptor); data.image_width = grub_le_to_cpu16 (data.hdr.image_width); data.image_height = grub_le_to_cpu16 (data.hdr.image_height); /* Check that bitmap encoding is supported. */ switch (data.hdr.image_type) { case GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR: case GRUB_TGA_IMAGE_TYPE_RLE_BLACK_AND_WHITE: case GRUB_TGA_IMAGE_TYPE_RLE_INDEXCOLOR: data.uses_rle = 1; break; case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_TRUECOLOR: case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_BLACK_AND_WHITE: case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_INDEXCOLOR: data.uses_rle = 0; break; default: grub_file_close (data.file); return grub_error (GRUB_ERR_BAD_FILE_TYPE, "unsupported bitmap format (unknown encoding %d)", data.hdr.image_type); } data.bpp = data.hdr.image_bpp / 8; /* Check that bitmap depth is supported. */ switch (data.hdr.image_type) { case GRUB_TGA_IMAGE_TYPE_RLE_BLACK_AND_WHITE: case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_BLACK_AND_WHITE: if (data.hdr.image_bpp != 8) { grub_file_close (data.file); return grub_error (GRUB_ERR_BAD_FILE_TYPE, "unsupported bitmap format (bpp=%d)", data.hdr.image_bpp); } grub_video_bitmap_create (bitmap, data.image_width, data.image_height, GRUB_VIDEO_BLIT_FORMAT_RGB_888); if (grub_errno != GRUB_ERR_NONE) { grub_file_close (data.file); return grub_errno; } data.bitmap = *bitmap; /* Load bitmap data. */ tga_load_grayscale (&data); break; case GRUB_TGA_IMAGE_TYPE_RLE_INDEXCOLOR: case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_INDEXCOLOR: if (data.hdr.image_bpp != 8 || data.hdr.color_map_bpp != 24 || data.hdr.color_map_first_index != 0) { grub_file_close (data.file); return grub_error (GRUB_ERR_BAD_FILE_TYPE, "unsupported bitmap format (bpp=%d)", data.hdr.image_bpp); } grub_video_bitmap_create (bitmap, data.image_width, data.image_height, GRUB_VIDEO_BLIT_FORMAT_RGB_888); if (grub_errno != GRUB_ERR_NONE) { grub_file_close (data.file); return grub_errno; } data.bitmap = *bitmap; /* Load bitmap data. */ tga_load_palette (&data); tga_load_index_color (&data); break; case GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR: case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_TRUECOLOR: switch (data.hdr.image_bpp) { case 24: grub_video_bitmap_create (bitmap, data.image_width, data.image_height, GRUB_VIDEO_BLIT_FORMAT_RGB_888); if (grub_errno != GRUB_ERR_NONE) { grub_file_close (data.file); return grub_errno; } data.bitmap = *bitmap; /* Load bitmap data. */ tga_load_truecolor_R8G8B8 (&data); break; case 32: grub_video_bitmap_create (bitmap, data.image_width, data.image_height, GRUB_VIDEO_BLIT_FORMAT_RGBA_8888); if (grub_errno != GRUB_ERR_NONE) { grub_file_close (data.file); return grub_errno; } data.bitmap = *bitmap; /* Load bitmap data. */ tga_load_truecolor_R8G8B8A8 (&data); break; default: grub_file_close (data.file); return grub_error (GRUB_ERR_BAD_FILE_TYPE, "unsupported bitmap format (bpp=%d)", data.hdr.image_bpp); } } /* If there was a loading problem, destroy bitmap. */ if (grub_errno != GRUB_ERR_NONE) { grub_video_bitmap_destroy (*bitmap); *bitmap = 0; } grub_file_close (data.file); return grub_errno; }