int tar_main(int argc, char **argv) { char (*get_header_ptr)(archive_handle_t *) = get_header_tar; archive_handle_t *tar_handle; char *base_dir = NULL; const char *tar_filename = "-"; unsigned long opt; unsigned long ctx_flag = 0; if (argc < 2) { bb_show_usage(); } /* Prepend '-' to the first argument if required */ if (argv[1][0] != '-') { char *tmp; bb_xasprintf(&tmp, "-%s", argv[1]); argv[1] = tmp; } /* Initialise default values */ tar_handle = init_handle(); tar_handle->flags = ARCHIVE_CREATE_LEADING_DIRS | ARCHIVE_PRESERVE_DATE | ARCHIVE_EXTRACT_UNCONDITIONAL; bb_opt_complementaly = "c~tx:t~cx:x~ct:X*:T*"; #ifdef CONFIG_FEATURE_TAR_LONG_OPTIONS bb_applet_long_options = tar_long_options; #endif opt = bb_getopt_ulflags(argc, argv, tar_options, &base_dir, /* Change to dir <optarg> */ &tar_filename /* archive filename */ #ifdef CONFIG_FEATURE_TAR_FROM , NULL, &(tar_handle->reject) #endif ); /* Check one and only one context option was given */ if(opt & 0x80000000UL) { bb_show_usage(); } #ifdef CONFIG_FEATURE_TAR_CREATE ctx_flag = opt & (CTX_CREATE | CTX_TEST | CTX_EXTRACT); #else ctx_flag = opt & (CTX_TEST | CTX_EXTRACT); #endif if (ctx_flag == 0) { bb_show_usage(); } if(ctx_flag & CTX_TEST) { if ((tar_handle->action_header == header_list) || (tar_handle->action_header == header_verbose_list)) { tar_handle->action_header = header_verbose_list; } else { tar_handle->action_header = header_list; } } if(ctx_flag & CTX_EXTRACT) { if (tar_handle->action_data != data_extract_to_stdout) tar_handle->action_data = data_extract_all; } if(opt & TAR_OPT_2STDOUT) { /* To stdout */ tar_handle->action_data = data_extract_to_stdout; } if(opt & TAR_OPT_VERBOSE) { if ((tar_handle->action_header == header_list) || (tar_handle->action_header == header_verbose_list)) { tar_handle->action_header = header_verbose_list; } else { tar_handle->action_header = header_list; } } if (opt & TAR_OPT_KEEP_OLD) { tar_handle->flags &= ~ARCHIVE_EXTRACT_UNCONDITIONAL; } #ifdef CONFIG_FEATURE_TAR_GZIP if(opt & TAR_OPT_GZIP) { get_header_ptr = get_header_tar_gz; } #endif #ifdef CONFIG_FEATURE_TAR_BZIP2 if(opt & TAR_OPT_BZIP2) { get_header_ptr = get_header_tar_bz2; } #endif #ifdef CONFIG_FEATURE_TAR_COMPRESS if(opt & TAR_OPT_UNCOMPRESS) { get_header_ptr = get_header_tar_Z; } #endif #ifdef CONFIG_FEATURE_TAR_FROM if(opt & TAR_OPT_EXCLUDE_FROM) { tar_handle->reject = append_file_list_to_list(tar_handle->reject); } #endif /* Check if we are reading from stdin */ if ((argv[optind]) && (*argv[optind] == '-')) { /* Default is to read from stdin, so just skip to next arg */ optind++; } /* Setup an array of filenames to work with */ /* TODO: This is the same as in ar, separate function ? */ while (optind < argc) { char *filename_ptr = last_char_is(argv[optind], '/'); if (filename_ptr) { *filename_ptr = '\0'; } tar_handle->accept = llist_add_to(tar_handle->accept, argv[optind]); optind++; } if ((tar_handle->accept) || (tar_handle->reject)) { tar_handle->filter = filter_accept_reject_list; } /* Open the tar file */ { FILE *tar_stream; int flags; #ifdef CONFIG_FEATURE_TAR_CREATE if (opt & CTX_CREATE) { /* Make sure there is at least one file to tar up. */ if (tar_handle->accept == NULL) { bb_error_msg_and_die("Cowardly refusing to create an empty archive"); } tar_stream = stdout; flags = O_WRONLY | O_CREAT | O_EXCL; unlink(tar_filename); } else #endif { tar_stream = stdin; flags = O_RDONLY; } if ((tar_filename[0] == '-') && (tar_filename[1] == '\0')) { tar_handle->src_fd = fileno(tar_stream); tar_handle->seek = seek_by_char; } else { tar_handle->src_fd = bb_xopen(tar_filename, flags); } } if ((base_dir) && (chdir(base_dir))) { bb_perror_msg_and_die("Couldnt chdir to %s", base_dir); } #ifdef CONFIG_FEATURE_TAR_CREATE /* create an archive */ if (opt & CTX_CREATE) { int verboseFlag = FALSE; int gzipFlag = FALSE; # ifdef CONFIG_FEATURE_TAR_GZIP if (get_header_ptr == get_header_tar_gz) { gzipFlag = TRUE; } # endif /* CONFIG_FEATURE_TAR_GZIP */ # ifdef CONFIG_FEATURE_TAR_BZIP2 if (get_header_ptr == get_header_tar_bz2) { bb_error_msg_and_die("Creating bzip2 compressed archives is not currently supported."); } # endif /* CONFIG_FEATURE_TAR_BZIP2 */ if ((tar_handle->action_header == header_list) || (tar_handle->action_header == header_verbose_list)) { verboseFlag = TRUE; } writeTarFile(tar_handle->src_fd, verboseFlag, opt & TAR_OPT_DEREFERNCE, tar_handle->accept, tar_handle->reject, gzipFlag); } else #endif /* CONFIG_FEATURE_TAR_CREATE */ { while (get_header_ptr(tar_handle) == EXIT_SUCCESS); /* Ckeck that every file that should have been extracted was */ while (tar_handle->accept) { if (find_list_entry(tar_handle->reject, tar_handle->accept->data) == NULL) { if (find_list_entry(tar_handle->passed, tar_handle->accept->data) == NULL) { bb_error_msg_and_die("%s: Not found in archive\n", tar_handle->accept->data); } } tar_handle->accept = tar_handle->accept->link; } } #ifdef CONFIG_FEATURE_CLEAN_UP if (tar_handle->src_fd != STDIN_FILENO) { close(tar_handle->src_fd); } #endif /* CONFIG_FEATURE_CLEAN_UP */ return(EXIT_SUCCESS); }
int flash_eraseall_main(int argc, char **argv) { struct jffs2_unknown_node oob_cleanmarker; mtd_info_t meminfo; int fd, clmpos, clmlen; erase_info_t erase; struct stat st; unsigned int flags; char *mtd_name; // flags = BBTEST | bb_getopt_ulflags(argc, argv, "jqre"); flags = BBTEST | getopt32(argv,"jqre"); mtd_name = argv[optind]; stat(mtd_name, &st); if (!S_ISCHR(st.st_mode)) bb_error_msg_and_die("%s: not a char device", mtd_name); fd = bb_xopen(mtd_name, O_RDWR); ioctl(fd, MEMGETINFO, &meminfo); erase.length = meminfo.erasesize; if (meminfo.type == MTD_NANDFLASH) flags |= IS_NAND; clmpos = 0; clmlen = 8; if (flags & OPTION_J) { oob_cleanmarker.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); oob_cleanmarker.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER); oob_cleanmarker.totlen = cpu_to_je32(8); oob_cleanmarker.hdr_crc = cpu_to_je32(0); if (!(flags & IS_NAND)) oob_cleanmarker.totlen = cpu_to_je32(sizeof(struct jffs2_unknown_node)); else { struct k_nand_ecclayout ecclayout; ioctl(fd, ECCGETLAYOUT, &ecclayout); clmlen = ecclayout.oobavail; clmpos = 0; } } /* Don't want to destroy progress indicator by bb_error_msg's */ printf("\nflash_eraseall: %s", mtd_name); for (erase.start = 0; erase.start < meminfo.size; erase.start += meminfo.erasesize) { if (flags & BBTEST) { int ret; loff_t offset = erase.start; ret = ioctl(fd, MEMGETBADBLOCK, &offset); if (ret > 0) { if (!(flags & OPTION_Q)) printf("\nSkipping bad block at 0x%08x", erase.start); continue; } if (ret < 0) { /* Black block table is not available on certain flash * types e.g. NOR */ if (errno == EOPNOTSUPP) { flags = ~BBTEST; if (flags & IS_NAND) bb_error_msg_and_die("bad block check not available"); } else { bb_perror_msg_and_die("MEMGETBADBLOCK error"); } } } if (!(flags & OPTION_Q)) show_progress(&meminfo, &erase); if (!(flags & OPTION_E)) ioctl(fd, MEMERASE, &erase); /* format for JFFS2 ? */ if (!(flags & OPTION_J)) continue; /* write cleanmarker */ if (flags & IS_NAND) { struct mtd_oob_buf oob; oob.ptr = (unsigned char *) &oob_cleanmarker; oob.start = erase.start + clmpos; oob.length = clmlen; #if 0 /* TESTING */ printf("W %8.8lx %lu - %8.8lx %8.8lx %8.8lx\n", (unsigned long) oob.start, (unsigned long) oob.length, *((unsigned long *) &oob_cleanmarker + 0), *((unsigned long *) &oob_cleanmarker + 1), *((unsigned long *) &oob_cleanmarker + 2)); #endif ioctl(fd, MEMWRITEOOB, &oob); } else { lseek(fd, erase.start, SEEK_SET); /* if (lseek(fd, erase.start, SEEK_SET) < 0) { bb_perror_msg("MTD %s failure", "seek"); continue; } */ write(fd, &oob_cleanmarker, sizeof(oob_cleanmarker)); /* if (write(fd, &oob_cleanmarker, sizeof(oob_cleanmarker)) != sizeof(oob_cleanmarker)) { bb_perror_msg("MTD %s failure", "write"); continue; } */ } if (!(flags & OPTION_Q)) printf(" Cleanmarker written at %x.", erase.start); } if (!(flags & OPTION_Q)) { show_progress(&meminfo, &erase); putchar('\n'); } if (flags & OPTION_R) { int i; /* For testing, read back cleanmarker plus 12 bytes. */ for (i= 0; i< meminfo.size; i+= meminfo.erasesize) { if (flags & BBTEST) { int ret; loff_t offset = i; ret = ioctl(fd, MEMGETBADBLOCK, &offset); if (ret > 0) { if (!(flags & OPTION_Q)) printf("\nSkipping bad block at 0x%08x", i); continue; } if (ret < 0) { /* Black block table is not available on certain flash * types e.g. NOR */ if (errno == EOPNOTSUPP) { flags = ~BBTEST; if (flags & IS_NAND) bb_error_msg_and_die("bad block check not available"); } else { bb_perror_msg_and_die("MEMGETBADBLOCK error"); } } } if (flags & IS_NAND) { unsigned char clnmrk[20]; struct mtd_oob_buf oob; memset(clnmrk, 0x00, sizeof(clnmrk)); oob.ptr = (unsigned char *) &clnmrk; oob.start = i + clmpos; oob.length = 16; // clmlen; ioctl(fd, MEMREADOOB, &oob); printf("R %8.8lx %lu - %8.8lx %8.8lx %8.8lx %8.8lx\n", (unsigned long) (i + clmpos), (unsigned long) clmlen, *((unsigned long *) &clnmrk[0]), *((unsigned long *) &clnmrk[4]), *((unsigned long *) &clnmrk[8]), *((unsigned long *) &clnmrk[12])); } } } close(fd); return EXIT_SUCCESS; }
int readprofile_main(int argc, char **argv) { FILE *map; int proFd; const char *mapFile, *proFile, *mult=0; unsigned long len=0, indx=1; unsigned long long add0=0; unsigned int step; unsigned int *buf, total, fn_len; unsigned long long fn_add, next_add; /* current and next address */ char fn_name[S_LEN], next_name[S_LEN]; /* current and next name */ char mode[8]; int c; int optAll=0, optInfo=0, optReset=0, optVerbose=0, optNative=0; int optBins=0, optSub=0; char mapline[S_LEN]; int maplineno=1; int header_printed; #define next (current^1) proFile = defaultpro; mapFile = defaultmap; while ((c = getopt(argc, argv, "M:m:np:itvarVbs")) != -1) { switch(c) { case 'm': mapFile = optarg; break; case 'n': optNative++; break; case 'p': proFile = optarg; break; case 'a': optAll++; break; case 'b': optBins++; break; case 's': optSub++; break; case 'i': optInfo++; break; case 'M': mult = optarg; break; case 'r': optReset++; break; case 'v': optVerbose++; break; default: bb_show_usage(); } } if (optReset || mult) { int multiplier, fd, to_write; /* * When writing the multiplier, if the length of the write is * not sizeof(int), the multiplier is not changed */ if (mult) { multiplier = strtoul(mult, 0, 10); to_write = sizeof(int); } else { multiplier = 0; to_write = 1; /* sth different from sizeof(int) */ } fd = bb_xopen(defaultpro,O_WRONLY); if (write(fd, &multiplier, to_write) != to_write) bb_perror_msg_and_die("error writing %s", defaultpro); close(fd); return EXIT_SUCCESS; } /* * Use an fd for the profiling buffer, to skip stdio overhead */ proFd = bb_xopen(proFile,O_RDONLY); if (((int)(len=lseek(proFd,0,SEEK_END)) < 0) || (lseek(proFd,0,SEEK_SET) < 0)) bb_perror_msg_and_die(proFile); buf = xmalloc(len); if (read(proFd,buf,len) != len) bb_perror_msg_and_die(proFile); close(proFd); if (!optNative) { int entries = len/sizeof(*buf); int big = 0,small = 0,i; unsigned *p; for (p = buf+1; p < buf+entries; p++) { if (*p & ~0U << (sizeof(*buf)*4)) big++; if (*p & ((1 << (sizeof(*buf)*4))-1)) small++; } if (big > small) { bb_error_msg("Assuming reversed byte order. " "Use -n to force native byte order."); for (p = buf; p < buf+entries; p++) for (i = 0; i < sizeof(*buf)/2; i++) { unsigned char *b = (unsigned char *) p; unsigned char tmp; tmp = b[i]; b[i] = b[sizeof(*buf)-i-1]; b[sizeof(*buf)-i-1] = tmp; } } } step = buf[0]; if (optInfo) { printf("Sampling_step: %i\n", step); return EXIT_SUCCESS; } total = 0; map = bb_xfopen(mapFile, "r"); while (fgets(mapline,S_LEN,map)) { if (sscanf(mapline,"%llx %s %s",&fn_add,mode,fn_name) != 3) bb_error_msg_and_die("%s(%i): wrong map line", mapFile, maplineno); if (!strcmp(fn_name,"_stext")) /* only elf works like this */ { add0 = fn_add; break; } maplineno++; } if (!add0) bb_error_msg_and_die("can't find \"_stext\" in %s", mapFile); /* * Main loop. */ while (fgets(mapline,S_LEN,map)) { unsigned int this = 0; if (sscanf(mapline,"%llx %s %s",&next_add,mode,next_name) != 3) bb_error_msg_and_die("%s(%i): wrong map line", mapFile, maplineno); header_printed = 0; /* ignore any LEADING (before a '[tT]' symbol is found) Absolute symbols */ if ((*mode == 'A' || *mode == '?') && total == 0) continue; if (*mode != 'T' && *mode != 't' && *mode != 'W' && *mode != 'w') break; /* only text is profiled */ if (indx >= len / sizeof(*buf)) bb_error_msg_and_die("profile address out of range. " "Wrong map file?"); while (indx < (next_add-add0)/step) { if (optBins && (buf[indx] || optAll)) { if (!header_printed) { printf ("%s:\n", fn_name); header_printed = 1; } printf ("\t%llx\t%u\n", (indx - 1)*step + add0, buf[indx]); } this += buf[indx++]; } total += this; if (optBins) { if (optVerbose || this > 0) printf (" total\t\t\t\t%u\n", this); } else if ((this || optAll) && (fn_len = next_add-fn_add) != 0) { if (optVerbose) printf("%016llx %-40s %6i %8.4f\n", fn_add, fn_name,this,this/(double)fn_len); else printf("%6i %-40s %8.4f\n", this,fn_name,this/(double)fn_len); if (optSub) { unsigned long long scan; for (scan = (fn_add-add0)/step + 1; scan < (next_add-add0)/step; scan++) { unsigned long long addr; addr = (scan - 1)*step + add0; printf("\t%#llx\t%s+%#llx\t%u\n", addr, fn_name, addr - fn_add, buf[scan]); } } } fn_add = next_add; strcpy(fn_name,next_name); maplineno++; } /* clock ticks, out of kernel text - probably modules */ printf("%6i %s\n", buf[len/sizeof(*buf)-1], "*unknown*"); /* trailer */ if (optVerbose) printf("%016x %-40s %6i %8.4f\n", 0,"total",total,total/(double)(fn_add-add0)); else printf("%6i %-40s %8.4f\n", total,"total",total/(double)(fn_add-add0)); fclose(map); free(buf); return EXIT_SUCCESS; }
extern int gunzip_main(int argc, char **argv) { char status = EXIT_SUCCESS; unsigned long opt; opt = bb_getopt_ulflags(argc, argv, "cftd"); /* if called as zcat */ if (strcmp(bb_applet_name, "zcat") == 0) { opt |= GUNZIP_OPT_STDOUT; } do { struct stat stat_buf; const char *old_path = argv[optind]; const char *delete_path = NULL; char *new_path = NULL; int src_fd; int dst_fd; optind++; if (old_path == NULL || strcmp(old_path, "-") == 0) { src_fd = STDIN_FILENO; opt |= GUNZIP_OPT_STDOUT; } else { src_fd = bb_xopen(old_path, O_RDONLY); /* Get the time stamp on the input file. */ if (stat(old_path, &stat_buf) < 0) { bb_error_msg_and_die("Couldn't stat file %s", old_path); } } /* Check that the input is sane. */ if (isatty(src_fd) && ((opt & GUNZIP_OPT_FORCE) == 0)) { bb_error_msg_and_die ("compressed data not read from terminal. Use -f to force it."); } /* Set output filename and number */ if (opt & GUNZIP_OPT_TEST) { dst_fd = bb_xopen(bb_dev_null, O_WRONLY); /* why does test use filenum 2 ? */ } else if (opt & GUNZIP_OPT_STDOUT) { dst_fd = STDOUT_FILENO; } else { char *extension; new_path = bb_xstrdup(old_path); extension = strrchr(new_path, '.'); #ifdef CONFIG_FEATURE_GUNZIP_UNCOMPRESS if (extension && (strcmp(extension, ".Z") == 0)) { *extension = '\0'; } else #endif if (extension && (strcmp(extension, ".gz") == 0)) { *extension = '\0'; } else if (extension && (strcmp(extension, ".tgz") == 0)) { extension[2] = 'a'; extension[3] = 'r'; } else { bb_error_msg_and_die("Invalid extension"); } /* Open output file */ dst_fd = bb_xopen(new_path, O_WRONLY | O_CREAT); /* Set permissions on the file */ chmod(new_path, stat_buf.st_mode); /* If unzip succeeds remove the old file */ delete_path = old_path; } /* do the decompression, and cleanup */ if (bb_xread_char(src_fd) == 0x1f) { unsigned char magic2; magic2 = bb_xread_char(src_fd); #ifdef CONFIG_FEATURE_GUNZIP_UNCOMPRESS if (magic2 == 0x9d) { status = uncompress(src_fd, dst_fd); } else #endif if (magic2 == 0x8b) { check_header_gzip(src_fd); status = inflate_gunzip(src_fd, dst_fd); if (status != 0) { bb_error_msg_and_die("Error inflating"); } } else { bb_error_msg_and_die("Invalid magic"); } } else { bb_error_msg_and_die("Invalid magic"); } if ((status != EXIT_SUCCESS) && (new_path)) { /* Unzip failed, remove new path instead of old path */ delete_path = new_path; } if (dst_fd != STDOUT_FILENO) { close(dst_fd); } if (src_fd != STDIN_FILENO) { close(src_fd); } /* delete_path will be NULL if in test mode or from stdin */ if (delete_path && (unlink(delete_path) == -1)) { bb_error_msg_and_die("Couldn't remove %s", delete_path); } free(new_path); } while (optind < argc); return status; }
static int ftp_send(ftp_host_info_t *server, FILE *control_stream, const char *server_path, char *local_path) { struct stat sbuf; char buf[512]; int fd_data; int fd_local; int response; /* Connect to the data socket */ if (ftpcmd("PASV", NULL, control_stream, buf) != 227) { bb_error_msg_and_die("PASV error: %s", buf + 4); } fd_data = xconnect_ftpdata(server, buf); if (ftpcmd("CWD ", server_path, control_stream, buf) != 250) { bb_error_msg_and_die("CWD error: %s", buf + 4); } /* get the local file */ if ((local_path[0] == '-') && (local_path[1] == '\0')) { fd_local = fileno(stdin); } else { fd_local = bb_xopen(local_path, O_RDONLY); fstat(fd_local, &sbuf); sprintf(buf, "ALLO %lu", (unsigned long)sbuf.st_size); response = ftpcmd(buf, NULL, control_stream, buf); switch (response) { case 200: case 202: break; default: close(fd_local); bb_error_msg_and_die("ALLO error: %s", buf + 4); break; } } response = ftpcmd("STOR ", local_path, control_stream, buf); switch (response) { case 125: case 150: break; default: close(fd_local); bb_error_msg_and_die("STOR error: %s", buf + 4); } /* transfer the file */ if (bb_copyfd_eof(fd_local, fd_data) == -1) { exit(EXIT_FAILURE); } /* close it all down */ close(fd_data); if (ftpcmd(NULL, NULL, control_stream, buf) != 226) { bb_error_msg_and_die("error: %s", buf + 4); } ftpcmd("QUIT", NULL, control_stream, buf); return(EXIT_SUCCESS); }
static int ftp_recieve(ftp_host_info_t *server, FILE *control_stream, const char *local_path, char *server_path) { char buf[512]; off_t filesize = 0; int fd_data; int fd_local = -1; off_t beg_range = 0; /* Connect to the data socket */ if (ftpcmd("PASV", NULL, control_stream, buf) != 227) { bb_error_msg_and_die("PASV error: %s", buf + 4); } fd_data = xconnect_ftpdata(server, buf); if (ftpcmd("SIZE ", server_path, control_stream, buf) == 213) { filesize = atol(buf + 4); } if ((local_path[0] == '-') && (local_path[1] == '\0')) { fd_local = fileno(stdout); do_continue = 0; } if (do_continue) { struct stat sbuf; if (lstat(local_path, &sbuf) < 0) { bb_perror_msg_and_die("fstat()"); } if (sbuf.st_size > 0) { beg_range = sbuf.st_size; } else { do_continue = 0; } } if (do_continue) { sprintf(buf, "REST %ld", (long)beg_range); if (ftpcmd(buf, NULL, control_stream, buf) != 350) { do_continue = 0; } else { filesize -= beg_range; } } if (ftpcmd("RETR ", server_path, control_stream, buf) > 150) { bb_error_msg_and_die("RETR error: %s", buf + 4); } /* only make a local file if we know that one exists on the remote server */ if (fd_local == -1) { if (do_continue) { fd_local = bb_xopen(local_path, O_APPEND | O_WRONLY); } else { fd_local = bb_xopen(local_path, O_CREAT | O_TRUNC | O_WRONLY); } } /* Copy the file */ if (bb_copyfd_size(fd_data, fd_local, filesize) == -1) { exit(EXIT_FAILURE); } /* close it all down */ close(fd_data); if (ftpcmd(NULL, NULL, control_stream, buf) != 226) { bb_error_msg_and_die("ftp error: %s", buf + 4); } ftpcmd("QUIT", NULL, control_stream, buf); return(EXIT_SUCCESS); }
int dd_main(int argc, char **argv) { size_t out_full = 0; size_t out_part = 0; size_t in_full = 0; size_t in_part = 0; size_t count = -1; size_t bs = 512; ssize_t n; off_t seek = 0; off_t skip = 0; int sync_flag = FALSE; int noerror = FALSE; int trunc_flag = TRUE; int oflag; int ifd; int ofd; int i; const char *infile = NULL; const char *outfile = NULL; char *buf; for (i = 1; i < argc; i++) { if (strncmp("bs=", argv[i], 3) == 0) bs = bb_xparse_number(argv[i]+3, dd_suffixes); else if (strncmp("count=", argv[i], 6) == 0) count = bb_xparse_number(argv[i]+6, dd_suffixes); else if (strncmp("seek=", argv[i], 5) == 0) seek = bb_xparse_number(argv[i]+5, dd_suffixes); else if (strncmp("skip=", argv[i], 5) == 0) skip = bb_xparse_number(argv[i]+5, dd_suffixes); else if (strncmp("if=", argv[i], 3) == 0) infile = argv[i]+3; else if (strncmp("of=", argv[i], 3) == 0) outfile = argv[i]+3; else if (strncmp("conv=", argv[i], 5) == 0) { buf = argv[i]+5; while (1) { if (strncmp("notrunc", buf, 7) == 0) { trunc_flag = FALSE; buf += 7; } else if (strncmp("sync", buf, 4) == 0) { sync_flag = TRUE; buf += 4; } else if (strncmp("noerror", buf, 7) == 0) { noerror = TRUE; buf += 7; } else { bb_error_msg_and_die("invalid conversion `%s'", argv[i]+5); } if (buf[0] == '\0') break; if (buf[0] == ',') buf++; } } else bb_show_usage(); } buf = xmalloc(bs); if (infile != NULL) { ifd = bb_xopen(infile, O_RDONLY|0x20000000); } else { ifd = STDIN_FILENO; infile = bb_msg_standard_input; } if (outfile != NULL) { oflag = O_WRONLY | O_CREAT; if (!seek && trunc_flag) { oflag |= O_TRUNC; } if ((ofd = open(outfile, oflag|0x20000000, 0666)) < 0) { bb_perror_msg_and_die("%s", outfile); } if (seek && trunc_flag) { if (ftruncate(ofd, seek * bs) < 0) { struct stat st; if (fstat (ofd, &st) < 0 || S_ISREG (st.st_mode) || S_ISDIR (st.st_mode)) { bb_perror_msg_and_die("%s", outfile); } } } } else { ofd = STDOUT_FILENO; outfile = bb_msg_standard_output; } if (skip) { if (lseek(ifd, skip * bs, SEEK_CUR) < 0) { bb_perror_msg_and_die("%s", infile); } } if (seek) { if (lseek(ofd, seek * bs, SEEK_CUR) < 0) { bb_perror_msg_and_die("%s", outfile); } } while (in_full + in_part != count) { if (noerror) { /* Pre-zero the buffer when doing the noerror thing */ memset(buf, '\0', bs); } n = safe_read(ifd, buf, bs); if (n < 0) { if (noerror) { n = bs; bb_perror_msg("%s", infile); } else { bb_perror_msg_and_die("%s", infile); } } if (n == 0) { break; } if ((size_t)n == bs) { in_full++; } else { in_part++; } if (sync_flag) { memset(buf + n, '\0', bs - n); n = bs; } n = bb_full_write(ofd, buf, n); if (n < 0) { bb_perror_msg_and_die("%s", outfile); } if ((size_t)n == bs) { out_full++; } else { out_part++; } } if (close (ifd) < 0) { bb_perror_msg_and_die("%s", infile); } if (close (ofd) < 0) { bb_perror_msg_and_die("%s", outfile); } fprintf(stderr, "%ld+%ld records in\n%ld+%ld records out\n", (long)in_full, (long)in_part, (long)out_full, (long)out_part); return EXIT_SUCCESS; }