FILE *HCache_open(const char *file, const char *opt) { FILE *first; char s_path[255]; if( file[0] == '.' && file[1] == '/' ) file += 2; else if( file[0] == '.' ) file++; snprintf(s_path, 255, "./cache/%s", file); if( !(first = fopen(s_path,opt)) ) { return NULL; } if( opt[0] != 'r' ) { char dT[1];/* 1-byte key to ensure our method is the latest, we can modify to ensure the method matches */ dT[0] = HCACHE_KEY; hwrite(dT,sizeof(dT),1,first); hwrite(&HCache->recompile_time,sizeof(HCache->recompile_time),1,first); } fseek(first, 20, SEEK_SET);/* skip first 20, might wanna store something else later */ return first; }
DLL_EXPORT int html_include(WEBBLK *webblk, char *filename) { FILE *inclfile; char fullname[HTTP_PATH_LENGTH]; char buffer[HTTP_PATH_LENGTH]; int ret; strlcpy( fullname, http_serv.httproot, sizeof(fullname) ); strlcat( fullname, filename, sizeof(fullname) ); inclfile = fopen(fullname,"rb"); if (!inclfile) { WRMSG(HHC01800,"E","fopen()",strerror(errno)); hprintf(webblk->sock,MSG(HHC01800,"E","fopen()",strerror(errno))); return FALSE; } while (!feof(inclfile)) { ret = (int)fread(buffer, 1, sizeof(buffer), inclfile); if (ret <= 0) break; hwrite(webblk->sock,buffer, ret); } fclose(inclfile); return TRUE; }
DLL_EXPORT int html_include(WEBBLK *webblk, char *filename) { FILE *inclfile; char fullname[HTTP_PATH_LENGTH]; char buffer[HTTP_PATH_LENGTH]; int ret; strlcpy( fullname, sysblk.httproot, sizeof(fullname) ); strlcat( fullname, filename, sizeof(fullname) ); inclfile = fopen(fullname,"rb"); if (!inclfile) { logmsg(_("HHCHT011E html_include: Cannot open %s: %s\n"), fullname,strerror(errno)); hprintf(webblk->sock,_("ERROR: Cannot open %s: %s\n"), filename,strerror(errno)); return FALSE; } while (!feof(inclfile)) { ret = fread(buffer, 1, sizeof(buffer), inclfile); if (ret <= 0) break; hwrite(webblk->sock,buffer, ret); } fclose(inclfile); return TRUE; }
DLL_EXPORT int hprintf(int s,char *fmt,...) { char *bfr; size_t bsize=1024; int rc; va_list vl; bfr=malloc(bsize); while(1) { if(!bfr) { return -1; } va_start(vl,fmt); rc=vsnprintf(bfr,bsize,fmt,vl); va_end(vl); if(rc<(int)bsize) { break; } bsize+=1024; bfr=realloc(bfr,bsize); } rc=hwrite(s,bfr,strlen(bfr)); free(bfr); return rc; }
static int fromwebdir(HConnect *c) { char buf[4096], *p, *ext, *type; int i, fd, n, defaulted; Dir *d; if(webroot == nil || strstr(c->req.uri, "..")) return hnotfound(c); snprint(buf, sizeof buf-20, "%s/%s", webroot, c->req.uri+1); defaulted = 0; reopen: if((fd = open(buf, OREAD)) < 0) return hnotfound(c); d = dirfstat(fd); if(d == nil){ close(fd); return hnotfound(c); } if(d->mode&DMDIR){ if(!defaulted){ defaulted = 1; strcat(buf, "/index.html"); free(d); close(fd); goto reopen; } free(d); return hnotfound(c); } free(d); p = buf+strlen(buf); type = "application/octet-stream"; for(i=0; exttab[i].ext; i++){ ext = exttab[i].ext; if(p-strlen(ext) >= buf && strcmp(p-strlen(ext), ext) == 0){ type = exttab[i].type; break; } } if(hsettype(c, type) < 0){ close(fd); return 0; } while((n = read(fd, buf, sizeof buf)) > 0) if(hwrite(&c->hout, buf, n) < 0) break; close(fd); hflush(&c->hout); return 0; }
static int hmanager(HConnect *c) { Hio *hout; int r; int i, k; Job *j; VtLog *l; VtLogChunk *ch; r = hsethtml(c); if(r < 0) return r; hout = &c->hout; hprint(hout, "<html><head><title>venti mgr status</title></head>\n"); hprint(hout, "<body><h2>venti mgr status</h2>\n"); for(i=0; i<njob; i++) { j = &job[i]; hprint(hout, "<b>"); if(j->nrun == 0) hprint(hout, "----/--/-- --:--:--"); else hprint(hout, "%+T", (long)(j->runstart + time0)); hprint(hout, " %s", j->name); if(j->nrun > 0) { if(j->newok == -1) { hprint(hout, " (running)"); } else if(!j->newok) { hprint(hout, " <font color=\"#cc0000\">(FAILED)</font>"); } } hprint(hout, "</b>\n"); hprint(hout, "<font size=-1><pre>\n"); l = j->newlog; ch = l->w; for(k=0; k<l->nchunk; k++){ if(++ch == l->chunk+l->nchunk) ch = l->chunk; hwrite(hout, ch->p, ch->wp-ch->p); } hprint(hout, "</pre></font>\n"); hprint(hout, "\n"); } hprint(hout, "</body></html>\n"); hflush(hout); return 0; }
static void http_download(WEBBLK *webblk, char *filename) { char buffer[HTTP_PATH_LENGTH]; char tbuf[80]; int fd, length; char *filetype; char fullname[HTTP_PATH_LENGTH]; struct stat st; MIMETAB *mime_type = mime_types; strlcpy( fullname, http_serv.httproot, sizeof(fullname) ); strlcat( fullname, filename, sizeof(fullname) ); http_verify_path(webblk,fullname); if(stat(fullname,&st)) http_error(webblk, "404 File Not Found","", strerror(errno)); if(!S_ISREG(st.st_mode)) http_error(webblk, "404 File Not Found","", "The requested file is not a regular file"); fd = HOPEN(fullname,O_RDONLY|O_BINARY,0); if (fd == -1) http_error(webblk, "404 File Not Found","", strerror(errno)); hprintf(webblk->sock,"HTTP/1.0 200 OK\n"); if ((filetype = strrchr(filename,'.'))) for(mime_type++;mime_type->suffix && strcasecmp(mime_type->suffix,filetype + 1); mime_type++); if(mime_type->type) hprintf(webblk->sock,"Content-Type: %s\n", mime_type->type); hprintf(webblk->sock,"Expires: %s\n", http_timestring(tbuf,sizeof(tbuf),time(NULL)+HTML_STATIC_EXPIRY_TIME)); hprintf(webblk->sock,"Content-Length: %d\n\n", (int)st.st_size); while ((length = read(fd, buffer, sizeof(buffer))) > 0) hwrite(webblk->sock,buffer, length); close(fd); http_exit(webblk); }
static int herror(HConnect *c) { int n; Hio *hout; hout = &c->hout; n = snprint(c->xferbuf, HBufSize, "<html><head><title>Error</title></head>\n<body><h1>Error</h1>\n<pre>%r</pre>\n</body></html>"); hprint(hout, "%s %s\r\n", hversion, "400 Bad Request"); hprint(hout, "Date: %D\r\n", time(nil)); hprint(hout, "Server: Venti\r\n"); hprint(hout, "Content-Type: text/html\r\n"); hprint(hout, "Content-Length: %d\r\n", n); if(c->head.closeit) hprint(hout, "Connection: close\r\n"); else if(!http11(c)) hprint(hout, "Connection: Keep-Alive\r\n"); hprint(hout, "\r\n"); if(c->req.meth == nil || strcmp(c->req.meth, "HEAD") != 0) hwrite(hout, c->xferbuf, n); return hflush(hout); }
void vtloghdump(Hio *h, VtLog *l) { int i; VtLogChunk *c; char *name; name = l ? l->name : "<nil>"; hprint(h, "<html><head>\n"); hprint(h, "<title>Venti Server Log: %s</title>\n", name); hprint(h, "</head><body>\n"); hprint(h, "<b>Venti Server Log: %s</b>\n<p>\n", name); if(l){ c = l->w; for(i=0; i<l->nchunk; i++){ if(++c == l->chunk+l->nchunk) c = l->chunk; hwrite(h, c->p, c->wp-c->p); } } hprint(h, "</body></html>\n"); }
/* * send back a nice error message if the content is unacceptable * to get this message in ie, go to tools, internet options, advanced, * and turn off Show Friendly HTTP Error Messages under the Browsing category */ static int notaccept(HConnect *c, HContent *type, HContent *enc, char *which) { Hio *hout; char *s, *e; hout = &c->hout; e = &c->xferbuf[HBufSize]; s = c->xferbuf; s = seprint(s, e, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n"); s = seprint(s, e, "<html>\n<title>Unacceptable %s</title>\n<body>\n", which); s = seprint(s, e, "Your browser will not accept this data, %H, because of its %s.<br>\n", c->req.uri, which); s = seprint(s, e, "Its Content-Type is %s/%s", type->generic, type->specific); if(enc != nil) s = seprint(s, e, ", and Content-Encoding is %s", enc->generic); s = seprint(s, e, ".<br>\n\n"); s = acceptcont(s, e, c->head.oktype, "Content-Type"); s = acceptcont(s, e, c->head.okencode, "Content-Encoding"); s = seprint(s, e, "</body>\n</html>\n"); hprint(hout, "%s 406 Not Acceptable\r\n", hversion); hprint(hout, "Server: Plan9\r\n"); hprint(hout, "Date: %D\r\n", time(nil)); hprint(hout, "Content-Type: text/html\r\n"); hprint(hout, "Content-Length: %lud\r\n", s - c->xferbuf); if(c->head.closeit) hprint(hout, "Connection: close\r\n"); else if(!http11(c)) hprint(hout, "Connection: Keep-Alive\r\n"); hprint(hout, "\r\n"); if(strcmp(c->req.meth, "HEAD") != 0) hwrite(hout, c->xferbuf, s - c->xferbuf); writelog(c, "Reply: 406 Not Acceptable\nReason: %s\n", which); return hflush(hout); }
void cgibin_syslog(WEBBLK *webblk) { int num_bytes; int logbuf_idx; char *logbuf_ptr; char *command; char *value; int autorefresh = 0; int refresh_interval = 5; int msgcount = 22; if ((command = cgi_variable(webblk,"command"))) { panel_command(command); // Wait a bit before proceeding in case // the command issues a lot of messages usleep(50000); } if((value = cgi_variable(webblk,"msgcount"))) msgcount = atoi(value); else if((value = cgi_cookie(webblk,"msgcount"))) msgcount = atoi(value); if ((value = cgi_variable(webblk,"refresh_interval"))) refresh_interval = atoi(value); if (cgi_variable(webblk,"autorefresh")) autorefresh = 1; else if (cgi_variable(webblk,"norefresh")) autorefresh = 0; else if (cgi_variable(webblk,"refresh")) autorefresh = 1; html_header(webblk); hprintf(webblk->sock,"<script language=\"JavaScript\">\n" "<!--\n" "document.cookie = \"msgcount=%d\";\n" "//-->\n" "</script>\n", msgcount); hprintf(webblk->sock, "<H2>Hercules System Log</H2>\n"); hprintf(webblk->sock, "<PRE>\n"); // Get the index to our desired starting message... logbuf_idx = msgcount ? log_line( msgcount ) : -1; // Now read the logfile starting at that index. The return // value is the total #of bytes of messages data there is. if ( (num_bytes = log_read( &logbuf_ptr, &logbuf_idx, LOG_NOBLOCK )) > 0 ) { // Copy the message data to a work buffer for processing. // This is to allow for the possibility, however remote, // that the logfile buffer actually wraps around and over- // lays the message data we were going to display (which // could happen if there's a sudden flood of messages) int sav_bytes = num_bytes; char *wrk_bufptr = malloc( num_bytes ); if ( wrk_bufptr ) strncpy( wrk_bufptr, logbuf_ptr, num_bytes ); else wrk_bufptr = logbuf_ptr; // We need to convert certain characters that might // possibly be erroneously interpretted as HTML code #define AMP_LT "<" // (HTML code for '<') #define AMP_GT ">" // (HTML code for '>') #define AMP_AMP "&" // (HTML code for '&') while ( num_bytes-- ) { switch ( *wrk_bufptr ) { case '<': hwrite( webblk->sock, AMP_LT , sizeof(AMP_LT) ); break; case '>': hwrite( webblk->sock, AMP_GT , sizeof(AMP_GT) ); break; case '&': hwrite( webblk->sock, AMP_AMP , sizeof(AMP_AMP)); break; default: hwrite( webblk->sock, wrk_bufptr , 1 ); break; } wrk_bufptr++; } // (free our work buffer if it's really ours) if ( ( wrk_bufptr -= sav_bytes ) != logbuf_ptr ) free( wrk_bufptr ); } hprintf(webblk->sock, "</PRE>\n"); hprintf(webblk->sock, "<FORM method=post>Command:\n"); hprintf(webblk->sock, "<INPUT type=text name=command size=80>\n"); hprintf(webblk->sock, "<INPUT type=submit name=send value=\"Send\">\n"); hprintf(webblk->sock, "<INPUT type=hidden name=%srefresh value=1>\n",autorefresh ? "auto" : "no"); hprintf(webblk->sock, "<INPUT type=hidden name=refresh_interval value=%d>\n",refresh_interval); hprintf(webblk->sock, "<INPUT type=hidden name=msgcount value=%d>\n",msgcount); hprintf(webblk->sock, "</FORM>\n<BR>\n"); hprintf(webblk->sock, "<A name=bottom>\n"); hprintf(webblk->sock, "<FORM method=post>\n"); if(!autorefresh) { hprintf(webblk->sock, "<INPUT type=submit value=\"Auto Refresh\" name=autorefresh>\n"); hprintf(webblk->sock, "Refresh Interval: "); hprintf(webblk->sock, "<INPUT type=text name=\"refresh_interval\" size=2 value=%d>\n", refresh_interval); } else { hprintf(webblk->sock, "<INPUT type=submit name=norefresh value=\"Stop Refreshing\">\n"); hprintf(webblk->sock, "<INPUT type=hidden name=refresh_interval value=%d>\n",refresh_interval); hprintf(webblk->sock, " Refresh Interval: %2d \n", refresh_interval); } hprintf(webblk->sock, "<INPUT type=hidden name=msgcount value=%d>\n",msgcount); hprintf(webblk->sock, "</FORM>\n"); hprintf(webblk->sock, "<FORM method=post>\n"); hprintf(webblk->sock, "Only show last "); hprintf(webblk->sock, "<INPUT type=text name=msgcount size=3 value=%d>",msgcount); hprintf(webblk->sock, " lines (zero for all loglines)\n"); hprintf(webblk->sock, "<INPUT type=hidden name=%srefresh value=1>\n",autorefresh ? "auto" : "no"); hprintf(webblk->sock, "<INPUT type=hidden name=refresh_interval value=%d>\n",refresh_interval); hprintf(webblk->sock, "</FORM>\n"); if (autorefresh) { /* JavaScript to cause automatic page refresh */ hprintf(webblk->sock, "<script language=\"JavaScript\">\n"); hprintf(webblk->sock, "<!--\nsetTimeout('window.location.replace(\"%s" "?refresh_interval=%d" "&refresh=1" "&msgcount=%d" "\")', %d)\n", cgi_baseurl(webblk), refresh_interval, msgcount, refresh_interval*1000); hprintf(webblk->sock, "//-->\n</script>\n"); } html_footer(webblk); }
int main(void) { static const int size[] = { 1, 13, 403, 999, 30000 }; char buffer[40000]; char *original; int c, i; ssize_t n; off_t off; reopen("vcf.c", "test/hfile1.tmp"); while ((c = hgetc(fin)) != EOF) { if (hputc(c, fout) == EOF) fail("hputc"); } if (herrno(fin)) { errno = herrno(fin); fail("hgetc"); } reopen("test/hfile1.tmp", "test/hfile2.tmp"); if (hpeek(fin, buffer, 50) < 0) fail("hpeek"); while ((n = hread(fin, buffer, 17)) > 0) { if (hwrite(fout, buffer, n) != n) fail("hwrite"); } if (n < 0) fail("hread"); reopen("test/hfile2.tmp", "test/hfile3.tmp"); while ((n = hread(fin, buffer, sizeof buffer)) > 0) { if (hwrite(fout, buffer, n) != n) fail("hwrite"); if (hpeek(fin, buffer, 700) < 0) fail("hpeek"); } if (n < 0) fail("hread"); reopen("test/hfile3.tmp", "test/hfile4.tmp"); i = 0; off = 0; while ((n = hread(fin, buffer, size[i++ % 5])) > 0) { off += n; buffer[n] = '\0'; check_offset(fin, off, "pre-peek"); if (hputs(buffer, fout) == EOF) fail("hputs"); if ((n = hpeek(fin, buffer, size[(i+3) % 5])) < 0) fail("hpeek"); check_offset(fin, off, "post-peek"); } if (n < 0) fail("hread"); reopen("test/hfile4.tmp", "test/hfile5.tmp"); n = hread(fin, buffer, 200); if (n < 0) fail("hread"); else if (n != 200) fail("hread only got %d", (int)n); if (hwrite(fout, buffer, 1000) != 1000) fail("hwrite"); check_offset(fin, 200, "input/first200"); check_offset(fout, 1000, "output/first200"); if (hseek(fin, 800, SEEK_CUR) < 0) fail("hseek/cur"); check_offset(fin, 1000, "input/seek"); for (off = 1000; (n = hread(fin, buffer, sizeof buffer)) > 0; off += n) if (hwrite(fout, buffer, n) != n) fail("hwrite"); if (n < 0) fail("hread"); check_offset(fin, off, "input/eof"); check_offset(fout, off, "output/eof"); if (hseek(fin, 200, SEEK_SET) < 0) fail("hseek/set"); if (hseek(fout, 200, SEEK_SET) < 0) fail("hseek(output)"); check_offset(fin, 200, "input/backto200"); check_offset(fout, 200, "output/backto200"); n = hread(fin, buffer, 800); if (n < 0) fail("hread"); else if (n != 800) fail("hread only got %d", (int)n); if (hwrite(fout, buffer, 800) != 800) fail("hwrite"); check_offset(fin, 1000, "input/wrote800"); check_offset(fout, 1000, "output/wrote800"); if (hflush(fout) == EOF) fail("hflush"); original = slurp("vcf.c"); for (i = 1; i <= 5; i++) { char *text; sprintf(buffer, "test/hfile%d.tmp", i); text = slurp(buffer); if (strcmp(original, text) != 0) { fprintf(stderr, "%s differs from vcf.c\n", buffer); return EXIT_FAILURE; } free(text); } free(original); if (hclose(fin) != 0) fail("hclose(input)"); if (hclose(fout) != 0) fail("hclose(output)"); fout = hopen("test/hfile_chars.tmp", "w"); if (fout == NULL) fail("hopen(\"test/hfile_chars.tmp\")"); for (i = 0; i < 256; i++) if (hputc(i, fout) != i) fail("chars: hputc (%d)", i); if (hclose(fout) != 0) fail("hclose(test/hfile_chars.tmp)"); fin = hopen("test/hfile_chars.tmp", "r"); if (fin == NULL) fail("hopen(\"test/hfile_chars.tmp\") for reading"); for (i = 0; i < 256; i++) if ((c = hgetc(fin)) != i) fail("chars: hgetc (%d = 0x%x) returned %d = 0x%x", i, i, c, c); if ((c = hgetc(fin)) != EOF) fail("chars: hgetc (EOF) returned %d", c); if (hclose(fin) != 0) fail("hclose(test/hfile_chars.tmp) for reading"); fin = hopen("data:hello, world!\n", "r"); if (fin == NULL) fail("hopen(\"data:...\")"); n = hread(fin, buffer, 300); if (n < 0) fail("hread"); buffer[n] = '\0'; if (strcmp(buffer, "hello, world!\n") != 0) fail("hread result"); if (hclose(fin) != 0) fail("hclose(\"data:...\")"); return EXIT_SUCCESS; }
//main int main (int argc, char* argv[]) { //keep frequencies in array for (int i = 0; i < SYMBOLS; i++) frequencies[i] = 0; //make sure user inputs two arguments if (argc != 3) { printf("You must enter %s input output\n", argv[0]); return 1; } //open input FILE *fp = fopen(argv[1],"r" ); if (fp == NULL) { printf("Could not open souce file: %s\n", argv[1]); return 1; } //open output Huffile *outfile = hfopen(argv[2], "w"); if (outfile == NULL) { printf("Could not open destination file: %s\n", argv[2]); return 1; } //create a forest Forest *myForest = mkforest(); if (myForest == NULL) { printf("The forest could not be created :(\n"); return 1; } //read each character from source file for (int c = fgetc(fp); c!= EOF; c = fgetc(fp)) { //printf("%c", c); //increment frequencies for char frequencies[c]++; //increment checksum checksum_counter++; } //make and plant trees in sorted order for (int i = 0; i < SYMBOLS; i++) { if (frequencies[i] != 0) { //make the tree Tree *tempTree = mktree(); tempTree->symbol = i; tempTree->frequency = frequencies[i]; tempTree->left = NULL; tempTree->right = NULL; //plant tree in forest if (plant(myForest, tempTree) == false) printf("Could not plant tree %c\n", i); } } //build the huffman tree while (myForest->first->tree->frequency < checksum_counter) { //make the tree Tree *tempTree = mktree(); tempTree->symbol = 0x00; tempTree->left = pick(myForest); tempTree->right = pick(myForest); if (tempTree->right != NULL) tempTree->frequency = tempTree->left->frequency + tempTree->right->frequency; else tempTree->frequency = tempTree->left->frequency; //plant tree in forest if (plant(myForest, tempTree) == false) printf("Could not plant parent tree\n"); } //create encoding of each character for (int i = 0; i < SYMBOLS; i++) { if (frequencies[i] != 0) { //create a temporary array to store the encoded value char temp[256]; for (int j = 0; j < 256; j++) temp[j] = '9'; encode(myForest->first->tree, i, 0, "", &temp[0]); //copy temp to encoded strncpy(encoded[i], temp, strlen(temp)); //printf("temp: %s\n", temp); //printf("encoded: %c, hops: %s ", i, encoded[i]); } } //create huffeader header Huffeader *header = malloc(sizeof(Huffeader)); header->magic = MAGIC; for (int i = 0; i < SYMBOLS; i++) header->frequencies[i] = frequencies[i]; header->checksum = checksum_counter; //write header hwrite(header, outfile); //move to beginning of source file rewind(fp); //keep track of how many bits we use int bit_count = 0; //read file per character, lookup frequency, and write to outfile for (int c = fgetc(fp); c!= EOF; c = fgetc(fp)) { for (int i = 0; i < strlen(encoded[c]); i++) { bit_count++; int bit = 0; //write each bit if (encoded[c][i] == '0') bit = 0; else if (encoded[c][i] == '1') bit = 1; bool write_output = bwrite(bit, outfile); if (write_output == false) printf("Error bwriting: %c\n", encoded[c][i]); //printf("%c bit_count: %d\n", encoded[c][i], bit_count); } //printf("%s", encoded[c]); } //figure out how many bits in second to last byte are used int bits_used = 0; if (bit_count <= 8) bits_used = bit_count; else bits_used = (bit_count % 8); //write trailing bits for (int i = 8 - bits_used; i > 1; i--) { //printf("0\n"); bool write_output = bwrite(0, outfile); if (write_output == false) printf("Error bwriting: %c\n", '0'); } //cleanup outfile->ith = bits_used; free(header); rmforest(myForest); hfclose(outfile); fclose(fp); return 0; }
/* * Reads a version 3 CRAM file and replaces the header in-place, * provided the header is small enough to fit without growing the * entire file. * * Version 3 format has a SAM header held as an (optionally) * compressed block within the header container. Additional * uncompressed blocks or simply unallocated space (the difference * between total block sizes and the container size) are used to * provide room for growth or contraction of the compressed header. * * Returns 0 on success; * -1 on general failure; * -2 on failure due to insufficient size */ int cram_reheader_inplace3(cram_fd *fd, const bam_hdr_t *h, const char *arg_list, int add_PG) { cram_container *c = NULL; cram_block *b = NULL; SAM_hdr *hdr = NULL; off_t start, sz, end; int container_sz, max_container_sz; char *buf = NULL; int ret = -1; if (cram_major_vers(fd) < 2 || cram_major_vers(fd) > 3) { fprintf(stderr, "[%s] unsupported CRAM version %d\n", __func__, cram_major_vers(fd)); goto err; } if (!(hdr = sam_hdr_parse_(h->text, h->l_text))) goto err; if (add_PG && sam_hdr_add_PG(hdr, "samtools", "VN", samtools_version(), arg_list ? "CL": NULL, arg_list ? arg_list : NULL, NULL)) goto err; int header_len = sam_hdr_length(hdr); /* Fix M5 strings? Maybe out of scope for this tool */ // Find current size of SAM header block if ((start = hseek(cram_fd_get_fp(fd), 26, SEEK_SET)) != 26) goto err; if (!(c = cram_read_container(fd))) goto err; // +5 allows num_landmarks to increase from 0 to 1 (Cramtools) max_container_sz = cram_container_size(c)+5; sz = htell(cram_fd_get_fp(fd)) + cram_container_get_length(c) - start; end = htell(cram_fd_get_fp(fd)) + cram_container_get_length(c); // We force 1 block instead of (optionally) 2. C CRAM // implementations for v3 were writing 1 compressed block followed // by 1 uncompressed block. However this is tricky to deal with // as changing block sizes can mean the block header also changes // size due to itf8 and variable size integers. // // If we had 1 block, this doesn't change anything. // If we had 2 blocks, the new container header will be smaller by // 1+ bytes, requiring the cram_container_get_length(c) to be larger in value. // However this is an int32 instead of itf8 so the container // header structure stays the same size. This means we can always // reduce the number of blocks without running into size problems. cram_container_set_num_blocks(c, 1); int32_t *landmark; int32_t num_landmarks; landmark = cram_container_get_landmarks(c, &num_landmarks); if (num_landmarks && landmark) { num_landmarks = 1; landmark[0] = 0; } else { num_landmarks = 0; } cram_container_set_landmarks(c, num_landmarks, landmark); buf = malloc(max_container_sz); container_sz = max_container_sz; if (cram_store_container(fd, c, buf, &container_sz) != 0) goto err; if (!buf) goto err; // Proposed new length, but changing cram_container_get_length(c) may change the // container_sz and thus the remainder (cram_container_get_length(c) itself). cram_container_set_length(c, sz - container_sz); int old_container_sz = container_sz; container_sz = max_container_sz; if (cram_store_container(fd, c, buf, &container_sz) != 0) goto err; if (old_container_sz != container_sz) { fprintf(stderr, "Quirk of fate makes this troublesome! " "Please use non-inplace version.\n"); goto err; } // Version 3.0 supports compressed header b = cram_new_block(FILE_HEADER, 0); int32_put_blk(b, header_len); cram_block_append(b, sam_hdr_str(hdr), header_len); cram_block_update_size(b); cram_compress_block(fd, b, NULL, -1, -1); if (hseek(cram_fd_get_fp(fd), 26, SEEK_SET) != 26) goto err; if (cram_block_size(b) > cram_container_get_length(c)) { fprintf(stderr, "New header will not fit. Use non-inplace version" " (%d > %d)\n", (int)cram_block_size(b), cram_container_get_length(c)); ret = -2; goto err; } if (cram_write_container(fd, c) == -1) goto err; if (cram_write_block(fd, b) == -1) goto err; // Blank out the remainder int rsz = end - htell(cram_fd_get_fp(fd)); assert(rsz >= 0); if (rsz) { char *rem = calloc(1, rsz); ret = hwrite(cram_fd_get_fp(fd), rem, rsz) == rsz ? 0 : -1; free(rem); } err: if (c) cram_free_container(c); if (buf) free(buf); if (b) cram_free_block(b); if (hdr) sam_hdr_free(hdr); return ret; }