static char * grub_gettext_getstr_from_position (struct grub_gettext_context *ctx, grub_off_t off, grub_size_t position) { grub_off_t internal_position; grub_size_t length; grub_off_t offset; char *translation; struct string_descriptor desc; grub_err_t err; internal_position = (off + position * sizeof (desc)); err = grub_gettext_pread (ctx->fd_mo, (char *) &desc, sizeof (desc), internal_position); if (err) return NULL; length = grub_cpu_to_le32 (desc.length); offset = grub_cpu_to_le32 (desc.offset); translation = grub_malloc (length + 1); if (!translation) return NULL; err = grub_gettext_pread (ctx->fd_mo, translation, length, offset); if (err) { grub_free (translation); return NULL; } translation[length] = '\0'; return translation; }
static void grub_gettext_getstring_from_offset (grub_uint32_t offset, grub_uint32_t length, char *translation) { grub_gettext_pread (fd_mo, translation, length, offset); translation[length] = '\0'; }
/* This is similar to grub_file_open. */ static grub_err_t grub_mofile_open (struct grub_gettext_context *ctx, const char *filename) { struct header head; grub_err_t err; grub_file_t fd; /* Using fd_mo and not another variable because it's needed for grub_gettext_get_info. */ fd = grub_file_open (filename); if (!fd) return grub_errno; err = grub_gettext_pread (fd, &head, sizeof (head), 0); if (err) { grub_file_close (fd); return err; } if (head.magic != grub_cpu_to_le32_compile_time (MO_MAGIC_NUMBER)) { grub_file_close (fd); return grub_error (GRUB_ERR_BAD_FILE_TYPE, "mo: invalid mo magic in file: %s", filename); } if (head.version != 0) { grub_file_close (fd); return grub_error (GRUB_ERR_BAD_FILE_TYPE, "mo: invalid mo version in file: %s", filename); } ctx->grub_gettext_offset_original = grub_le_to_cpu32 (head.offset_original); ctx->grub_gettext_offset_translation = grub_le_to_cpu32 (head.offset_translation); ctx->grub_gettext_max = grub_le_to_cpu32 (head.number_of_strings); for (ctx->grub_gettext_max_log = 0; ctx->grub_gettext_max >> ctx->grub_gettext_max_log; ctx->grub_gettext_max_log++); ctx->grub_gettext_msg_list = grub_zalloc (ctx->grub_gettext_max * sizeof (ctx->grub_gettext_msg_list[0])); if (!ctx->grub_gettext_msg_list) { grub_file_close (fd); return grub_errno; } ctx->fd_mo = fd; if (grub_gettext != grub_gettext_translate) { grub_gettext_original = grub_gettext; grub_gettext = grub_gettext_translate; } return 0; }
static grub_uint32_t grub_gettext_get_info (int offset) { grub_uint32_t value; grub_gettext_pread (fd_mo, (char *) &value, 4, offset); value = grub_cpu_to_le32 (value); return value; }
static char * grub_gettext_getstring_from_position (int position) { int internal_position; int length, offset; char *original; /* Get position for string i. */ internal_position = grub_gettext_offsetoriginal + (position * 8); /* Get the length of the string i. */ grub_gettext_pread (fd_mo, (char *) &length, 4, internal_position); /* Get the offset of the string i. */ grub_gettext_pread (fd_mo, (char *) &offset, 4, internal_position + 4); /* Get the string i. */ original = grub_malloc (length + 1); grub_gettext_getstring_from_offset (offset, length, original); return original; }
static const char * grub_gettext_gettranslation_from_position (int position) { int offsettranslation; int internal_position; grub_uint32_t length, offset; char *translation; offsettranslation = grub_gettext_get_info (GETTEXT_OFFSET_TRANSLATION); internal_position = offsettranslation + position * 8; grub_gettext_pread (fd_mo, (char *) &length, 4, internal_position); length = grub_cpu_to_le32 (length); grub_gettext_pread (fd_mo, (char *) &offset, 4, internal_position + 4); offset = grub_cpu_to_le32 (offset); translation = grub_malloc (length + 1); grub_gettext_getstring_from_offset (offset, length, translation); return translation; }