/* -*- C -*- * Copyright (c) 1998-2006 Motoyuki Kasahara * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "ebzip.h" #include "ebutils.h" #include "getumask.h" #include "makedir.h" #include "strlist.h" /* * Unexported function. */ static int ebzip_zip_book_eb(EB_Book *book, const char *out_top_path, const char *book_path, EB_Subbook_Code *subbook_list, int subbook_count); static int ebzip_zip_book_epwing(EB_Book *book, const char *out_top_path, const char *book_path, EB_Subbook_Code *subbook_list, int subbook_count); /* * Compress files in `book' and output them under `out_top_path'. * If it succeeds, 0 is returned. Otherwise -1 is returned. */ int ebzip_zip_book(const char *out_top_path, const char *book_path, char subbook_name_list[][EB_MAX_DIRECTORY_NAME_LENGTH + 1], int subbook_name_count) { EB_Book book; EB_Error_Code error_code; EB_Subbook_Code subbook_list[EB_MAX_SUBBOOKS]; EB_Subbook_Code subbook_code; int subbook_count; int result; int i; eb_initialize_book(&book); /* * Bind a book. */ error_code = eb_bind(&book, book_path); if (error_code != EB_SUCCESS) { fprintf(stderr, "%s: %s\n", invoked_name, eb_error_message(error_code)); fflush(stderr); return -1; } /* * For each targe subbook, convert a subbook-names to a subbook-codes. * If no subbook is specified by `--subbook'(`-S'), set all subbooks * as the target. */ if (subbook_name_count == 0) { error_code = eb_subbook_list(&book, subbook_list, &subbook_count); if (error_code != EB_SUCCESS) { fprintf(stderr, "%s: %s\n", invoked_name, eb_error_message(error_code)); fflush(stderr); return -1; } } else { subbook_count = 0; for (i = 0; i < subbook_name_count; i++) { error_code = find_subbook(&book, subbook_name_list[i], &subbook_code); if (error_code != EB_SUCCESS) { fprintf(stderr, _("%s: unknown subbook name `%s'\n"), invoked_name, subbook_name_list[i]); return -1; } subbook_list[subbook_count++] = subbook_code; } } /* * Compress the book. */ if (book.disc_code == EB_DISC_EB) { result = ebzip_zip_book_eb(&book, out_top_path, book_path, subbook_list, subbook_count); } else { result = ebzip_zip_book_epwing(&book, out_top_path, book_path, subbook_list, subbook_count); } eb_finalize_book(&book); return result; } /* * Internal function for `zip_book'. * This is used to compress an EB book. */ static int ebzip_zip_book_eb(EB_Book *book, const char *out_top_path, const char *book_path, EB_Subbook_Code *subbook_list, int subbook_count) { EB_Subbook *subbook; EB_Error_Code error_code; String_List string_list; char in_path_name[PATH_MAX + 1]; char out_sub_path[PATH_MAX + 1]; char out_path_name[PATH_MAX + 1]; char catalog_file_name[EB_MAX_FILE_NAME_LENGTH]; char language_file_name[EB_MAX_FILE_NAME_LENGTH]; mode_t out_directory_mode; Zip_Speedup speedup; Zio_Code in_zio_code; int i; /* * If `out_top_path' and/or `book_path' represents "/", replace it * to an empty string. */ if (strcmp(out_top_path, "/") == 0) out_top_path++; if (strcmp(book_path, "/") == 0) book_path++; /* * Initialize variables. */ out_directory_mode = 0777 ^ get_umask(); string_list_initialize(&string_list); error_code = eb_load_all_subbooks(book); if (error_code != EB_SUCCESS) { fprintf(stderr, "%s: %s\n", invoked_name, eb_error_message(error_code)); } /* * Compress a book. */ for (i = 0; i < subbook_count; i++) { subbook = book->subbooks + subbook_list[i]; /* * Make an output directory for the current subbook. */ eb_compose_path_name(out_top_path, subbook->directory_name, out_sub_path); if (!ebzip_test_flag && make_missing_directory(out_sub_path, out_directory_mode) < 0) { fprintf(stderr, _("%s: failed to create a directory, %s: %s\n"), invoked_name, strerror(errno), out_sub_path); goto failed; } /* * Compress START file. */ in_zio_code = zio_mode(&subbook->text_zio); eb_compose_path_name2(book->path, subbook->directory_name, subbook->text_file_name, in_path_name); eb_compose_path_name2(out_top_path, subbook->directory_name, subbook->text_file_name, out_path_name); eb_fix_path_name_suffix(out_path_name, EBZIP_SUFFIX_EBZ); if (in_zio_code != ZIO_INVALID && !string_list_find(&string_list, in_path_name)) { ebzip_initialize_zip_speedup(&speedup); if (ebzip_set_zip_speedup(&speedup, in_path_name, in_zio_code, subbook->index_page) < 0) goto failed; if (ebzip_zip_start_file(out_path_name, in_path_name, in_zio_code, subbook->index_page, &speedup) < 0) goto failed; ebzip_finalize_zip_speedup(&speedup); string_list_add(&string_list, in_path_name); } } /* * Compress a language file. */ if (eb_find_file_name(book->path, "language", language_file_name) == EB_SUCCESS) { eb_compose_path_name(book->path, language_file_name, in_path_name); eb_compose_path_name(out_top_path, language_file_name, out_path_name); eb_path_name_zio_code(in_path_name, ZIO_PLAIN, &in_zio_code); eb_fix_path_name_suffix(out_path_name, EBZIP_SUFFIX_EBZ); if (ebzip_zip_file(out_path_name, in_path_name, in_zio_code, NULL) < 0) goto failed; } /* * Copy CATALOG file. */ if (eb_find_file_name(book->path, "catalog", catalog_file_name) == EB_SUCCESS) { eb_compose_path_name(book->path, catalog_file_name, in_path_name); eb_compose_path_name(out_top_path, catalog_file_name, out_path_name); eb_path_name_zio_code(in_path_name, ZIO_PLAIN, &in_zio_code); if (ebzip_copy_file(out_path_name, in_path_name) < 0) goto failed; } string_list_finalize(&string_list); return 0; /* * An error occurs... */ failed: string_list_finalize(&string_list); return -1; } /* * Internal function for `zip_book'. * This is used to compress an EPWING book. */ static int ebzip_zip_book_epwing(EB_Book *book, const char *out_top_path, const char *book_path, EB_Subbook_Code *subbook_list, int subbook_count) { EB_Subbook *subbook; EB_Error_Code error_code; EB_Font *font; String_List string_list; char in_path_name[PATH_MAX + 1]; char out_sub_path[PATH_MAX + 1]; char out_path_name[PATH_MAX + 1]; char catalogs_file_name[EB_MAX_FILE_NAME_LENGTH]; mode_t out_directory_mode; Zip_Speedup speedup; Zio_Code in_zio_code; int i, j; /* * If `out_top_path' and/or `book_path' represents "/", replace it * to an empty string. */ if (strcmp(out_top_path, "/") == 0) out_top_path++; if (strcmp(book_path, "/") == 0) book_path++; /* * Initialize variables. */ out_directory_mode = 0777 ^ get_umask(); string_list_initialize(&string_list); error_code = eb_load_all_subbooks(book); if (error_code != EB_SUCCESS) { fprintf(stderr, "%s: %s\n", invoked_name, eb_error_message(error_code)); } /* * Compress a book. */ for (i = 0; i < subbook_count; i++) { subbook = book->subbooks + subbook_list[i]; /* * Make an output directory for the current subbook. */ eb_compose_path_name(out_top_path, subbook->directory_name, out_sub_path); if (!ebzip_test_flag && make_missing_directory(out_sub_path, out_directory_mode) < 0) { fprintf(stderr, _("%s: failed to create a directory, %s: %s\n"), invoked_name, strerror(errno), out_sub_path); goto failed; } /* * Make `data' sub directory for the current subbook. */ eb_compose_path_name2(out_top_path, subbook->directory_name, subbook->data_directory_name, out_sub_path); if (!ebzip_test_flag && make_missing_directory(out_sub_path, out_directory_mode) < 0) { fprintf(stderr, _("%s: failed to create a directory, %s: %s\n"), invoked_name, strerror(errno), out_sub_path); goto failed; } /* * Compress HONMON/HONMON2 file. */ in_zio_code = zio_mode(&subbook->text_zio); eb_compose_path_name3(book->path, subbook->directory_name, subbook->data_directory_name, subbook->text_file_name, in_path_name); eb_compose_path_name3(out_top_path, subbook->directory_name, subbook->data_directory_name, subbook->text_file_name, out_path_name); eb_fix_path_name_suffix(out_path_name, EBZIP_SUFFIX_EBZ); if (in_zio_code != ZIO_INVALID && !string_list_find(&string_list, in_path_name)) { ebzip_initialize_zip_speedup(&speedup); if (ebzip_set_zip_speedup(&speedup, in_path_name, in_zio_code, subbook->index_page) < 0) goto failed; if (ebzip_zip_file(out_path_name, in_path_name, in_zio_code, &speedup) < 0) goto failed; ebzip_finalize_zip_speedup(&speedup); string_list_add(&string_list, in_path_name); } /* * Compress HONMONS file. */ in_zio_code = zio_mode(&subbook->sound_zio); eb_compose_path_name3(book->path, subbook->directory_name, subbook->data_directory_name, subbook->sound_file_name, in_path_name); eb_compose_path_name3(out_top_path, subbook->directory_name, subbook->data_directory_name, subbook->sound_file_name, out_path_name); eb_fix_path_name_suffix(out_path_name, EBZIP_SUFFIX_EBZ); if (!ebzip_skip_flag_sound && in_zio_code != ZIO_INVALID && !string_list_find(&string_list, in_path_name)) { if (ebzip_zip_file(out_path_name, in_path_name, in_zio_code, NULL) < 0) goto failed; string_list_add(&string_list, in_path_name); } /* * Copy HONMONG file. */ in_zio_code = zio_mode(&subbook->graphic_zio); eb_compose_path_name3(book->path, subbook->directory_name, subbook->data_directory_name, subbook->graphic_file_name, in_path_name); eb_compose_path_name3(out_top_path, subbook->directory_name, subbook->data_directory_name, subbook->graphic_file_name, out_path_name); if (!ebzip_skip_flag_graphic && in_zio_code != ZIO_INVALID && !string_list_find(&string_list, in_path_name)) { if (ebzip_copy_file(out_path_name, in_path_name) < 0) goto failed; string_list_add(&string_list, in_path_name); } if (!ebzip_skip_flag_font) { /* * Make `gaiji' sub directory for the current subbook. */ eb_compose_path_name2(out_top_path, subbook->directory_name, subbook->gaiji_directory_name, out_sub_path); if (!ebzip_test_flag && make_missing_directory(out_sub_path, out_directory_mode) < 0) { fprintf(stderr, _("%s: failed to create a directory, %s: %s\n"), invoked_name, strerror(errno), out_sub_path); goto failed; } /* * Compress narrow font files. */ for (j = 0; j < EB_MAX_FONTS; j++) { font = subbook->narrow_fonts + j; if (font->font_code == EB_FONT_INVALID) continue; in_zio_code = zio_mode(&font->zio); eb_compose_path_name3(book->path, subbook->directory_name, subbook->gaiji_directory_name, font->file_name, in_path_name); eb_compose_path_name3(out_top_path, subbook->directory_name, subbook->gaiji_directory_name, font->file_name, out_path_name); eb_fix_path_name_suffix(out_path_name, EBZIP_SUFFIX_EBZ); if (in_zio_code != ZIO_INVALID && !string_list_find(&string_list, in_path_name)) { if (ebzip_zip_file(out_path_name, in_path_name, in_zio_code, NULL) < 0) goto failed; string_list_add(&string_list, in_path_name); } } /* * Compress wide font files. */ for (j = 0; j < EB_MAX_FONTS; j++) { font = subbook->wide_fonts + j; if (font->font_code == EB_FONT_INVALID) continue; in_zio_code = zio_mode(&font->zio); eb_compose_path_name3(book->path, subbook->directory_name, subbook->gaiji_directory_name, font->file_name, in_path_name); eb_compose_path_name3(out_top_path, subbook->directory_name, subbook->gaiji_directory_name, font->file_name, out_path_name); eb_fix_path_name_suffix(out_path_name, EBZIP_SUFFIX_EBZ); if (in_zio_code != ZIO_INVALID && !string_list_find(&string_list, in_path_name)) { if (ebzip_zip_file(out_path_name, in_path_name, in_zio_code, NULL) < 0) goto failed; string_list_add(&string_list, in_path_name); } } } /* * Copy movie files. */ if (!ebzip_skip_flag_movie) { eb_compose_path_name2(book->path, subbook->directory_name, subbook->movie_directory_name, in_path_name); eb_compose_path_name2(out_top_path, subbook->directory_name, subbook->movie_directory_name, out_path_name); if (ebzip_copy_files_in_directory(out_path_name, in_path_name) < 0) goto failed; } } /* * Copy CATALOGS file. */ if (eb_find_file_name(book->path, "catalogs", catalogs_file_name) == EB_SUCCESS) { eb_compose_path_name(book->path, catalogs_file_name, in_path_name); eb_compose_path_name(out_top_path, catalogs_file_name, out_path_name); if (ebzip_copy_file(out_path_name, in_path_name) < 0) goto failed; } string_list_finalize(&string_list); return 0; /* * An error occurs... */ failed: string_list_finalize(&string_list); return -1; }