char * deb_extract(const char *package_filename, FILE *out_stream, const int extract_function, const char *prefix, const char *filename, int *err) { FILE *deb_stream = NULL; file_header_t *ar_header = NULL; const char **file_list = NULL; char *output_buffer = NULL; char *ared_file = NULL; char ar_magic[8]; int gz_err; *err = 0; if (filename != NULL) { file_list = xmalloc(sizeof(char *) * 2); file_list[0] = filename; file_list[1] = NULL; } if (extract_function & extract_control_tar_gz) { ared_file = "control.tar.gz"; } else if (extract_function & extract_data_tar_gz) { ared_file = "data.tar.gz"; } else { error_msg( "Internal error: extract_function=%x\n", extract_function); *err = -1; goto cleanup; } /* open the debian package to be worked on */ deb_stream = wfopen(package_filename, "r"); if (deb_stream == NULL) { *err = -1; goto cleanup; } /* set the buffer size */ setvbuf(deb_stream, NULL, _IOFBF, 0x8000); /* check ar magic */ fread(ar_magic, 1, 8, deb_stream); if (strncmp(ar_magic,"!<arch>",7) == 0) { archive_offset = 8; while ((ar_header = get_header_ar(deb_stream)) != NULL) { if (strcmp(ared_file, ar_header->name) == 0) { int gunzip_pid = 0; FILE *uncompressed_stream; /* open a stream of decompressed data */ uncompressed_stream = gz_open(deb_stream, &gunzip_pid); if (uncompressed_stream == NULL) { *err = -1; goto cleanup; } archive_offset = 0; output_buffer = unarchive(uncompressed_stream, out_stream, get_header_tar, free_header_tar, extract_function, prefix, file_list, err); fclose(uncompressed_stream); gz_err = gz_close(gunzip_pid); if (gz_err) *err = -1; free_header_ar(ar_header); break; } if (fseek(deb_stream, ar_header->size, SEEK_CUR) == -1) { perror_msg("Couldn't fseek into %s", package_filename); *err = -1; free_header_ar(ar_header); goto cleanup; } free_header_ar(ar_header); } goto cleanup; } else if (strncmp(ar_magic, "\037\213", 2) == 0) { /* it's a gz file, let's assume it's an opkg */ int unzipped_opkg_pid; FILE *unzipped_opkg_stream; file_header_t *tar_header; archive_offset = 0; if (fseek(deb_stream, 0, SEEK_SET) == -1) { perror_msg( "Couldn't fseek into %s", package_filename); *err = -1; goto cleanup; } unzipped_opkg_stream = gz_open(deb_stream, &unzipped_opkg_pid); if (unzipped_opkg_stream == NULL) { *err = -1; goto cleanup; } /* walk through outer tar file to find ared_file */ while ((tar_header = get_header_tar(unzipped_opkg_stream)) != NULL) { int name_offset = 0; if (strncmp(tar_header->name, "./", 2) == 0) name_offset = 2; if (strcmp(ared_file, tar_header->name+name_offset) == 0) { int gunzip_pid = 0; FILE *uncompressed_stream; /* open a stream of decompressed data */ uncompressed_stream = gz_open(unzipped_opkg_stream, &gunzip_pid); if (uncompressed_stream == NULL) { *err = -1; goto cleanup; } archive_offset = 0; output_buffer = unarchive(uncompressed_stream, out_stream, get_header_tar, free_header_tar, extract_function, prefix, file_list, err); free_header_tar(tar_header); fclose(uncompressed_stream); gz_err = gz_close(gunzip_pid); if (gz_err) *err = -1; break; } seek_sub_file(unzipped_opkg_stream, tar_header->size); free_header_tar(tar_header); } fclose(unzipped_opkg_stream); gz_err = gz_close(unzipped_opkg_pid); if (gz_err) *err = -1; goto cleanup; } else { *err = -1; error_msg("%s: invalid magic", package_filename); } cleanup: if (deb_stream) fclose(deb_stream); if (file_list) free(file_list); return output_buffer; }
long load_elf (int fd, char *buf, int *n, int flags) { Elf32_Ehdr *ep; Elf32_Phdr *phtab = 0; Elf32_Shdr *shtab = 0; unsigned int nbytes; int i; Elf32_Off highest_load = 0; bootseg = 0; myflags=flags; #ifdef __mips__ tablebase = PHYS_TO_CACHED(memorysize); #else tablebase = memorysize; #endif #if NGZIP > 0 lseek(fd,*n,0); read(fd,buf,2); if(((unsigned char)buf[0]==0x1f) && ((unsigned char)buf[1]==0x8b))flags |=ZFLAG; else flags &=~ZFLAG; myflags=flags; lseek(fd,*n,0); if(myflags&ZFLAG){ gz_open(fd); *n = 0; gz_lseek (fd, 0, SEEK_SET); } #endif /* NGZIP */ ep = (Elf32_Ehdr *)buf; if (sizeof(*ep) > *n) { #if NGZIP > 0 if(myflags&ZFLAG) *n += gz_read (fd, buf+*n, sizeof(*ep)-*n); else #endif /* NGZIP */ { lseek(fd,*n,0); *n += read (fd, buf+*n, sizeof(*ep)-*n); } if (*n < sizeof(*ep)) { #if NGZIP > 0 if(myflags&ZFLAG) gz_close(fd); #endif /* NGZIP */ return -1; } } /* check header validity */ if (ep->e_ident[EI_MAG0] != ELFMAG0 || ep->e_ident[EI_MAG1] != ELFMAG1 || ep->e_ident[EI_MAG2] != ELFMAG2 || ep->e_ident[EI_MAG3] != ELFMAG3) { #if NGZIP > 0 if(myflags&ZFLAG) gz_close(fd); #endif /* NGZIP */ return (-1); } fprintf (stderr, "(elf)\n"); { char *nogood = (char *)0; if (ep->e_ident[EI_CLASS] == ELFCLASS64) return load_elf64(fd, buf, n, flags); if (ep->e_ident[EI_CLASS] != ELFCLASS32) nogood = "not 32-bit"; else if ( #if BYTE_ORDER == BIG_ENDIAN ep->e_ident[EI_DATA] != ELFDATA2MSB #endif #if BYTE_ORDER == LITTLE_ENDIAN ep->e_ident[EI_DATA] != ELFDATA2LSB #endif ) nogood = "incorrect endianess"; else if (ep->e_ident[EI_VERSION] != EV_CURRENT) nogood = "version not current"; else if ( #ifdef powerpc ep->e_machine != EM_PPC #else /* default is MIPS */ #define GREENHILLS_HACK #ifdef GREENHILLS_HACK ep->e_machine != 10 && #endif ep->e_machine != EM_MIPS #endif ) nogood = "incorrect machine type"; if (nogood) { fprintf (stderr, "Invalid ELF: %s\n", nogood); #if NGZIP > 0 if(myflags&ZFLAG) gz_close(fd); #endif /* NGZIP */ return -2; } } /* Is there a program header? */ if (ep->e_phoff == 0 || ep->e_phnum == 0 || ep->e_phentsize != sizeof(Elf32_Phdr)) { fprintf (stderr, "missing program header (not executable)\n"); #if NGZIP > 0 if(myflags&ZFLAG) gz_close(fd); #endif /* NGZIP */ return (-2); } /* Load program header */ #if _ORIG_CODE_ nbytes = ep->e_phnum * sizeof(Elf32_Phdr); #else /* XXX: We need to figure out why it works by adding 32!!!! */ nbytes = ep->e_phnum * sizeof(Elf32_Phdr)+32; #endif phtab = (Elf32_Phdr *) malloc (nbytes); if (!phtab) { fprintf (stderr,"\nnot enough memory to read program headers"); #if NGZIP > 0 if(myflags&ZFLAG) gz_close(fd); #endif /* NGZIP */ return (-2); } #if NGZIP > 0 if(myflags&ZFLAG){ if (gz_lseek (fd, ep->e_phoff, SEEK_SET) != ep->e_phoff || gz_read (fd, (void *)phtab, nbytes) != nbytes) { perror ("program header"); free (phtab); gz_close(fd); return (-2); } }else #endif /* NGZIP */ if (lseek (fd, ep->e_phoff, SEEK_SET) != ep->e_phoff || read (fd, (void *)phtab, nbytes) != nbytes) { perror ("program header"); free (phtab); return (-2); } /* * From now on we've got no guarantee about the file order, * even where the section header is. Hopefully most linkers * will put the section header after the program header, when * they know that the executable is not demand paged. We assume * that the symbol and string tables always follow the program * segments. */ /* read section table (if before first program segment) */ if (!(flags & NFLAG) && ep->e_shoff < phtab[0].p_offset) shtab = elfgetshdr (fd, ep); /* load program segments */ if (!(flags & YFLAG)) { /* We cope with a badly sorted program header, as produced by * older versions of the GNU linker, by loading the segments * in file offset order, not in program header order. */ while (1) { Elf32_Off lowest_offset = ~0; Elf32_Phdr *ph = 0; /* find nearest loadable segment */ for (i = 0; i < ep->e_phnum; i++) if (phtab[i].p_type == PT_LOAD && phtab[i].p_offset < lowest_offset) { ph = &phtab[i]; lowest_offset = ph->p_offset; } if (!ph) break; /* none found, finished */ /* load the segment */ if (ph->p_filesz) { #if NGZIP > 0 if(myflags&ZFLAG){ if (gz_lseek (fd, ph->p_offset, SEEK_SET) != ph->p_offset) { fprintf (stderr, "seek failed (corrupt object file?)\n"); if (shtab) free (shtab); free (phtab); gz_close(fd); return (-2); } }else #endif /* NGZIP */ if (lseek (fd, ph->p_offset, SEEK_SET) != ph->p_offset) { fprintf (stderr, "seek failed (corrupt object file?)\n"); if (shtab) free (shtab); free (phtab); return (-2); } if (bootread (fd, (void *)ph->p_vaddr, ph->p_filesz) != ph->p_filesz) { if (shtab) free (shtab); free (phtab); #if NGZIP > 0 if(myflags&ZFLAG) gz_close(fd); #endif /* NGZIP */ return (-2); } } if((ph->p_vaddr + ph->p_memsz) > highest_load) { highest_load = ph->p_vaddr + ph->p_memsz; } if (ph->p_filesz < ph->p_memsz) bootclear (fd, (void *)ph->p_vaddr + ph->p_filesz, ph->p_memsz - ph->p_filesz); ph->p_type = PT_NULL; /* remove from consideration */ } } if (flags & KFLAG) { highest_load = roundup(highest_load, sizeof(long)); tablebase = highest_load; } if (!(flags & NFLAG)) { /* read section table (if after last program segment) */ if (!shtab) shtab = elfgetshdr (fd, ep); if (shtab) { elfreadsyms (fd, ep, shtab, flags); free (shtab); } } free (phtab); #if NGZIP > 0 if(myflags&ZFLAG) gz_close(fd); #endif /* NGZIP */ return (ep->e_entry + dl_offset); }
static int devcp(int argc, char **argv) { char *buf; int fp0, fp1; int n, i; int bs = 0x20000; int seek = 0, skip = 0; char *fsrc = 0, *fdst = 0; unsigned int count = -1, nowcount = 0; char pstr[80] = ""; int quiet = 0; yaf_use = 0; //lxy yaf_w = 1; #if NGZIP > 0 int unzip=0; #endif if (argc < 3) return -1; fsrc = argv[1]; fdst = argv[2]; if (!fsrc||!fdst) return -1; fp0 = open(fsrc, O_RDONLY); fp1 = open(fdst, O_RDWR|O_CREAT|O_TRUNC); if (!strncmp(_file[fp1].fs->devname, "mtd", 3)) { mtdpriv *priv; mtdfile *p; priv = (mtdpriv *)_file[fp1].data; p = priv->file; if (p->mtd->type == MTD_NANDFLASH) { bs = p->mtd->erasesize; } } for (i=3; i<argc; i++) { if(!strncmp(argv[i],"bs=",3)) bs=strtoul(&argv[i][3],0,0); else if(!strncmp(argv[i],"count=",6)) count=strtoul(&argv[i][6],0,0); else if(!strncmp(argv[i],"skip=",5)) skip=strtoul(&argv[i][5],0,0); else if(!strncmp(argv[i],"seek=",5)) seek=strtoul(&argv[i][5],0,0); else if(!strncmp(argv[i],"quiet=",6)) quiet=strtoul(&argv[i][6],0,0); #if NGZIP > 0 else if(!strcmp(argv[i],"unzip=1")) unzip=1; #endif else if (!strcmp(argv[i], "yaf")) //lxy { yaf_use = 1; bs += (4 * 1024); } else if (!strcmp(argv[i], "nw")) //lxy yaf_w = 0; } buf = malloc(bs); // buf = (char *)(((long)malloc(bs + 32) + 32) & ~(32-1) | 0xa0000000); // buf = 0xa1000000; if (!buf) { printf("malloc failed!,please set heaptop bigger\n"); return -1; } if (!fp0||!fp1) { printf("open file error!\n"); free(buf); return -1; } lseek(fp0, skip*bs, SEEK_SET); lseek(fp1, seek*bs, SEEK_SET); #if NGZIP > 0 if (unzip) if (gz_open(fp0) == -1) unzip = 0; #endif while(count--) { int rcount=0; char *pnow=buf; #if NGZIP > 0 if (unzip) while (rcount<bs) { n = gz_read(fp0, pnow, bs); if (n <= 0) break; rcount += n; pnow += n; } else #endif while (rcount<bs) { n = read(fp0, pnow, bs-rcount); if (n <= 0) break; rcount += n; pnow += n; } nowcount += rcount; if (!(strstr(argv[1],"/dev/tty") || strstr(argv[2],"/dev/tty") || quiet)) { int i; for (i=0; i<strlen(pstr); i++) printf("\b \b"); sprintf(pstr, "%d", nowcount); printf("%s", pstr); } if (write(fp1, buf, rcount) < rcount || rcount <bs) break; } free(buf); #if NGZIP > 0 if (unzip) gz_close(fp0); #endif close(fp0); close(fp1); if (nowcount == 0) //lxy return -1; return 0; }
extern int tar_main(int argc, char **argv) { char** excludeList=NULL; char** extractList=NULL; const char *tarName="-"; const char *cwd=NULL; #if defined BB_FEATURE_TAR_EXCLUDE int excludeListSize=0; FILE *fileList; char file[256]; #endif #if defined BB_FEATURE_TAR_GZIP FILE *comp_file = NULL; int unzipFlag = FALSE; #endif int listFlag = FALSE; int extractFlag = FALSE; int createFlag = FALSE; int verboseFlag = FALSE; int tostdoutFlag = FALSE; int status = FALSE; int opt; #if defined BB_FEATURE_TAR_GZIP pid_t pid; #endif if (argc <= 1) show_usage(); if (argv[1][0] != '-') { char *tmp = xmalloc(strlen(argv[1]) + 2); tmp[0] = '-'; strcpy(tmp + 1, argv[1]); argv[1] = tmp; } while ( #ifndef BB_FEATURE_TAR_EXCLUDE (opt = getopt(argc, argv, "cxtzvOf:pC:")) #else (opt = getopt_long(argc, argv, "cxtzvOf:X:pC:", longopts, NULL)) #endif > 0) { switch (opt) { case 'c': if (extractFlag == TRUE || listFlag == TRUE) goto flagError; createFlag = TRUE; break; case 'x': if (listFlag == TRUE || createFlag == TRUE) goto flagError; extractFlag = TRUE; break; case 't': if (extractFlag == TRUE || createFlag == TRUE) goto flagError; listFlag = TRUE; break; #ifdef BB_FEATURE_TAR_GZIP case 'z': unzipFlag = TRUE; break; #endif case 'v': verboseFlag = TRUE; break; case 'O': tostdoutFlag = TRUE; break; case 'f': if (*tarName != '-') error_msg_and_die( "Only one 'f' option allowed"); tarName = optarg; break; #if defined BB_FEATURE_TAR_EXCLUDE case 'e': excludeList=xrealloc( excludeList, sizeof(char *) * (excludeListSize+2)); excludeList[excludeListSize] = optarg; /* Tack a NULL onto the end of the list */ excludeList[++excludeListSize] = NULL; case 'X': fileList = xfopen(optarg, "r"); while (fgets(file, sizeof(file), fileList) != NULL) { excludeList = xrealloc(excludeList, sizeof(char *) * (excludeListSize+2)); chomp(file); excludeList[excludeListSize] = xstrdup(file); /* Tack a NULL onto the end of the list */ excludeList[++excludeListSize] = NULL; } fclose(fileList); break; #endif case 'p': break; case 'C': cwd = xgetcwd((char *)cwd); if (chdir(optarg)) { printf("cd: %s: %s\n", optarg, strerror(errno)); return EXIT_FAILURE; } break; default: show_usage(); } } /* * Do the correct type of action supplying the rest of the * command line arguments as the list of files to process. */ if (createFlag == TRUE) { #ifndef BB_FEATURE_TAR_CREATE error_msg_and_die( "This version of tar was not compiled with tar creation support."); #else #ifdef BB_FEATURE_TAR_GZIP if (unzipFlag==TRUE) error_msg_and_die("Creation of compressed not internally support by tar, pipe to busybox gunzip"); #endif status = writeTarFile(tarName, verboseFlag, argv + optind, excludeList); #endif } if (listFlag == TRUE || extractFlag == TRUE) { int tarFd; if (argv[optind]) extractList = argv + optind; /* Open the tar file for reading. */ if (!strcmp(tarName, "-")) tarFd = fileno(stdin); else tarFd = open(tarName, O_RDONLY); if (tarFd < 0) perror_msg_and_die("Error opening '%s'", tarName); #ifdef BB_FEATURE_TAR_GZIP /* unzip tarFd in a seperate process */ if (unzipFlag == TRUE) { comp_file = fdopen(tarFd, "r"); /* set the buffer size */ setvbuf(comp_file, NULL, _IOFBF, 0x8000); if ((tarFd = fileno(gz_open(comp_file, &pid))) == EXIT_FAILURE) { error_msg_and_die("Couldnt unzip file"); } } #endif status = readTarFile(tarFd, extractFlag, listFlag, tostdoutFlag, verboseFlag, extractList, excludeList); close(tarFd); #ifdef BB_FEATURE_TAR_GZIP if (unzipFlag == TRUE) { gz_close(pid); fclose(comp_file); } #endif } if (cwd) chdir(cwd); if (status == TRUE) return EXIT_SUCCESS; else return EXIT_FAILURE; flagError: error_msg_and_die( "Exactly one of 'c', 'x' or 't' must be specified"); }