int guestfs__launch (guestfs_h *g) { /* Configured? */ if (g->state != CONFIG) { error (g, _("the libguestfs handle has already been launched")); return -1; } /* Start the clock ... */ gettimeofday (&g->launch_t, NULL); TRACE0 (launch_start); /* Make the temporary directory. */ if (guestfs___lazy_make_tmpdir (g) == -1) return -1; /* Allow anyone to read the temporary directory. The socket in this * directory won't be readable but anyone can see it exists if they * want. (RHBZ#610880). */ if (chmod (g->tmpdir, 0755) == -1) warning (g, "chmod: %s: %m (ignored)", g->tmpdir); /* Some common debugging information. */ if (g->verbose) { CLEANUP_FREE_VERSION struct guestfs_version *v = guestfs_version (g); struct backend *b; CLEANUP_FREE char *backend = guestfs_get_backend (g); debug (g, "launch: program=%s", g->program); debug (g, "launch: version=%"PRIi64".%"PRIi64".%"PRIi64"%s", v->major, v->minor, v->release, v->extra); for (b = backends; b != NULL; b = b->next) debug (g, "launch: backend registered: %s", b->name); debug (g, "launch: backend=%s", backend); debug (g, "launch: tmpdir=%s", g->tmpdir); debug (g, "launch: umask=0%03o", get_umask (g)); debug (g, "launch: euid=%d", geteuid ()); } /* Launch the appliance. */ if (g->backend_ops->launch (g, g->backend_data, g->backend_arg) == -1) return -1; /* If network is enabled, upload /etc/resolv.conf from the host so * the guest will know how to reach the nameservers. */ if (g->enable_network && access ("/etc/resolv.conf", F_OK) == 0) { guestfs_internal_upload (g, "/etc/resolv.conf", "/etc/resolv.conf", 0644); } return 0; }
void procstat_cred(struct procstat *procstat, struct kinfo_proc *kipp) { unsigned int i, ngroups; gid_t *groups; if ((procstat_opts & PS_OPT_NOHEADER) == 0) xo_emit("{T:/%5s %-16s %5s %5s %5s %5s %5s %5s %5s %5s %-15s}\n", "PID", "COMM", "EUID", "RUID", "SVUID", "EGID", "RGID", "SVGID", "UMASK", "FLAGS", "GROUPS"); xo_emit("{k:process_id/%5d/%d} ", kipp->ki_pid); xo_emit("{:command/%-16s/%s} ", kipp->ki_comm); xo_emit("{:uid/%5d} ", kipp->ki_uid); xo_emit("{:ruid/%5d} ", kipp->ki_ruid); xo_emit("{:svuid/%5d} ", kipp->ki_svuid); xo_emit("{:group/%5d} ", kipp->ki_groups[0]); xo_emit("{:rgid/%5d} ", kipp->ki_rgid); xo_emit("{:svgid/%5d} ", kipp->ki_svgid); xo_emit("{:umask/%5s} ", get_umask(procstat, kipp)); xo_emit("{:cr_flags/%s}", kipp->ki_cr_flags & CRED_FLAG_CAPMODE ? "C" : "-"); xo_emit("{P: }"); groups = NULL; /* * We may have too many groups to fit in kinfo_proc's statically * sized storage. If that occurs, attempt to retrieve them using * libprocstat. */ if (kipp->ki_cr_flags & KI_CRF_GRP_OVERFLOW) groups = procstat_getgroups(procstat, kipp, &ngroups); if (groups == NULL) { ngroups = kipp->ki_ngroups; groups = kipp->ki_groups; } xo_open_list("groups"); for (i = 0; i < ngroups; i++) xo_emit("{D:/%s}{l:groups/%d}", (i > 0) ? "," : "", groups[i]); if (groups != kipp->ki_groups) procstat_freegroups(procstat, groups); xo_close_list("groups"); xo_emit("\n"); }
void procstat_cred(struct procstat *procstat, struct kinfo_proc *kipp) { unsigned int i, ngroups; gid_t *groups; if (!hflag) printf("%5s %-16s %5s %5s %5s %5s %5s %5s %5s %5s %-15s\n", "PID", "COMM", "EUID", "RUID", "SVUID", "EGID", "RGID", "SVGID", "UMASK", "FLAGS", "GROUPS"); printf("%5d ", kipp->ki_pid); printf("%-16s ", kipp->ki_comm); printf("%5d ", kipp->ki_uid); printf("%5d ", kipp->ki_ruid); printf("%5d ", kipp->ki_svuid); printf("%5d ", kipp->ki_groups[0]); printf("%5d ", kipp->ki_rgid); printf("%5d ", kipp->ki_svgid); printf("%5s ", get_umask(procstat, kipp)); printf("%s", kipp->ki_cr_flags & CRED_FLAG_CAPMODE ? "C" : "-"); printf(" "); groups = NULL; /* * We may have too many groups to fit in kinfo_proc's statically * sized storage. If that occurs, attempt to retrieve them using * libprocstat. */ if (kipp->ki_cr_flags & KI_CRF_GRP_OVERFLOW) groups = procstat_getgroups(procstat, kipp, &ngroups); if (groups == NULL) { ngroups = kipp->ki_ngroups; groups = kipp->ki_groups; } for (i = 0; i < ngroups; i++) printf("%s%d", (i > 0) ? "," : "", groups[i]); if (groups != kipp->ki_groups) procstat_freegroups(procstat, groups); printf("\n"); }
env_var_t env_get_string(const wcstring &key, env_mode_flags_t mode) { const bool has_scope = mode & (ENV_LOCAL | ENV_GLOBAL | ENV_UNIVERSAL); const bool search_local = !has_scope || (mode & ENV_LOCAL); const bool search_global = !has_scope || (mode & ENV_GLOBAL); const bool search_universal = !has_scope || (mode & ENV_UNIVERSAL); const bool search_exported = (mode & ENV_EXPORT) || !(mode & ENV_UNEXPORT); const bool search_unexported = (mode & ENV_UNEXPORT) || !(mode & ENV_EXPORT); /* Make the assumption that electric keys can't be shadowed elsewhere, since we currently block that in env_set() */ if (is_electric(key)) { if (!search_global) return env_var_t::missing_var(); /* Big hack...we only allow getting the history on the main thread. Note that history_t may ask for an environment variable, so don't take the lock here (we don't need it) */ if (key == L"history" && is_main_thread()) { env_var_t result; history_t *history = reader_get_history(); if (! history) { history = &history_t::history_with_name(L"fish"); } if (history) history->get_string_representation(&result, ARRAY_SEP_STR); return result; } else if (key == L"COLUMNS") { return to_string(common_get_width()); } else if (key == L"LINES") { return to_string(common_get_height()); } else if (key == L"status") { return to_string(proc_get_last_status()); } else if (key == L"umask") { return format_string(L"0%0.3o", get_umask()); } // we should never get here unless the electric var list is out of sync } if (search_local || search_global) { /* Lock around a local region */ scoped_lock lock(env_lock); env_node_t *env = search_local ? top : global_env; while (env != NULL) { const var_entry_t *entry = env->find_entry(key); if (entry != NULL && (entry->exportv ? search_exported : search_unexported)) { if (entry->val == ENV_NULL) { return env_var_t::missing_var(); } else { return entry->val; } } if (has_scope) { if (!search_global || env == global_env) break; env = global_env; } else { env = env->next_scope_to_search(); } } } if (!search_universal) return env_var_t::missing_var(); /* Another big hack - only do a universal barrier on the main thread (since it can change variable values) Make sure we do this outside the env_lock because it may itself call env_get_string */ if (is_main_thread() && ! get_proc_had_barrier()) { set_proc_had_barrier(true); env_universal_barrier(); } if (uvars()) { env_var_t env_var = uvars()->get(key); if (env_var == ENV_NULL || !(uvars()->get_export(key) ? search_exported : search_unexported)) { env_var = env_var_t::missing_var(); } return env_var; } return env_var_t::missing_var(); }
env_var_t env_get_string(const wcstring &key) { /* Big hack...we only allow getting the history on the main thread. Note that history_t may ask for an environment variable, so don't take the lock here (we don't need it) */ const bool is_main = is_main_thread(); if (key == L"history" && is_main) { env_var_t result; history_t *history = reader_get_history(); if (! history) { history = &history_t::history_with_name(L"fish"); } if (history) history->get_string_representation(result, ARRAY_SEP_STR); return result; } else if (key == L"COLUMNS") { return to_string(common_get_width()); } else if (key == L"LINES") { return to_string(common_get_height()); } else if (key == L"status") { return to_string(proc_get_last_status()); } else if (key == L"umask") { return format_string(L"0%0.3o", get_umask()); } else { { /* Lock around a local region */ scoped_lock lock(env_lock); env_node_t *env = top; wcstring result; while (env != NULL) { const var_entry_t *entry = env->find_entry(key); if (entry != NULL) { if (entry->val == ENV_NULL) { return env_var_t::missing_var(); } else { return entry->val; } } env = env->next_scope_to_search(); } } /* Another big hack - only do a universal barrier on the main thread (since it can change variable values) Make sure we do this outside the env_lock because it may itself call env_get_string */ if (is_main && ! get_proc_had_barrier()) { set_proc_had_barrier(true); env_universal_barrier(); } const wchar_t *item = env_universal_get(key); if (!item || (wcscmp(item, ENV_NULL)==0)) { return env_var_t::missing_var(); } else { return item; } } }
/* * Internal function for `unzip_book'. * This is used to compress an EPWING book. */ static int ebzip_unzip_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; 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)); } /* * Uncompress 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; } /* * Uncompress 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); if (in_zio_code != ZIO_INVALID && !string_list_find(&string_list, in_path_name)) { if (strncasecmp(subbook->text_file_name, "honmon2", 7) == 0) eb_fix_path_name_suffix(out_path_name, EBZIP_SUFFIX_ORG); else eb_fix_path_name_suffix(out_path_name, EBZIP_SUFFIX_NONE); if (ebzip_unzip_file(out_path_name, in_path_name, in_zio_code) < 0) goto failed; string_list_add(&string_list, in_path_name); } /* * Uncompress 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_NONE); if (!ebzip_skip_flag_sound && in_zio_code != ZIO_INVALID && !string_list_find(&string_list, in_path_name)) { if (ebzip_unzip_file(out_path_name, in_path_name, in_zio_code) < 0) goto failed; string_list_add(&string_list, in_path_name); } /* * Uncompress 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); eb_fix_path_name_suffix(out_path_name, EBZIP_SUFFIX_NONE); if (!ebzip_skip_flag_graphic && in_zio_code != ZIO_INVALID && !string_list_find(&string_list, in_path_name)) { if (ebzip_unzip_file(out_path_name, in_path_name, in_zio_code) < 0) goto failed; string_list_add(&string_list, in_path_name); } /* * Make `gaiji' sub directory for the current subbook. */ if (!ebzip_skip_flag_font) { 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; } /* * Uncompress 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_NONE); if (in_zio_code != ZIO_INVALID && !string_list_find(&string_list, in_path_name)) { if (ebzip_unzip_file(out_path_name, in_path_name, in_zio_code) < 0) goto failed; string_list_add(&string_list, in_path_name); } } /* * Uncompress 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_NONE); if (in_zio_code != ZIO_INVALID && !string_list_find(&string_list, in_path_name)) { if (ebzip_unzip_file(out_path_name, in_path_name, in_zio_code) < 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; }
/* * Internal function for `unzip_book'. * This is used to compress an EB book. */ static int ebzip_unzip_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; 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)); } /* * Uncompress 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; } /* * Uncompress 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_NONE); if (in_zio_code != ZIO_INVALID && !string_list_find(&string_list, in_path_name)) { if (ebzip_unzip_start_file(out_path_name, in_path_name, in_zio_code, subbook->index_page) < 0) goto failed; } if (!ebzip_test_flag && rewrite_sebxa_start(out_path_name, subbook->index_page) < 0) goto failed; string_list_add(&string_list, in_path_name); } /* * Uncompress 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_NONE); if (ebzip_unzip_file(out_path_name, in_path_name, in_zio_code) < 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); 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; }
int main( int argc, char** argv ) { // parse options int c; uint64_t nid = 0; int portnum = -1; time_t timeout = -1; uint32_t flags = 0; char* file_path = NULL; char* stdin_path = NULL; char* stdout_path = NULL; char* stderr_path = NULL; char* cmd_str = NULL; char* hostname = NULL; uint64_t gpid = 0; while((c = getopt(argc, argv, "h:dt:f:g:c:i:o:e:")) != -1) { switch( c ) { case 'h': { // is there a hostname given? hostname = strdup( optarg ); char* tmp = strchr(hostname, ':'); if( tmp != NULL ) { *tmp = 0; char* tmp2; portnum = strtol(tmp + 1, &tmp2, 10 ); if( tmp2 == tmp + 1 ) { free( hostname ); usage( argv[0] ); } } nid = wish_host_nid( hostname ); break; } case 'd': { flags |= JOB_DETACHED; break; } case 'f' : { if( cmd_str ) usage( argv[0] ); file_path = realpath( optarg, NULL ); flags |= JOB_USE_FILE; break; } case 't': { int cnt = sscanf( optarg, "%ld", &timeout ); if( cnt != 1 ) usage(argv[0]); break; } case 'g': { int cnt = sscanf( optarg, "%lu", &gpid ); if( cnt != 1 ) usage(argv[0]); break; } case 'c': { if( file_path ) usage( argv[0] ); cmd_str = optarg; break; } case 'i': { stdin_path = optarg; break; } case 'o': { stdout_path = optarg; break; } case 'e': { stderr_path = optarg; break; } default: { usage( argv[0] ); } } } if( optind != argc - 1 ) { usage( argv[0] ); } // no hostname given? then check the environment variables if( hostname == NULL ) { hostname = getenv( WISH_ORIGIN_ENV ); if( hostname == NULL ) { hostname = (char*)"localhost"; } else { char* portnum_str = getenv( WISH_PORTNUM_ENV ); if( portnum_str ) { char* tmp; long port_candidate = strtol(portnum_str, &tmp, 10 ); if( tmp != portnum_str ) { portnum = port_candidate; } } } } if( cmd_str == NULL && file_path == NULL ) { usage( argv[0] ); } nid = wish_host_nid( argv[argc - 1] ); // read the config file struct wish_conf conf; int rc = wish_read_conf( WISH_DEFAULT_CONFIG, &conf ); if( rc != 0 ) { fprintf(stderr, "Config file %s could not be read\n", WISH_DEFAULT_CONFIG ); exit(1); } // set portnum if( conf.portnum > 0 && portnum < 0 ) portnum = conf.portnum; // formulate the packet if( !file_path ) { cmd_str = cmd_str; } else { cmd_str = file_path; } // connect to daemon struct wish_connection con; rc = wish_connect( NULL, &con, hostname, portnum ); if( rc != 0 ) { // could not connect fprintf(stderr, "Could not connect to daemon on %s:%d, rc = %d\n", hostname, portnum, rc); exit(1); } struct wish_packet pkt; struct wish_job_packet jpkt; wish_init_job_packet_client( NULL, &jpkt, gpid, nid, 1, cmd_str, stdin_path, stdout_path, stderr_path, getuid(), getgid(), get_umask(), flags, timeout ); wish_pack_job_packet( NULL, &pkt, &jpkt ); // send of the job request rc = wish_write_packet( NULL, &con, &pkt ); if( rc != 0 ) { // could not write fprintf(stderr, "Could not send to daemon on %s:%d, rc = %d\n", hostname, portnum, rc); exit(1); } // wait for a reply that this job has started wish_free_packet( &pkt ); rc = wish_read_packet( NULL, &con, &pkt ); if( rc != 0 ) { // could not read fprintf(stderr, "Could not read reply from daemon on %s:%d, rc = %d\n", hostname, portnum, rc); exit(1); } if( pkt.hdr.type != PACKET_TYPE_PROCESS ) { // invalid packet fprintf(stderr, "Corrupt response from daemon on %s:%d, rc = %d\n", hostname, portnum, rc); exit(1); } struct wish_process_packet resp; wish_unpack_process_packet( NULL, &pkt, &resp ); if( resp.type != PROCESS_TYPE_STARTED ) { fprintf(stderr, "Daemon relied code %d\n", resp.type ); exit(1); } printf("%lu\n", jpkt.gpid ); wish_disconnect( NULL, &con ); wish_free_job_packet( &jpkt ); wish_free_packet( &pkt ); return 0; }
/* * Internal function for ebzip_unzip_file() and ebzip_unzip_sebxa_start(). * If it succeeds, 0 is returned. Otherwise -1 is returned. */ static int ebzip_unzip_file_internal(const char *out_file_name, const char *in_file_name, Zio_Code in_zio_code, int index_page) { Zio in_zio; unsigned char *buffer = NULL; off_t total_length; int out_file = -1; ssize_t length; struct stat in_status, out_status; unsigned int crc = 1; int progress_interval; int total_slices; int i; zio_initialize(&in_zio); /* * Simply copy a file, when an input file is not compressed. */ if (in_zio_code == ZIO_PLAIN) return ebzip_copy_file(out_file_name, in_file_name); /* * Output file name information. */ if (!ebzip_quiet_flag) { fprintf(stderr, _("==> uncompress %s <==\n"), in_file_name); fprintf(stderr, _("output to %s\n"), out_file_name); fflush(stderr); } /* * Get status of the input file. */ if (stat(in_file_name, &in_status) < 0 || !S_ISREG(in_status.st_mode)) { fprintf(stderr, _("%s: no such file: %s\n"), invoked_name, in_file_name); goto failed; } /* * Do nothing if the `in_file_name' and `out_file_name' are the same. */ if (is_same_file(out_file_name, in_file_name)) { if (!ebzip_quiet_flag) { fprintf(stderr, _("the input and output files are the same, skipped.\n\n")); fflush(stderr); } return 0; } /* * Allocate memories for in/out buffers. */ buffer = (unsigned char *)malloc(EB_SIZE_PAGE << ZIO_MAX_EBZIP_LEVEL); if (buffer == NULL) { fprintf(stderr, _("%s: memory exhausted\n"), invoked_name); goto failed; } /* * If the file `out_file_name' already exists, confirm and unlink it. */ if (!ebzip_test_flag && stat(out_file_name, &out_status) == 0 && S_ISREG(out_status.st_mode)) { if (ebzip_overwrite_mode == EBZIP_OVERWRITE_NO) { if (!ebzip_quiet_flag) { fputs(_("already exists, skip the file\n\n"), stderr); fflush(stderr); } return 0; } else if (ebzip_overwrite_mode == EBZIP_OVERWRITE_CONFIRM) { int y_or_n; fprintf(stderr, _("\nthe file already exists: %s\n"), out_file_name); y_or_n = query_y_or_n(_("do you wish to overwrite (y or n)? ")); fputc('\n', stderr); fflush(stderr); if (!y_or_n) return 0; } if (unlink(out_file_name) < 0) { fprintf(stderr, _("%s: failed to unlink the file: %s\n"), invoked_name, out_file_name); goto failed; } } /* * Open files. */ if (zio_open(&in_zio, in_file_name, in_zio_code) < 0) { fprintf(stderr, _("%s: failed to open the file: %s\n"), invoked_name, in_file_name); goto failed; } if (in_zio_code == ZIO_SEBXA) { off_t index_location; off_t index_base; off_t zio_start_location; off_t zio_end_location; if (get_sebxa_indexes(in_file_name, index_page, &index_location, &index_base, &zio_start_location, &zio_end_location) < 0) { goto failed; } zio_set_sebxa_mode(&in_zio, index_location, index_base, zio_start_location, zio_end_location); } if (!ebzip_test_flag) { trap_file_name = out_file_name; #ifdef SIGHUP signal(SIGHUP, trap); #endif signal(SIGINT, trap); #ifdef SIGQUIT signal(SIGQUIT, trap); #endif #ifdef SIGTERM signal(SIGTERM, trap); #endif #ifdef O_CREAT out_file = open(out_file_name, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0666 ^ get_umask()); #else out_file = creat(out_file_name, 0666 ^ get_umask()); #endif if (out_file < 0) { fprintf(stderr, _("%s: failed to open the file: %s\n"), invoked_name, out_file_name); goto failed; } trap_file = out_file; } /* * Read a slice from the input file, uncompress it if required, * and then write it to the output file. */ total_length = 0; total_slices = (in_zio.file_size + in_zio.slice_size - 1) / in_zio.slice_size; progress_interval = EBZIP_PROGRESS_INTERVAL_FACTOR; if (((total_slices + 999) / 1000) > progress_interval) progress_interval = ((total_slices + 999) / 1000); for (i = 0; i < total_slices; i++) { /* * Read a slice. */ if (zio_lseek(&in_zio, total_length, SEEK_SET) < 0) { fprintf(stderr, _("%s: failed to seek the file: %s\n"), invoked_name, in_file_name); goto failed; } length = zio_read(&in_zio, (char *)buffer, in_zio.slice_size); if (length < 0) { fprintf(stderr, _("%s: failed to read from the file: %s\n"), invoked_name, in_file_name); goto failed; } else if (length == 0) { fprintf(stderr, _("%s: unexpected EOF: %s\n"), invoked_name, in_file_name); goto failed; } else if (length != in_zio.slice_size && total_length + length != in_zio.file_size) { fprintf(stderr, _("%s: unexpected EOF: %s\n"), invoked_name, in_file_name); goto failed; } /* * Update CRC. (Calculate adler32 again.) */ if (in_zio.code == ZIO_EBZIP1) crc = adler32((uLong)crc, (Bytef *)buffer, (uInt)length); /* * Write the slice to `out_file'. */ if (!ebzip_test_flag) { if (write(out_file, buffer, length) != length) { fprintf(stderr, _("%s: failed to write to the file, %s: %s\n"), invoked_name, strerror(errno), out_file_name); goto failed; } } total_length += length; /* * Output status information unless `quiet' mode. */ if (!ebzip_quiet_flag && (i + 1) % progress_interval == 0) { #if defined(PRINTF_LL_MODIFIER) fprintf(stderr, _("%4.1f%% done (%llu / %llu bytes)\n"), (double) (i + 1) * 100.0 / (double) total_slices, (unsigned long long) total_length, (unsigned long long) in_zio.file_size); #elif defined(PRINTF_I64_MODIFIER) fprintf(stderr, _("%4.1f%% done (%I64u / %I64u bytes)\n"), (double) (i + 1) * 100.0 / (double) total_slices, (unsigned __int64) total_length, (unsigned __int64) in_zio.file_size); #else fprintf(stderr, _("%4.1f%% done (%lu / %lu bytes)\n"), (double) (i + 1) * 100.0 / (double) total_slices, (unsigned long) total_length, (unsigned long) in_zio.file_size); #endif fflush(stderr); } } /* * Output the result unless quiet mode. */ if (!ebzip_quiet_flag) { #if defined(PRINTF_LL_MODIFIER) fprintf(stderr, _("completed (%llu / %llu bytes)\n"), (unsigned long long) in_zio.file_size, (unsigned long long) in_zio.file_size); #elif defined(PRINTF_I64_MODIFIER) fprintf(stderr, _("completed (%I64u / %I64u bytes)\n"), (unsigned __int64) in_zio.file_size, (unsigned __int64) in_zio.file_size); #else fprintf(stderr, _("%lu -> %lu bytes\n\n"), (unsigned long) in_status.st_size, (unsigned long) total_length); #endif fflush(stderr); } /* * Close files. */ zio_close(&in_zio); zio_finalize(&in_zio); if (!ebzip_test_flag) { close(out_file); out_file = -1; trap_file = -1; trap_file_name = NULL; #ifdef SIGHUP signal(SIGHUP, SIG_DFL); #endif signal(SIGINT, SIG_DFL); #ifdef SIGQUIT signal(SIGQUIT, SIG_DFL); #endif #ifdef SIGTERM signal(SIGTERM, SIG_DFL); #endif } /* * Check for CRC. */ if (in_zio.code == ZIO_EBZIP1 && in_zio.crc != crc) { fprintf(stderr, _("%s: CRC error: %s\n"), invoked_name, out_file_name); goto failed; } /* * Delete an original file unless the keep flag is set. */ if (!ebzip_test_flag && !ebzip_keep_flag) unlink_files_add(in_file_name); /* * Set owner, group, permission, atime and mtime of `out_file'. * We ignore return values of `chown', `chmod' and `utime'. */ if (!ebzip_test_flag) { struct utimbuf utim; utim.actime = in_status.st_atime; utim.modtime = in_status.st_mtime; utime(out_file_name, &utim); } /* * Dispose memories. */ free(buffer); return 0; /* * An error occurs... */ failed: if (buffer != NULL) free(buffer); zio_close(&in_zio); zio_finalize(&in_zio); if (0 <= out_file) { close(out_file); trap_file = -1; trap_file_name = NULL; #ifdef SIGHUP signal(SIGHUP, SIG_DFL); #endif signal(SIGINT, SIG_DFL); #ifdef SIGQUIT signal(SIGQUIT, SIG_DFL); #endif #ifdef SIGTERM signal(SIGTERM, SIG_DFL); #endif } fputc('\n', stderr); fflush(stderr); return -1; }
/* * Read a catalog file `in_catalog_name' and create refiled catalog file * as `out_catalog_name'. */ static int refile_catalog(const char *out_catalog_name, const char *in_catalog_name, EB_Disc_Code disc_code, char subbook_name_list[][EB_MAX_DIRECTORY_NAME_LENGTH + 1], int subbook_name_count) { char buffer[EB_SIZE_PAGE]; char directory_name[EB_MAX_DIRECTORY_NAME_LENGTH + 1]; int in_subbook_count; int in_file = -1; int out_file = -1; int subbbook_map_table[EB_MAX_SUBBOOKS]; off_t out_file_offset; size_t catalog_size; int i, j; for (i = 0; i < EB_MAX_SUBBOOKS; i++) subbbook_map_table[i] = EB_SUBBOOK_INVALID; if (disc_code == EB_DISC_EB) catalog_size = EB_SIZE_EB_CATALOG; else catalog_size = EB_SIZE_EPWING_CATALOG; /* * Open input file. */ in_file = open(in_catalog_name, O_RDONLY | O_BINARY); if (in_file < 0) { fprintf(stderr, _("%s: failed to open the file, %s: %s\n"), invoked_name, strerror(errno), in_catalog_name); goto failed; } /* * Open output file. */ #ifdef O_CREAT out_file = open(out_catalog_name, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0666 ^ get_umask()); #else out_file = creat(out_catalog_name, 0666 ^ get_umask()); #endif trap_file = out_file; if (out_file < 0) { fprintf(stderr, _("%s: failed to open the file, %s: %s\n"), invoked_name, strerror(errno), out_catalog_name); goto failed; } /* * Copy header. */ if (read(in_file, buffer, 16) != 16) { fprintf(stderr, _("%s: failed to read the file, %s: %s\n"), invoked_name, strerror(errno), in_catalog_name); goto failed; } in_subbook_count = eb_uint2(buffer); if (write(out_file, buffer, 16) != 16) { fprintf(stderr, _("%s: failed to write the file, %s: %s\n"), invoked_name, strerror(errno), out_catalog_name); goto failed; } out_file_offset = 16; /* * Copy basic information of subbooks. */ for (i = 0; i < in_subbook_count; i++) { /* * Read subbook entry. */ if (read(in_file, buffer, catalog_size) != catalog_size) { fprintf(stderr, _("%s: failed to read the file, %s: %s\n"), invoked_name, strerror(errno), in_catalog_name); goto failed; } /* * Check whether `subbook_name_list' has a directory name of * this subbook. If not, we ignore this subbook. */ if (disc_code == EB_DISC_EB) { strncpy(directory_name, buffer + 2 + EB_MAX_EB_TITLE_LENGTH, EB_MAX_DIRECTORY_NAME_LENGTH); } else { strncpy(directory_name, buffer + 2 + EB_MAX_EPWING_TITLE_LENGTH, EB_MAX_DIRECTORY_NAME_LENGTH); } directory_name[EB_MAX_DIRECTORY_NAME_LENGTH] = '\0'; if (subbook_name_count == 0) subbbook_map_table[i] = i; else { int subbook_index; subbook_index = find_subbook_name(subbook_name_list, subbook_name_count, directory_name); if (subbook_index < 0) continue; subbbook_map_table[i] = subbook_index; } /* * Write the subbook entry. */ if (write(out_file, buffer, catalog_size) != catalog_size) { fprintf(stderr, _("%s: failed to write the file, %s: %s\n"), invoked_name, strerror(errno), out_catalog_name); goto failed; } out_file_offset += catalog_size; } /* * Copy extended information of subbooks. */ if (disc_code == EB_DISC_EPWING) { for (i = 0; i < in_subbook_count; i++) { if (read(in_file, buffer, catalog_size) != catalog_size) { fprintf(stderr, _("%s: failed to read the file, %s: %s\n"), invoked_name, strerror(errno), in_catalog_name); goto failed; } if (subbbook_map_table[i] == EB_SUBBOOK_INVALID) continue; if (write(out_file, buffer, catalog_size) != catalog_size) { fprintf(stderr, _("%s: failed to write the file, %s: %s\n"), invoked_name, strerror(errno), out_catalog_name); goto failed; } out_file_offset += catalog_size; } } /* * Check whether all subbooks in `subbook_name_list' are found. */ for (i = 0; i < subbook_name_count; i++) { for (j = 0; j < in_subbook_count; j++) { if (subbbook_map_table[j] == i) break; } if (in_subbook_count <= j) { fprintf(stderr, _("%s: warning: no such subbook: %s\n"), invoked_name, subbook_name_list[i]); } } /* * Copy rest of the catalog file. */ for (;;) { ssize_t read_length; read_length = read(in_file, buffer, EB_SIZE_PAGE); if (read_length == 0) { break; } else if (read_length < 0) { fprintf(stderr, _("%s: failed to read the file, %s: %s\n"), invoked_name, strerror(errno), in_catalog_name); goto failed; } if (write(out_file, buffer, read_length) != read_length) { fprintf(stderr, _("%s: failed to write the file, %s: %s\n"), invoked_name, strerror(errno), out_catalog_name); goto failed; } out_file_offset += read_length; } /* * Fill the current page with 0. */ if (0 < out_file_offset % EB_SIZE_PAGE) { size_t pad_length; pad_length = EB_SIZE_PAGE - (out_file_offset % EB_SIZE_PAGE); memset(buffer, 0, EB_SIZE_PAGE); if (write(out_file, buffer, pad_length) != pad_length) { fprintf(stderr, _("%s: failed to write the file, %s: %s\n"), invoked_name, strerror(errno), out_catalog_name); goto failed; } } /* * Fix the number of subbook. */ if (subbook_name_count == 0) { buffer[0] = (in_subbook_count >> 8) & 0xff; buffer[1] = in_subbook_count & 0xff; } else {