static int list(const char *filename, int arglen, char *args[]) { xar_t x; xar_iter_t i; xar_file_t f; x = xar_open(filename, READ); if( !x ) { fprintf(stderr, "Error opening xar archive: %s\n", filename); exit(1); } i = xar_iter_new(); if( !i ) { fprintf(stderr, "Error creating xar iterator\n"); exit(1); } for(f = xar_file_first(x, i); f; f = xar_file_next(i)) { print_file(f); } xar_iter_free(i); xar_close(x); return Err; }
bool InstallChecker::verifyPackage( const QString &filePath, bool ) { QProcess proc; proc.start( "hdiutil", QStringList() << "verify" << filePath ); proc.waitForFinished(); if( proc.exitCode() ) return false; QString path = mountPackage( filePath ); if( path.isEmpty() ) return false; xar_t xar = xar_open( path.toUtf8().constData(), 0 ); if( !xar ) return false; QSslCertificate cert; xar_signature_t sig = xar_signature_first( xar ); int32_t count = xar_signature_get_x509certificate_count( sig ); for( int32_t i = 0; i < count; ++i ) { uint32_t size = 0; const uint8_t *data = 0; if( xar_signature_get_x509certificate_data( sig, i, &data, &size ) ) continue; QSslCertificate c( QByteArray( (const char*)data, size ), QSsl::Der ); #if QT_VERSION >= 0x050000 QString cn = c.subjectInfo( QSslCertificate::CommonName ).value(0); #else QString cn = c.subjectInfo( QSslCertificate::CommonName ); #endif if( cn == "Estonian Informatics Centre" || cn == "Developer ID Installer: Riigi Infosüsteemi Amet" ) cert = c; } if( cert.isNull() ) { xar_close( xar ); return false; } uint8_t *data = 0, *signature = 0; uint32_t dataSize = 0, signatureSize = 0; off_t offset = 0; if( xar_signature_copy_signed_data( sig, &data, &dataSize, &signature, &signatureSize, &offset ) ) { xar_close( xar ); return false; } int result = RSA_verify( NID_sha1, data, dataSize, signature, signatureSize, (RSA*)cert.publicKey().handle() ); xar_close( xar ); free( data ); free( signature ); return result; }
static int dumptoc(const char *filename, const char* tocfile) { xar_t x; x = xar_open(filename, READ); if( !x ) { fprintf(stderr, "Error opening xar archive: %s\n", filename); exit(1); } xar_serialize(x, tocfile); xar_close(x); return Err; }
bool IsXarFile(std::string file) { #ifdef HAVE_LIBXAR xar_t x = xar_open(file.c_str(), READ); if (x == nullptr) return false; xar_close(x); return true; #else return false; #endif }
bool WriteTOC(std::string xarFile, std::string tocFile) { #ifdef HAVE_LIBXAR xar_t x = xar_open(xarFile.c_str(), READ); if (x == nullptr) return false; xar_serialize(x, tocFile.c_str()); xar_close(x); return true; #else return false; #endif }
/* belated_sign Prepare a previously unsigned archive for signing by creating a signature placeholder and inserting the certificates. Since libxar is currently not capable of doing this directly, we have to create a new xar archive, copy all the files and options from the current archive, and sign the new archive */ static void belated_sign(const char *filename) { xar_t x = xar_open(filename, READ); if ( x == NULL ) { fprintf(stderr, "Could not open archive %s!\n", filename); exit(1); } xar_signature_t sig = xar_signature_first(x); if ( sig ) { fprintf(stderr, "Archive has already been signed. Use --replace-sign instead.\n"); exit(E_SIGEXISTS); } xar_close(x); replace_sign(filename); }
static void extract_certs(char *filename, char *cert_base_path) { xar_signature_t sig; xar_t x; int32_t count; int i; const uint8_t *cert_data; uint32_t cert_len; FILE *file; char *cert_path; // open xar, get signature x = xar_open(filename, READ); if ( x == NULL ) { fprintf(stderr, "Could not open %s to extract certificates!\n", filename); exit(1); } sig = xar_signature_first(x); if ( !sig ) { fprintf(stderr, "No signatures found to extract data from.\n"); exit(E_NOSIG); } // iterate through all certificates associated with that signature, write them to disk count = xar_signature_get_x509certificate_count(sig); if (!count) { fprintf(stderr, "Signature bears no certificates. Odd.\n"); exit(1); } for (i=0; i<count; i++) { xar_signature_get_x509certificate_data(sig, i, &cert_data, &cert_len); asprintf(&cert_path, "%s/cert%02i", cert_base_path, i); file = fopen(cert_path, "w"); if (!file) { fprintf(stderr, "Could not save certificate %i to %s.\n", i, cert_path); exit(1); } int n = fwrite(cert_data, cert_len, 1, file); if (n < 0) { fprintf(stderr, "Failed to write certificate to %s (fwrite() returned %i)!\n", cert_path, n); exit(1); } fclose(file); free(cert_path); } // clean up xar_close(x); }
static void inject_signature(const char *xar_path, const char *sig_path) { // since there is no API to insert a signature other than during signingCallback time, we have to // inject it by editing the raw file int buffer_size = 1024; void *buffer = malloc(buffer_size); FILE *sig, *xar; off_t signedDataOffset; xar_t x; int i; printf("inject_signature(%s, %s)",xar_path,sig_path); // open xar via the API first to determine the signature offset x = xar_open(xar_path, READ); if ( x == NULL ) { fprintf(stderr, "Could not open xar archive %s to get signature offset!\n", xar_path); exit(1); } signedDataOffset = get_sig_offset(x); xar_close(x); // then re-open xar and signature files raw... sig = fopen(sig_path, "r"); if (!sig) { fprintf(stderr, "Could not open %s for reading signature!\n", sig_path); exit(1); } xar = fopen(xar_path, "r+"); if (!xar) { fprintf(stderr, "Could not open xar archive %s for injecting signature!\n", xar_path); exit(1); } // ...and inject the signature fseek(xar, signedDataOffset, SEEK_SET); do { i = fread(buffer, 1, buffer_size, sig); if (ferror(sig)) { fprintf(stderr, "Failed to read signature from %s!\n", sig_path); exit(1); } fwrite(buffer, 1, i, xar); } while (!feof(sig)); fclose(sig); fclose(xar); free(buffer); }
static int list_subdocs(const char *filename) { xar_t x; xar_subdoc_t s; x = xar_open(filename, READ); if( !x ) { fprintf(stderr, "Error opening xar archive: %s\n", filename); exit(1); } for(s = xar_subdoc_first(x); s; s = xar_subdoc_next(s)) { printf("%s\n", xar_subdoc_name(s)); } xar_close(x); return Err; }
int main(int argc, char *argv[]) { char *file = argv[1]; xar_t x; xar_iter_t ifile, iprop, iattr; xar_file_t f; const char *key; int fd; off_t off; xar_header_t hdr; x = xar_open(file, READ); if( !x ) { fprintf(stderr, "Error opening archive\n"); exit(1); } fd = open(file, O_RDONLY); if( fd < 0 ) { fprintf(stderr, "Error opening archive\n"); exit(1); } read(fd, &hdr, sizeof(hdr)); hdr.size = htons(hdr.size); hdr.toc_length_compressed = xar_ntoh64(hdr.toc_length_compressed); HeapOff = hdr.size + hdr.toc_length_compressed; ifile = xar_iter_new(); if( !ifile ) { fprintf(stderr, "Error creating file iterator"); exit(1); } for(f = xar_file_first(x, ifile); f; f = xar_file_next(ifile)) { prop_check(fd, x, f); } }
static int archive(const char *filename, int arglen, char *args[]) { xar_t x; FTS *fts; FTSENT *ent; int flags; struct lnode *i; const char *default_compression; x = xar_open(filename, WRITE); if( !x ) { fprintf(stderr, "Error creating archive %s\n", filename); exit(1); } if ( SigSize ) { xar_signature_t sig = xar_signature_new(x, "RSA", SigSize, &signingCallback, NULL); if ( LeafCertPath ) insert_cert(sig, LeafCertPath); if ( IntermediateCertPath ) insert_cert(sig, IntermediateCertPath); } if( Toccksum ) xar_opt_set(x, XAR_OPT_TOCCKSUM, Toccksum); if( Compression ) xar_opt_set(x, XAR_OPT_COMPRESSION, Compression); if( Coalesce ) xar_opt_set(x, XAR_OPT_COALESCE, "true"); if( LinkSame ) xar_opt_set(x, XAR_OPT_LINKSAME, "true"); if ( Rsize != NULL ) xar_opt_set(x, XAR_OPT_RSIZE, Rsize); xar_register_errhandler(x, err_callback, NULL); if( Subdoc ) add_subdoc(x); if( Perms == SYMBOLIC ) { xar_opt_set(x, XAR_OPT_OWNERSHIP, XAR_OPT_VAL_SYMBOLIC); } if( Perms == NUMERIC ) { xar_opt_set(x, XAR_OPT_OWNERSHIP, XAR_OPT_VAL_NUMERIC); } default_compression = strdup(xar_opt_get(x, XAR_OPT_COMPRESSION)); if( !default_compression ) default_compression = strdup(XAR_OPT_VAL_GZIP); flags = FTS_PHYSICAL|FTS_NOSTAT|FTS_NOCHDIR; if( Local ) flags |= FTS_XDEV; fts = fts_open(args, flags, NULL); if( !fts ) { fprintf(stderr, "Error traversing file tree\n"); exit(1); } while( (ent = fts_read(fts)) ) { xar_file_t f; int exclude_match = 1; int nocompress_match = 1; if( ent->fts_info == FTS_DP ) continue; if( strcmp(ent->fts_path, "/") == 0 ) continue; if( strcmp(ent->fts_path, ".") == 0 ) continue; for( i = Exclude; i; i=i->next ) { exclude_match = regexec(&i->reg, ent->fts_path, 0, NULL, 0); if( !exclude_match ) break; } if( !exclude_match ) { if( Verbose ) printf("Excluding %s\n", ent->fts_path); continue; } for( i = NoCompress; i; i=i->next ) { nocompress_match = regexec(&i->reg, ent->fts_path, 0, NULL, 0); if( !nocompress_match ) { xar_opt_set(x, XAR_OPT_COMPRESSION, XAR_OPT_VAL_NONE); break; } } f = xar_add(x, ent->fts_path); if( !f ) { fprintf(stderr, "Error adding file %s\n", ent->fts_path); } else { print_file(f); } if( !nocompress_match ) xar_opt_set(x, XAR_OPT_COMPRESSION, default_compression); } fts_close(fts); if( xar_close(x) != 0 ) { fprintf(stderr, "Error creating the archive\n"); if( !Err ) Err = 42; } free((char *)default_compression); for( i = Exclude; i; ) { struct lnode *tmp; regfree(&i->reg); tmp = i; i = i->next; free(tmp); } for( i = NoCompress; i; ) { struct lnode *tmp; regfree(&i->reg); tmp = i; i = i->next; free(tmp); } if ( SigOffsetDumpPath ) { x = xar_open(filename, READ); if( !x ) { fprintf(stderr, "Error re-opening archive %s\n", filename); exit(1); } if (extract_sig_offset(x, SigOffsetDumpPath)) exit(1); } return Err; }
int main(int argc, char *argv[]) { xar_t x; xar_iter_t i; xar_file_t f; xar_stream s; char buffer[8192]; x = xar_open(argv[1], READ); if( !x ) { fprintf(stderr, "Error opening archive\n"); exit(1); } xar_register_errhandler(x, err_callback, NULL); i = xar_iter_new(); if( !i ) { fprintf(stderr, "Error creating xar iterator\n"); exit(1); } for(f = xar_file_first(x, i); f; f = xar_file_next(i)) { char *path; const char *type; int32_t ret; int fd; path = xar_get_path(f); xar_prop_get(f, "type", &type); if( !type ) { fprintf(stderr, "File has no type %s\n", path); free(path); continue; } if( strcmp(type, "file") != 0 ) { fprintf(stderr, "Skipping %s\n", path); free(path); continue; } fprintf(stderr, "Extracting %s\n", path); if( xar_extract_tostream_init(x, f, &s) != XAR_STREAM_OK ) { fprintf(stderr, "Error initializing stream %s\n", path); free(path); continue; } fd = open(path, O_CREAT|O_WRONLY, S_IRUSR|S_IWUSR); if( !fd ) { fprintf(stderr, "Error opening output file %s\n", path); free(path); continue; } s.avail_out = sizeof(buffer); s.next_out = buffer; while( (ret = xar_extract_tostream(&s)) != XAR_STREAM_END ) { if( ret == XAR_STREAM_ERR ) { fprintf(stderr, "Error extracting stream %s\n", path); exit(2); } write(fd, buffer, sizeof(buffer)-s.avail_out); s.avail_out = sizeof(buffer); s.next_out = buffer; } if( xar_extract_tostream_end(&s) != XAR_STREAM_OK ) { fprintf(stderr, "Error ending stream %s\n", path); } close(fd); free(path); } }
static int list(const char *filename, int arglen, char *args[]) { xar_t x; xar_iter_t i; xar_file_t f; int argi = 0; struct lnode *list_files = NULL; struct lnode *list_tail = NULL; struct lnode *lnodei = NULL; for(argi = 0; args[argi]; argi++) { struct lnode *tmp; int err; tmp = malloc(sizeof(struct lnode)); tmp->str = strdup(args[argi]); tmp->next = NULL; err = regcomp(&tmp->reg, tmp->str, REG_NOSUB); if( err ) { char errstr[1024]; regerror(err, &tmp->reg, errstr, sizeof(errstr)); printf("Error with regular expression %s: %s\n", tmp->str, errstr); exit(1); } if( list_files == NULL ) { list_files = tmp; list_tail = tmp; } else { list_tail->next = tmp; list_tail = tmp; } } x = xar_open(filename, READ); if( !x ) { fprintf(stderr, "Error opening xar archive: %s\n", filename); exit(1); } i = xar_iter_new(); if( !i ) { fprintf(stderr, "Error creating xar iterator\n"); exit(1); } for(f = xar_file_first(x, i); f; f = xar_file_next(i)) { int matched = 0; if( args[0] ) { char *path = xar_get_path(f); if (xar_path_issane(path) == 0) { fprintf(stderr, "Warning, archive contains invalid path: %s\n", path); free(path); continue; } for(lnodei = list_files; lnodei != NULL; lnodei = lnodei->next) { int list_match = 1; list_match = regexec(&lnodei->reg, path, 0, NULL, 0); if( !list_match ) { matched = 1; break; } } free(path); } else { matched = 1; } if( matched ) print_file(x, f); } xar_iter_free(i); xar_close(x); for(lnodei = list_files; lnodei != NULL; ) { struct lnode *tmp; free(lnodei->str); regfree(&lnodei->reg); tmp = lnodei; lnodei = lnodei->next; free(tmp); } return Err; }
int main(int argc, char *argv[]) { int ret; char *filename = NULL; char command = 0, c; char **args; const char *tocfile = NULL; int arglen, i, err; xar_t x; int loptind = 0; int required_dash_f = 0; /* This release requires us to use -f */ struct lnode *tmp; long int longtmp; struct option o[] = { {"toc-cksum", 1, 0, 1}, {"dump-toc", 1, 0, 'd'}, {"compression", 1, 0, 2}, {"list-subdocs", 0, 0, 3}, {"help", 0, 0, 'h'}, {"version", 0, 0, 4}, {"dump-header", 0, 0, 5}, {"extract-subdoc", 1, 0, 6}, {"exclude", 1, 0, 7}, {"rsize", 1, 0, 8}, {"coalesce-heap", 0, 0, 9}, {"link-same", 0, 0, 10}, {"no-compress", 1, 0, 11}, {"prop-include", 1, 0, 12}, {"prop-exclude", 1, 0, 13}, {"distribution", 0, 0, 14}, {"keep-existing", 0, 0, 15}, {"keep-setuid", 0, 0, 16}, {"compression-args", 1, 0, 17}, { 0, 0, 0, 0} }; if( argc < 2 ) { usage(argv[0]); exit(1); } while( (c = getopt_long(argc, argv, "axcC:vtjzf:hpPln:s:d:vk", o, &loptind)) != -1 ) { switch(c) { case 1 : if( !optarg ) { usage(argv[0]); exit(1); } if( (strcmp(optarg, XAR_OPT_VAL_NONE) != 0) && (strcmp(optarg, XAR_OPT_VAL_SHA1) != 0) && (strcmp(optarg, XAR_OPT_VAL_MD5) != 0) ) { usage(argv[0]); exit(1); } Toccksum = optarg; break; case 2 : if( !optarg ) { usage(argv[0]); exit(1); } if( (strcmp(optarg, XAR_OPT_VAL_NONE) != 0) && (strcmp(optarg, XAR_OPT_VAL_GZIP) != 0) && (strcmp(optarg, XAR_OPT_VAL_BZIP) != 0) && (strcmp(optarg, XAR_OPT_VAL_LZMA) != 0) ) { usage(argv[0]); exit(1); } Compression = optarg; break; case 3 : if( command && (command != 3) ) { fprintf(stderr, "Conflicting commands specified\n"); exit(1); } command = 3; break; case 4 : print_version(); exit(0); case 'd': if( !optarg ) { usage(argv[0]); exit(1); } tocfile = optarg; command = 'd'; break; case 5 : command = 5; break; case 6 : SubdocName = optarg; asprintf(&Subdoc, "%s.xml", SubdocName); if( !command ) command = 6; break; case 7 : tmp = malloc(sizeof(struct lnode)); tmp->str = optarg; tmp->next = NULL; err = regcomp(&tmp->reg, tmp->str, REG_NOSUB); if( err ) { char errstr[1024]; regerror(err, &tmp->reg, errstr, sizeof(errstr)); printf("Error with regular expression %s: %s\n", tmp->str, errstr); exit(1); } if( Exclude == NULL ) { Exclude = tmp; Exclude_Tail = tmp; } else { Exclude_Tail->next = tmp; Exclude_Tail = tmp; } break; case 8 : if ( !optarg ) { usage(argv[0]); exit(1); } longtmp = strtol(optarg, NULL, 10); if( (((longtmp == LONG_MIN) || (longtmp == LONG_MAX)) && (errno == ERANGE)) || (longtmp < 1) ) { fprintf(stderr, "Invalid rsize value: %s\n", optarg); exit(5); } Rsize = optarg; break; case 9 : Coalesce = 1; break; case 10 : LinkSame = 1; break; case 11 : tmp = malloc(sizeof(struct lnode)); tmp->str = optarg; tmp->next = NULL; err = regcomp(&tmp->reg, tmp->str, REG_NOSUB); if( err ) { char errstr[1024]; regerror(err, &tmp->reg, errstr, sizeof(errstr)); printf("Error with regular expression %s: %s\n", tmp->str, errstr); exit(1); } if( NoCompress == NULL ) { NoCompress = tmp; NoCompress_Tail = tmp; } else { NoCompress_Tail->next = tmp; NoCompress_Tail = tmp; } break; case 12 : tmp = malloc(sizeof(struct lnode)); tmp->str = optarg; tmp->next = NULL; if( PropInclude == NULL ) { PropInclude = tmp; PropInclude_Tail = tmp; } else { PropInclude_Tail->next = tmp; PropInclude_Tail = tmp; } break; case 13 : tmp = malloc(sizeof(struct lnode)); tmp->str = optarg; tmp->next = NULL; if( PropExclude == NULL ) { PropExclude = tmp; PropExclude_Tail = tmp; } else { PropExclude_Tail->next = tmp; PropExclude_Tail = tmp; } break; case 14 : { char *props[] = { "type", "data", "mode", "name" }; int i; for( i = 0; i < 4; i++ ) { tmp = malloc(sizeof(struct lnode)); tmp->str = strdup(props[i]); tmp->next = NULL; if( PropInclude == NULL ) { PropInclude = tmp; PropInclude_Tail = tmp; } else { PropInclude_Tail->next = tmp; PropInclude_Tail = tmp; } } } break; case 'k': case 15 : NoOverwrite++; break; case 16 : SaveSuid++; break; case 17 : CompressionArg = optarg; break; case 'C': if( !optarg ) { usage(argv[0]); exit(1); } Chdir = optarg; break; case 'c': case 'x': case 't': if( command && (command != 's') ) { usage(argv[0]); fprintf(stderr, "Conflicting command flags: %c and %c specified\n", c, command); exit(1); } if( c == 't' ) List = 1; command = c; break; case 'a': Compression = "lzma"; break; case 'j': Compression = "bzip2"; break; case 'z': Compression = "gzip"; break; case 'f': required_dash_f = 1; filename = optarg; break; case 'p': Perms = SYMBOLIC; break; case 'P': Perms = NUMERIC; break; case 'l': Local = 1; break; case 'n': SubdocName = optarg; break; case 's': Subdoc = optarg; if( !command ) command = 's'; break; case 'v': Verbose++; break; case 'h': default: usage(argv[0]); exit(1); } } if (! required_dash_f) { usage(argv[0]); fprintf(stderr, "\n -f option is REQUIRED\n"); exit(1); } switch(command) { case 5 : return dump_header(filename); case 3 : return list_subdocs(filename); case 'c': if( optind == argc ) { usage(argv[0]); fprintf(stderr, "No files to operate on.\n"); exit(1); } arglen = argc - optind; args = malloc(sizeof(char*) * (arglen+1)); memset(args, 0, sizeof(char*) * (arglen+1)); for( i = 0; i < arglen; i++ ) args[i] = strdup(argv[optind + i]); return archive(filename, arglen, args); case 'd': if( !tocfile ) { usage(argv[0]); exit(1); } return dumptoc(filename, tocfile); case 'x': arglen = argc - optind; args = malloc(sizeof(char*) * (arglen+1)); for( i = 0; i < arglen; i++ ) args[i] = strdup(argv[optind + i]); args[i] = NULL; return extract(filename, arglen, args); case 't': arglen = argc - optind; args = calloc(sizeof(char*) * (arglen+1),1); for( i = 0; i < arglen; i++ ) args[i] = strdup(argv[optind + i]); ret = list(filename, arglen, args); for( i = 0; i < arglen; i++ ) free(args[i]); case 6 : case 's': x = xar_open(filename, READ); if( !x ) { fprintf(stderr, "Error opening xar archive: %s\n", filename); exit(1); } xar_register_errhandler(x, err_callback, NULL); extract_subdoc(x, SubdocName); xar_close(x); exit(Err); break; default: usage(argv[0]); fprintf(stderr, "Unrecognized command.\n"); exit(1); } /* unreached */ exit(0); }
static int extract(const char *filename, int arglen, char *args[]) { xar_t x; xar_iter_t i; xar_file_t f; int files_extracted = 0; int argi; struct lnode *extract_files = NULL; struct lnode *extract_tail = NULL; struct lnode *lnodei = NULL; struct lnode *dirs = NULL; for(argi = 0; args[argi]; argi++) { struct lnode *tmp; int err; tmp = malloc(sizeof(struct lnode)); tmp->str = strdup(args[argi]); tmp->next = NULL; err = regcomp(&tmp->reg, tmp->str, REG_NOSUB); if( err ) { char errstr[1024]; regerror(err, &tmp->reg, errstr, sizeof(errstr)); printf("Error with regular expression %s: %s\n", tmp->str, errstr); exit(1); } if( extract_files == NULL ) { extract_files = tmp; extract_tail = tmp; } else { extract_tail->next = tmp; extract_tail = tmp; } /* Add a clause for recursive extraction */ tmp = malloc(sizeof(struct lnode)); asprintf(&tmp->str, "%s/.*", args[argi]); tmp->next = NULL; err = regcomp(&tmp->reg, tmp->str, REG_NOSUB); if( err ) { char errstr[1024]; regerror(err, &tmp->reg, errstr, sizeof(errstr)); printf("Error with regular expression %s: %s\n", tmp->str, errstr); exit(1); } if( extract_files == NULL ) { extract_files = tmp; extract_tail = tmp; } else { extract_tail->next = tmp; extract_tail = tmp; } } x = xar_open(filename, READ); if( !x ) { fprintf(stderr, "Error opening xar archive: %s\n", filename); exit(1); } if(Chdir) { if( chdir(Chdir) != 0 ) { fprintf(stderr, "Unable to chdir to %s\n", Chdir); exit(1); } } xar_register_errhandler(x, err_callback, NULL); if( Perms == SYMBOLIC ) { xar_opt_set(x, XAR_OPT_OWNERSHIP, XAR_OPT_VAL_SYMBOLIC); } if( Perms == NUMERIC ) { xar_opt_set(x, XAR_OPT_OWNERSHIP, XAR_OPT_VAL_NUMERIC); } if ( Rsize != NULL ) { xar_opt_set(x, XAR_OPT_RSIZE, Rsize); } if( SaveSuid ) { xar_opt_set(x, XAR_OPT_SAVESUID, XAR_OPT_VAL_TRUE); } i = xar_iter_new(); if( !i ) { fprintf(stderr, "Error creating xar iterator\n"); exit(1); } for(f = xar_file_first(x, i); f; f = xar_file_next(i)) { int matched = 0; int exclude_match = 1; struct lnode *i; char *path = xar_get_path(f); if( args[0] ) { for(i = extract_files; i != NULL; i = i->next) { int extract_match = 1; extract_match = regexec(&i->reg, path, 0, NULL, 0); if( !extract_match ) { matched = 1; break; } } } else { matched = 1; } for( i = Exclude; i; i=i->next ) { exclude_match = regexec(&i->reg, path, 0, NULL, 0); if( !exclude_match ) break; } if( !exclude_match ) { if( Verbose ) printf("Excluding %s\n", path); free(path); continue; } if (!xar_path_issane(path)) { if (Verbose) printf("Warning, not extracting file \"%s\" because it's path is invalid.\n", path); free(path); continue; } if( matched ) { struct stat sb; if( NoOverwrite && (lstat(path, &sb) == 0) ) { printf("%s already exists, not overwriting\n", path); } else { const char *prop = NULL; int deferred = 0; if( xar_prop_get(f, "type", &prop) == 0 ) { if( strcmp(prop, "directory") == 0 ) { struct lnode *tmpl = calloc(sizeof(struct lnode),1); tmpl->str = (char *)f; tmpl->next = dirs; dirs = tmpl; deferred = 1; } } if( ! deferred ) { files_extracted++; print_file(x, f); xar_extract(x, f); } } } free(path); } for(lnodei = dirs; lnodei; lnodei = lnodei->next) { files_extracted++; print_file(x,(xar_file_t)lnodei->str); xar_extract(x, (xar_file_t)lnodei->str); } if( args[0] && (files_extracted == 0) ) { fprintf(stderr, "No files matched extraction criteria.\n"); Err = 3; } if( Subdoc ) extract_subdoc(x, NULL); xar_iter_free(i); if( xar_close(x) != 0 ) { fprintf(stderr, "Error extracting the archive\n"); if( !Err ) Err = 42; } for(lnodei = extract_files; lnodei != NULL; ) { struct lnode *tmp; free(lnodei->str); regfree(&lnodei->reg); tmp = lnodei; lnodei = lnodei->next; free(tmp); } return Err; }
int main(int argc, char *argv[]) { char *filename = NULL; char *sig_path = NULL; char *cert_path = NULL; char command = 0, c; char **args; const char *tocfile = NULL; int arglen, i, err; xar_t x; int loptind = 0; int required_dash_f = 0; /* This release requires us to use -f */ struct lnode *tmp; long int longtmp; struct stat stat_struct; struct option o[] = { {"toc-cksum", 1, 0, 1}, {"dump-toc", 1, 0, 'd'}, {"compression", 1, 0, 2}, {"list-subdocs", 0, 0, 3}, {"help", 0, 0, 'h'}, {"version", 0, 0, 4}, {"dump-header", 0, 0, 5}, {"extract-subdoc", 1, 0, 6}, {"exclude", 1, 0, 7}, {"rsize", 1, 0, 8}, {"coalesce-heap", 0, 0, 9}, {"link-same", 0, 0, 10}, {"no-compress", 1, 0, 11}, {"sig-size", 1, 0, 12}, {"data-to-sign", 1, 0, 13}, {"sig-offset", 1, 0, 14}, {"leaf-cert-loc", 1, 0, 15}, {"intermediate-cert-loc", 1, 0, 16}, {"extract-data-to-sign", 0, 0, 17}, {"sign", 0, 0, 18}, {"replace-sign", 0, 0, 19}, {"inject-sig", 1, 0, 20}, {"extract-certs", 1, 0, 21}, { 0, 0, 0, 0} }; if( argc < 2 ) { usage(argv[0]); exit(1); } while( (c = getopt_long(argc, argv, "xcvtf:hpPln:s:d:v", o, &loptind)) != -1 ) { switch(c) { case 1 : if( !optarg ) { usage(argv[0]); exit(1); } if( (strcmp(optarg, XAR_OPT_VAL_NONE) != 0) && (strcmp(optarg, XAR_OPT_VAL_SHA1) != 0) && (strcmp(optarg, XAR_OPT_VAL_MD5) != 0) ) { usage(argv[0]); exit(1); } Toccksum = optarg; break; case 2 : if( !optarg ) { usage(argv[0]); exit(1); } if( (strcmp(optarg, XAR_OPT_VAL_NONE) != 0) && (strcmp(optarg, XAR_OPT_VAL_GZIP) != 0) && (strcmp(optarg, XAR_OPT_VAL_BZIP) != 0) ) { usage(argv[0]); exit(1); } Compression = optarg; break; case 3 : if( command && (command != 3) ) { fprintf(stderr, "Conflicting commands specified\n"); exit(1); } command = 3; break; case 4 : print_version(); exit(0); case 'd': if( !optarg ) { usage(argv[0]); exit(1); } tocfile = optarg; command = 'd'; break; case 5 : command = 5; break; case 6 : SubdocName = optarg; asprintf(&Subdoc, "%s.xml", SubdocName); if( !command ) command = 6; break; case 7 : tmp = malloc(sizeof(struct lnode)); tmp->str = optarg; tmp->next = NULL; err = regcomp(&tmp->reg, tmp->str, REG_NOSUB); if( err ) { char errstr[1024]; regerror(err, &tmp->reg, errstr, sizeof(errstr)); printf("Error with regular expression %s: %s\n", tmp->str, errstr); exit(1); } if( Exclude == NULL ) { Exclude = tmp; Exclude_Tail = tmp; } else { Exclude_Tail->next = tmp; Exclude_Tail = tmp; } break; case 8 : if ( !optarg ) { usage(argv[0]); exit(1); } longtmp = strtol(optarg, NULL, 10); if( (((longtmp == LONG_MIN) || (longtmp == LONG_MAX)) && (errno == ERANGE)) || (longtmp < 1) ) { fprintf(stderr, "Invalid rsize value: %s\n", optarg); exit(5); } Rsize = optarg; break; case 9 : Coalesce = 1; break; case 10 : LinkSame = 1; break; case 11 : tmp = malloc(sizeof(struct lnode)); tmp->str = optarg; tmp->next = NULL; err = regcomp(&tmp->reg, tmp->str, REG_NOSUB); if( err ) { char errstr[1024]; regerror(err, &tmp->reg, errstr, sizeof(errstr)); printf("Error with regular expression %s: %s\n", tmp->str, errstr); exit(1); } if( NoCompress == NULL ) { NoCompress = tmp; NoCompress_Tail = tmp; } else { NoCompress_Tail->next = tmp; NoCompress_Tail = tmp; } break; case 12 : if( !optarg ) { usage(argv[0]); exit(1); } SigSize = strtol(optarg, (char **)NULL, 10); break; case 13 : if( !optarg ) { usage(argv[0]); exit(1); } DataToSignDumpPath = optarg; break; case 14 : if( !optarg ) { usage(argv[0]); exit(1); } SigOffsetDumpPath = optarg; break; case 15 : if( !optarg ) { usage(argv[0]); exit(1); } LeafCertPath = optarg; break; case 16 : if( !optarg ) { usage(argv[0]); exit(1); } IntermediateCertPath = optarg; break; case 17 : // extract-data-to-sign command = 'e'; break; case 18 : // sign DoSign = 1; break; case 19 : // replace-sign command = 'r'; break; case 20 : // inject signature if( !optarg ) { usage(argv[0]); exit(1); } sig_path = optarg; command = 'i'; break; case 21 : // extract-certs if( !optarg ) { usage(argv[0]); exit(1); } cert_path = optarg; stat(cert_path, &stat_struct); if (!(stat_struct.st_mode & S_IFDIR)) { usage(argv[0]); fprintf(stderr, "%s is not a directory.\n", cert_path); exit(1); } command = 'j'; break; case 'c': case 'x': case 't': if( command && (command != 's') ) { usage(argv[0]); fprintf(stderr, "Conflicting command flags: %c and %c specified\n", c, command); exit(1); } if( c == 't' ) Verbose++; command = c; break; case 'f': required_dash_f = 1; filename = optarg; break; case 'p': Perms = SYMBOLIC; break; case 'P': Perms = NUMERIC; break; case 'l': Local = 1; break; case 'n': SubdocName = optarg; break; case 's': Subdoc = optarg; if( !command ) command = 's'; break; case 'v': Verbose++; break; case 'h': default: usage(argv[0]); exit(1); } } if (! required_dash_f) { usage(argv[0]); fprintf(stderr, "\n -f option is REQUIRED\n"); exit(1); } // extract-data-to-sign if ( (command == 'e') && ((!filename) || (!DataToSignDumpPath) || (!SigOffsetDumpPath)) ) { usage(argv[0]); exit(1); } if ( DoSign ) { if ( ( !SigSize || !LeafCertPath || !IntermediateCertPath ) || ((command != 'c') && (!filename)) ) { usage(argv[0]); exit(1); } if (!command) command = 'n'; } if (command == 'r') { /*if ( !SigSize || !LeafCertPath || !IntermediateCertPath || !filename) { usage(argv[0]); exit(1); } xar_t x = xar_open(filename, READ); if ( x == NULL ) { fprintf(stderr, "Could not open archive %s!\n", filename); exit(1); } xar_signature_t sig = xar_signature_first(x); if ( !sig ) { fprintf(stderr, "No signature found to replace.\n"); exit(E_NOSIG); } xar_close(x);*/ } if ((command == 'i') && ((!filename) || (!sig_path))) { usage(argv[0]); exit(1); } if ((command == 'j') && (!filename)) { usage(argv[0]); exit(1); } switch(command) { case 5 : return dump_header(filename); case 3 : return list_subdocs(filename); case 'c': if( optind == argc ) { usage(argv[0]); fprintf(stderr, "No files to operate on.\n"); exit(1); } arglen = argc - optind; args = malloc(sizeof(char*) * (arglen+1)); memset(args, 0, sizeof(char*) * (arglen+1)); for( i = 0; i < arglen; i++ ) args[i] = strdup(argv[optind + i]); return archive(filename, arglen, args); case 'd': if( !tocfile ) { usage(argv[0]); exit(1); } return dumptoc(filename, tocfile); case 'x': arglen = argc - optind; args = malloc(sizeof(char*) * (arglen+1)); for( i = 0; i < arglen; i++ ) args[i] = strdup(argv[optind + i]); args[i] = NULL; return extract(filename, arglen, args); case 't': arglen = argc - optind; args = malloc(sizeof(char*) * (arglen+1)); for( i = 0; i < arglen; i++ ) args[i] = strdup(argv[optind + i]); return list(filename, arglen, args); case 6 : case 's': x = xar_open(filename, READ); if( !x ) { fprintf(stderr, "Error opening xar archive: %s\n", filename); exit(1); } xar_register_errhandler(x, err_callback, NULL); extract_subdoc(x, SubdocName); xar_close(x); exit(Err); break; case 'e': extract_data_to_sign(filename); exit(Err); case 'r': replace_sign(filename); exit(Err); case 'i': inject_signature(filename, sig_path); exit(Err); case 'n': belated_sign(filename); exit(Err); case 'j': extract_certs(filename, cert_path); exit(Err); default: usage(argv[0]); fprintf(stderr, "Unrecognized command.\n"); exit(1); } /* unreached */ exit(0); }
static void extract_data_to_sign(const char *filename) { xar_signature_t sig; off_t signatureOffset; FILE *file; xar_t x; int i; uint32_t dataToSignOffset = 0; uint32_t dataToSignSize = 0; char *buffer = NULL; const char *value; // find signature stub x = xar_open(filename, READ); if ( x == NULL ) { fprintf(stderr, "Could not open %s to extract data to sign!\n", filename); exit(1); } sig = xar_signature_first(x); if ( !sig ) { fprintf(stderr, "No signatures found to extract data from.\n"); exit(E_NOSIG); } // locate data to sign if( 0 != xar_prop_get((xar_file_t)x, "checksum/offset" ,&value) ){ fprintf(stderr, "Could not locate checksum/offset in archive.\n"); exit(1); } dataToSignOffset = xar_get_heap_offset(x); dataToSignOffset += strtoull(value, (char **)NULL, 10); if( 0 != xar_prop_get((xar_file_t)x, "checksum/size" ,&value) ){ fprintf(stderr, "Could not locate checksum/size in archive.\n"); exit(1); } dataToSignSize = strtoull(value, (char **)NULL, 10); // get signature offset (inject signature here) xar_signature_copy_signed_data(sig, NULL, NULL, NULL, NULL, &signatureOffset); signatureOffset += xar_get_heap_offset(x); xar_close(x); // now get data to be signed, using offset and size file = fopen(filename, "r"); if (!file) { fprintf(stderr, "Could not open %s for reading data to sign!\n", filename); exit(1); } fseek(file, dataToSignOffset, SEEK_SET); buffer = malloc(dataToSignSize); i = fread(buffer, dataToSignSize, 1, file); if (i != 1) { fprintf(stderr, "Failed to read data to sign from %s!\n", filename); exit(1); } fclose(file); // save data to sign file = fopen(DataToSignDumpPath, "w"); if (!file) { fprintf(stderr, "Could not open %s for saving data to sign!\n", DataToSignDumpPath); exit(1); } i = fwrite(buffer, dataToSignSize, 1, file); if (i != 1) { fprintf(stderr, "Failed to write data to sign to %s (fwrite() returned %i)!\n", DataToSignDumpPath, i); exit(1); } fclose(file); // save signature offset file = fopen(SigOffsetDumpPath, "w"); if (!file) { fprintf(stderr, "Could not open %s for saving signature offset!\n", SigOffsetDumpPath); exit(1); } i = fprintf(file, "%lli\n", signatureOffset); if (i < 0) { fprintf(stderr, "Failed to write signature offset to %s (fprintf() returned %i)!\n", SigOffsetDumpPath, i); exit(1); } fclose(file); free(buffer); }
/* replace_sign: rip out all current signatures and certs and insert a new pair Since libxar is currently not capable of doing this directly, we have to create a new xar archive, copy all the files and options from the current archive, and sign the new archive */ static void replace_sign(const char *filename) { xar_t old_xar, new_xar; xar_signature_t sig; char *new_xar_path = (char *)malloc(15); strncpy(new_xar_path, "/tmp/xar.XXXXX", 15); new_xar_path = mktemp(new_xar_path); char *systemcall; int err; // open both archives old_xar = xar_open(filename, READ); if ( old_xar == NULL ) { fprintf(stderr, "Could not open archive %s!\n", filename); exit(1); } new_xar = xar_open(new_xar_path, WRITE); if( !new_xar ) { fprintf(stderr, "Error creating new archive %s\n", new_xar_path); exit(1); } // install new signature and new certs in new_xar sig = xar_signature_new(new_xar, "RSA", SigSize, &signingCallback, NULL); if ( LeafCertPath ) insert_cert(sig, LeafCertPath); if ( IntermediateCertPath ) insert_cert(sig, IntermediateCertPath); // copy options char *opts[6] = {XAR_OPT_TOCCKSUM, XAR_OPT_COMPRESSION, XAR_OPT_COALESCE, XAR_OPT_LINKSAME, XAR_OPT_RSIZE, XAR_OPT_OWNERSHIP}; int i; const char *opt; for (i=0; i<6; i++) { opt = xar_opt_get(old_xar, opts[i]); if (opt) xar_opt_set(new_xar, opts[i], opt); } // skip copy subdocs for now since we don't use them yet // copy files xar_iter_t iter = xar_iter_new(); xar_file_t f = xar_file_first(old_xar, iter); // xar_file_next iterates the archive depth-first, i.e. all children are enumerated before the siblings. const char *name; char *f_dirname, *stack_top_dirname; stack s_new = stack_new(); stack s_old = stack_new(); xar_file_t last_copied = NULL, last_added; xar_iter_t loopIter = xar_iter_new(); xar_file_t current_xar_file; for (current_xar_file = xar_file_first(old_xar, loopIter); current_xar_file; current_xar_file = xar_file_next(loopIter)) { printf("old_xar -> %s (parent: %s)\n",xar_get_path(current_xar_file),XAR_FILE(current_xar_file)->parent?xar_get_path(XAR_FILE(current_xar_file)->parent):"(nil)"); } do { // parent is the parent in the new archive! // 3 cases: // 1. the file has no parent. Happens for every file at the top level of the archive. // 2. the file's parent is the last file we added. Happens while descending down a path // 3. the file's parent is one of the ancestors of the last file (and not NULL, that would be case 1) // that means we either go back up the tree and add a sibling of one of the ancestors, or we add a // sibling on the same level xar_prop_get(f, "name", &name); // filename, without any path info if (!XAR_FILE(f)->parent) { // case 1 printf("root: %s\n",xar_get_path(f)); last_added = xar_add_from_archive(new_xar, NULL, name, old_xar, f); last_copied = f; stack_push(s_new, (void *)last_added); stack_push(s_old, (void *)last_copied); } else if (f->parent == last_copied) { // case 2 printf("child: %s -> %s\n",xar_get_path(f->parent),xar_get_path(f)); last_added = xar_add_from_archive(new_xar, last_added, name, old_xar, f); last_copied = f; stack_push(s_new, (void *)last_added); stack_push(s_old, (void *)last_copied); } else { // case 3 printf("searching for parent: %s ?\n",xar_get_path(f)); while (XAR_FILE(f)->parent != XAR_FILE(s_old->top->data)->parent) { printf("popping: %s\n",xar_get_path(XAR_FILE(s_old->top->data))); stack_pop(s_new); stack_pop(s_old); } printf("found: %s -> %s\n",xar_get_path(XAR_FILE(s_new->top->data)),xar_get_path(f)); stack_pop(s_new); stack_pop(s_old); last_added = xar_add_from_archive(new_xar, (xar_file_t)(s_new->top->data), name, old_xar, f); last_copied = f; stack_push(s_new, (void *)last_added); stack_push(s_old, (void *)last_copied); } } while (f = xar_file_next(iter)); loopIter = xar_iter_new(); for (current_xar_file = xar_file_first(new_xar, loopIter); current_xar_file; current_xar_file = xar_file_next(loopIter)) { char * current_path = xar_get_path(current_xar_file); printf("new_xar -> %s\n",current_path); } xar_iter_free(iter); stack_free(s_new); stack_free(s_old); if( xar_close(new_xar) != 0 ) { fprintf(stderr, "Error creating the archive\n"); if( !Err ) Err = 42; } xar_close(old_xar); // write signature offset to file (have to re-open so xar_close can figure out the correct offset) new_xar = xar_open(new_xar_path, READ); if( !new_xar ) { fprintf(stderr, "Error re-opening new archive %s\n", new_xar_path); unlink(new_xar_path); exit(1); } if (extract_sig_offset(new_xar, SigOffsetDumpPath)) { xar_close(new_xar); unlink(new_xar_path); exit(1); } xar_close(new_xar); // delete old archive, move new in its place unlink(filename); asprintf(&systemcall, "cp \"%s\" \"%s\"", new_xar_path, filename); err = system(systemcall); if (err) { fprintf(stderr, "Could not copy new archive to final location (system() returned %i)\n", err); unlink(new_xar_path); exit(1); } // Delete the tmp archive unlink(new_xar_path); free(systemcall); }
std::map<std::string, std::string> Extract(std::string file, std::string prefix) { std::map<std::string, std::string> files; #ifdef HAVE_LIBXAR xar_t x; xar_iter_t xi; xar_file_t xf; xar_stream xs; char buffer[8192]; x = xar_open(file.c_str(), READ); if (x == nullptr) { std::cerr << "Could not open xar archive" << std::endl; } xi = xar_iter_new(); if (xi == nullptr) { xar_close(x); std::cerr << "Could not read xar archive" << std::endl; } for (xf = xar_file_first(x, xi); xf != nullptr; xf = xar_file_next(xi)) { char *path = xar_get_path(xf); const char *type; xar_prop_get(xf, "type", &type); if (type == nullptr) { std::cerr << "File has no type" << std::endl; free(path); continue; } if (std::strcmp(type, "file") != 0) { free(path); continue; } if (xar_extract_tostream_init(x, xf, &xs) != XAR_STREAM_OK) { std::cerr << "Error initializing stream" << std::endl; free(path); continue; } const std::string fileName = prefix + util::uuid::UuidToString(util::uuid::GenerateUUID()); // Write bitcode to file std::FILE *output = std::fopen(fileName.c_str(), "wb"); if (output == nullptr) { std::cerr << "Error opening output file" << std::endl; continue; } xs.avail_out = sizeof(buffer); xs.next_out = buffer; int32_t ret; while ((ret = xar_extract_tostream(&xs)) != XAR_STREAM_END) { if (ret == XAR_STREAM_ERR) { std::cerr << "Error extracting stream" << std::endl; break; } std::fwrite(buffer, sizeof(char), sizeof(buffer) - xs.avail_out, output); xs.avail_out = sizeof(buffer); xs.next_out = buffer; } if (xar_extract_tostream_end(&xs) != XAR_STREAM_OK) { std::cerr << "Error ending stream" << std::endl; } std::fclose(output); // Add to list of extracted files files[std::string(path)] = fileName; free(path); } xar_iter_free(xi); xar_close(x); #endif return files; }
static int extract(const char *filename, int arglen, char *args[]) { xar_t x; xar_iter_t i; xar_file_t f; int files_extracted = 0; x = xar_open(filename, READ); if( !x ) { fprintf(stderr, "Error opening xar archive: %s\n", filename); exit(1); } xar_register_errhandler(x, err_callback, NULL); if( Perms == SYMBOLIC ) { xar_opt_set(x, XAR_OPT_OWNERSHIP, XAR_OPT_VAL_SYMBOLIC); } if( Perms == NUMERIC ) { xar_opt_set(x, XAR_OPT_OWNERSHIP, XAR_OPT_VAL_NUMERIC); } if ( Rsize != NULL ) { xar_opt_set(x, XAR_OPT_RSIZE, Rsize); } i = xar_iter_new(); if( !i ) { fprintf(stderr, "Error creating xar iterator\n"); exit(1); } for(f = xar_file_first(x, i); f; f = xar_file_next(i)) { int matched = 0; int exclude_match = 1; struct lnode *i; char *path = xar_get_path(f); if( args[0] ) { int i; for(i = 0; args[i]; i++) { if( strcmp(path, args[i]) == 0 ) { matched = 1; break; } } } else { matched = 1; } for( i = Exclude; i; i=i->next ) { exclude_match = regexec(&i->reg, path, 0, NULL, 0); if( !exclude_match ) break; } if( !exclude_match ) { if( Verbose ) printf("Excluding %s\n", path); free(path); continue; } if( matched ) { files_extracted++; print_file(f); xar_extract(x, f); } free(path); } if( args[0] && (files_extracted == 0) ) { fprintf(stderr, "No files matched extraction criteria.\n"); Err = 3; } if( Subdoc ) extract_subdoc(x, NULL); xar_iter_free(i); if( xar_close(x) != 0 ) { fprintf(stderr, "Error extracting the archive\n"); if( !Err ) Err = 42; } return Err; }
int pkg_toc_process(const char *path, const char *toc) { u_int32_t pkgid; xar_t x; xar_iter_t i; xar_file_t f; struct vfs_fake_stat sb; if (!(x = xar_open(path, READ))) { Log(LOG_ERROR, "failed opening package %s", path); return EXIT_FAILURE; } xar_register_errhandler(x, pkg_xar_err_callback, NULL); if (!(i = xar_iter_new())) { Log(LOG_ERROR, "failed getting new xar iter in pkg %s", path); return EXIT_FAILURE; } db_pkg_remove(path); pkgid = db_pkg_add(path); fprintf(stderr, "id: %d\n", pkgid); for (f = xar_file_first(x, i); f; f = xar_file_next(i)) { char *size = xar_get_size(x, f); char *xpath = xar_get_path(f); char *xtype = xar_get_type(x, f); char *mode = xar_get_mode(x, f); char *user = xar_get_owner(x, f); char *group = xar_get_group(x, f); char *mtime = xar_get_mtime(x, f); const char *offset; char type = 'u'; /* * (f)ile, (d)irectory, (l)ink, (p)ipe * f(i)fo, (c)haracter, (b)lock, (s)ocket, * (u)ndefined */ if (!strcasecmp(xtype, "file")) { xar_prop_get(f, "data/offset", &offset); type = 'f'; } else { offset = "0"; if (!strcasecmp(xtype, "directory")) type = 'd'; else if (!strcasecmp(xtype, "hardlink")) type = 'l'; else if (!strcasecmp(xtype, "symlink")) type = 'l'; } #if 0 /* * what we gonna do with target? */ printf("%s: %s %8s/%-8s %10s %s %s @ %s\n", xtype, mode, user, group, size, mtime, xpath, offset); db_query(QUERY_INT, "INSERT INTO files (package, path, type, owner, group, size, offset, ctime, mode) VALUES (%lu, '%s', '%s', %s, %s, %s, %s, %s, %s, %s);", pkgid, xpath, type, user, group, size, offset, mtime); #endif free(mtime); free(group); free(user); free(mode); free(xtype); free(xpath); free(size); } return EXIT_SUCCESS; }
int main(int argc, char *argv[]) { int fd; unsigned char *buffer; struct stat sb; ssize_t red; xar_t x; xar_file_t f, f2; if( argc < 2 ) { fprintf(stderr, "usage: %s <filename>\n", argv[0]); exit(1); } fd = open(argv[1], O_RDONLY); if( fd < 0 ) { fprintf(stderr, "Unable to open file %s\n", argv[1]); exit(2); } if( fstat(fd, &sb) < 0 ) { fprintf(stderr, "Unable to stat file %s\n", argv[1]); exit(3); } buffer = malloc(sb.st_size); if( buffer == NULL ) { fprintf(stderr, "Unable to allocate memory\n"); exit(4); } red = read(fd, buffer, sb.st_size); if( red <= 0 ) { fprintf(stderr, "Error reading from file\n"); exit(5); } if( red < sb.st_size ) fprintf(stderr, "Incomplete read\n"); x = xar_open("/tmp/test.xar", WRITE); if( x == NULL ) { fprintf(stderr, "Error creating xarchive\n"); exit(6); } xar_register_errhandler(x, err_callback, NULL); memset(&sb, 0, sizeof(sb)); sb.st_mode = S_IFDIR | S_IRWXU; f = xar_add_folder(x, NULL, "mydir", &sb); if( !f ) { fprintf(stderr, "Error adding parent to archive\n"); exit(7); } f2 = xar_add_frombuffer(x, f, "secondfile", buffer, red); if( !f ) { fprintf(stderr, "Error adding child to archive\n"); exit(8); } xar_close(x); close(fd); exit(0); }