2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 1991-1999 University of Maryland at College Park
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of U.M. not be used in advertising or
11 * publicity pertaining to distribution of the software without specific,
12 * written prior permission. U.M. makes no representations about the
13 * suitability of this software for any purpose. It is provided "as is"
14 * without express or implied warranty.
16 * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
18 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 * Authors: the Amanda Development Team. Its members are listed in a
24 * file named AUTHORS, in the root directory of this distribution.
27 * $Id: fileheader.c 6512 2007-05-24 17:00:24Z ian $
31 #include "fileheader.h"
35 static const char * filetype2str(filetype_t);
36 static filetype_t str2filetype(const char *);
37 static void strange_header(dumpfile_t *, const char *,
38 size_t, const char *, const char *);
39 static char * strquotedstr(void);
40 static ssize_t hexdump(const char *buffer, size_t len);
46 memset(file, '\0', SIZEOF(*file));
47 file->blocksize = DISK_BLOCK_BYTES;
63 g_fprintf(stderr, _("%s: strange amanda header: \"%.*s\"\n"), get_pname(),
66 g_fprintf(stderr, _("%s: Expected: \"%s\" Actual: \"%s\"\n"), get_pname(),
79 char *buf, *line, *tok, *line1;
84 /* put the buffer into a writable chunk of memory and nul-term it */
85 buf = alloc(buflen + 1);
86 memcpy(buf, buffer, buflen);
91 for (line = buf, lsize = 0; lsize < buflen; line++) {
92 if ((*line == '\n') && !in_quotes)
96 in_quotes = !in_quotes;
97 } else if ((*line == '\\') && (*(line + 1) == '"')) {
104 line1 = alloc(lsize + 1);
105 strncpy(line1, buf, lsize);
109 tok = strtok(line1, " ");
111 g_fprintf(stderr, _("%s: Empty amanda header: buflen=%zu lsize=%zu\n"), get_pname(),
114 hexdump(buffer, lsize);
115 strange_header(file, buffer, buflen, _("<Non-empty line>"), tok);
119 if (strcmp(tok, "NETDUMP:") != 0 && strcmp(tok, "AMANDA:") != 0) {
121 file->type = F_UNKNOWN;
126 tok = strtok(NULL, " ");
128 strange_header(file, buffer, buflen, _("<file type>"), tok);
131 file->type = str2filetype(tok);
133 switch (file->type) {
135 tok = strtok(NULL, " ");
136 if ((tok == NULL) || (strcmp(tok, "DATE") != 0)) {
137 strange_header(file, buffer, buflen, "DATE", tok);
141 tok = strtok(NULL, " ");
143 strange_header(file, buffer, buflen, _("<date stamp>"), tok);
146 strncpy(file->datestamp, tok, SIZEOF(file->datestamp) - 1);
148 tok = strtok(NULL, " ");
149 if ((tok == NULL) || (strcmp(tok, "TAPE") != 0)) {
150 strange_header(file, buffer, buflen, "TAPE", tok);
154 tok = strtok(NULL, " ");
156 strange_header(file, buffer, buflen, _("<file type>"), tok);
159 strncpy(file->name, tok, SIZEOF(file->name) - 1);
163 case F_CONT_DUMPFILE:
164 case F_SPLIT_DUMPFILE:
165 tok = strtok(NULL, " ");
167 strange_header(file, buffer, buflen, _("<date stamp>"), tok);
170 strncpy(file->datestamp, tok, SIZEOF(file->datestamp) - 1);
172 tok = strtok(NULL, " ");
174 strange_header(file, buffer, buflen, _("<file name>"), tok);
177 strncpy(file->name, tok, SIZEOF(file->name) - 1);
179 tok = strquotedstr();
181 strange_header(file, buffer, buflen, _("<disk name>"), tok);
184 uqname = unquote_string(tok);
185 strncpy(file->disk, uqname, SIZEOF(file->disk) - 1);
188 if(file->type == F_SPLIT_DUMPFILE) {
189 tok = strtok(NULL, " ");
190 if (tok == NULL || strcmp(tok, "part") != 0) {
191 strange_header(file, buffer, buflen, "part", tok);
195 tok = strtok(NULL, "/");
196 if ((tok == NULL) || (sscanf(tok, "%d", &file->partnum) != 1)) {
197 strange_header(file, buffer, buflen, _("<part num param>"), tok);
201 /* If totalparts == -1, then the original dump was done in
202 streaming mode (no holding disk), thus we don't know how
203 many parts there are. */
204 tok = strtok(NULL, " ");
205 if((tok == NULL) || (sscanf(tok, "%d", &file->totalparts) != 1)) {
206 strange_header(file, buffer, buflen, _("<total parts param>"), tok);
211 tok = strtok(NULL, " ");
212 if ((tok == NULL) || (strcmp(tok, "lev") != 0)) {
213 strange_header(file, buffer, buflen, "lev", tok);
217 tok = strtok(NULL, " ");
218 if ((tok == NULL) || (sscanf(tok, "%d", &file->dumplevel) != 1)) {
219 strange_header(file, buffer, buflen, _("<dump level param>"), tok);
223 tok = strtok(NULL, " ");
224 if ((tok == NULL) || (strcmp(tok, "comp") != 0)) {
225 strange_header(file, buffer, buflen, "comp", tok);
229 tok = strtok(NULL, " ");
231 strange_header(file, buffer, buflen, _("<comp param>"), tok);
234 strncpy(file->comp_suffix, tok, SIZEOF(file->comp_suffix) - 1);
236 file->compressed = strcmp(file->comp_suffix, "N");
237 /* compatibility with pre-2.2 amanda */
238 if (strcmp(file->comp_suffix, "C") == 0)
239 strncpy(file->comp_suffix, ".Z", SIZEOF(file->comp_suffix) - 1);
241 tok = strtok(NULL, " ");
242 /* "program" is optional */
243 if (tok == NULL || strcmp(tok, "program") != 0) {
249 tok = strtok(NULL, " ");
251 strange_header(file, buffer, buflen, _("<program name>"), tok);
254 strncpy(file->program, tok, SIZEOF(file->program) - 1);
255 if (file->program[0] == '\0')
256 strncpy(file->program, "RESTORE", SIZEOF(file->program) - 1);
258 if ((tok = strtok(NULL, " ")) == NULL)
259 break; /* reached the end of the buffer */
261 /* "encryption" is optional */
262 if (BSTRNCMP(tok, "crypt") == 0) {
263 tok = strtok(NULL, " ");
265 strange_header(file, buffer, buflen, _("<crypt param>"), tok);
268 strncpy(file->encrypt_suffix, tok,
269 SIZEOF(file->encrypt_suffix) - 1);
270 file->encrypted = BSTRNCMP(file->encrypt_suffix, "N");
271 if ((tok = strtok(NULL, " ")) == NULL)
275 /* "srvcompprog" is optional */
276 if (BSTRNCMP(tok, "server_custom_compress") == 0) {
277 tok = strtok(NULL, " ");
279 strange_header(file, buffer, buflen,
280 _("<server custom compress param>"), tok);
283 strncpy(file->srvcompprog, tok, SIZEOF(file->srvcompprog) - 1);
284 if ((tok = strtok(NULL, " ")) == NULL)
288 /* "clntcompprog" is optional */
289 if (BSTRNCMP(tok, "client_custom_compress") == 0) {
290 tok = strtok(NULL, " ");
292 strange_header(file, buffer, buflen,
293 _("<client custom compress param>"), tok);
296 strncpy(file->clntcompprog, tok, SIZEOF(file->clntcompprog) - 1);
297 if ((tok = strtok(NULL, " ")) == NULL)
301 /* "srv_encrypt" is optional */
302 if (BSTRNCMP(tok, "server_encrypt") == 0) {
303 tok = strtok(NULL, " ");
305 strange_header(file, buffer, buflen,
306 _("<server encrypt param>"), tok);
309 strncpy(file->srv_encrypt, tok, SIZEOF(file->srv_encrypt) - 1);
310 if ((tok = strtok(NULL, " ")) == NULL)
314 /* "clnt_encrypt" is optional */
315 if (BSTRNCMP(tok, "client_encrypt") == 0) {
316 tok = strtok(NULL, " ");
318 strange_header(file, buffer, buflen,
319 _("<client encrypt param>"), tok);
322 strncpy(file->clnt_encrypt, tok, SIZEOF(file->clnt_encrypt) - 1);
323 if ((tok = strtok(NULL, " ")) == NULL)
327 /* "srv_decrypt_opt" is optional */
328 if (BSTRNCMP(tok, "server_decrypt_option") == 0) {
329 tok = strtok(NULL, " ");
331 strange_header(file, buffer, buflen,
332 _("<server decrypt param>"), tok);
335 strncpy(file->srv_decrypt_opt, tok,
336 SIZEOF(file->srv_decrypt_opt) - 1);
337 if ((tok = strtok(NULL, " ")) == NULL)
341 /* "clnt_decrypt_opt" is optional */
342 if (BSTRNCMP(tok, "client_decrypt_option") == 0) {
343 tok = strtok(NULL, " ");
345 strange_header(file, buffer, buflen,
346 _("<client decrypt param>"), tok);
349 strncpy(file->clnt_decrypt_opt, tok,
350 SIZEOF(file->clnt_decrypt_opt) - 1);
351 if ((tok = strtok(NULL, " ")) == NULL)
358 tok = strtok(NULL, " ");
359 /* DATE is optional */
361 if (strcmp(tok, "DATE") == 0) {
362 tok = strtok(NULL, " ");
364 file->datestamp[0] = '\0';
366 strncpy(file->datestamp, tok, SIZEOF(file->datestamp) - 1);
368 strange_header(file, buffer, buflen, _("<DATE>"), tok);
371 file->datestamp[0] = '\0';
376 strange_header(file, buffer, buflen,
377 _("TAPESTART|DUMPFILE|CONT_DUMPFILE|SPLIT_DUMPFILE|TAPEEND"), tok);
381 (void)strtok(buf, "\n"); /* this is the first line */
382 /* iterate through the rest of the lines */
383 while ((line = strtok(NULL, "\n")) != NULL) {
384 #define SC "CONT_FILENAME="
385 if (strncmp(line, SC, SIZEOF(SC) - 1) == 0) {
386 line += SIZEOF(SC) - 1;
387 strncpy(file->cont_filename, line,
388 SIZEOF(file->cont_filename) - 1);
393 #define SC "PARTIAL="
394 if (strncmp(line, SC, SIZEOF(SC) - 1) == 0) {
395 line += SIZEOF(SC) - 1;
396 file->is_partial = !strcasecmp(line, "yes");
401 if (strncmp(line, SC, SIZEOF(SC) - 1) == 0) {
402 line += SIZEOF(SC) - 1;
403 strncpy(file->dumper, line,
404 SIZEOF(file->dumper) - 1);
409 #define SC _("To restore, position tape at start of file and run:")
410 if (strncmp(line, SC, SIZEOF(SC) - 1) == 0)
414 #define SC "\tdd if=<tape> bs="
415 if (strncmp(line, SC, SIZEOF(SC) - 1) == 0) {
416 char *cmd1, *cmd2, *cmd3=NULL;
418 /* skip over dd command */
419 if ((cmd1 = strchr(line, '|')) == NULL) {
421 strncpy(file->recover_cmd, "BUG",
422 SIZEOF(file->recover_cmd) - 1);
427 /* block out first pipeline command */
428 if ((cmd2 = strchr(cmd1, '|')) != NULL) {
430 if ((cmd3 = strchr(cmd2, '|')) != NULL)
434 /* three cmds: decrypt | uncompress | recover
435 * two cmds: uncompress | recover
436 * XXX note that if there are two cmds, the first one
437 * XXX could be either uncompress or decrypt. Since no
438 * XXX code actually call uncompress_cmd/decrypt_cmd, it's ok
439 * XXX for header information.
445 strncpy(file->recover_cmd, cmd1,
446 SIZEOF(file->recover_cmd) - 1);
448 g_snprintf(file->uncompress_cmd,
449 SIZEOF(file->uncompress_cmd), "%s|", cmd1);
450 strncpy(file->recover_cmd, cmd2,
451 SIZEOF(file->recover_cmd) - 1);
453 } else { /* cmd3 presents: decrypt | uncompress | recover */
454 g_snprintf(file->decrypt_cmd,
455 SIZEOF(file->decrypt_cmd), "%s|", cmd1);
456 g_snprintf(file->uncompress_cmd,
457 SIZEOF(file->uncompress_cmd), "%s|", cmd2);
458 strncpy(file->recover_cmd, cmd3,
459 SIZEOF(file->recover_cmd) - 1);
464 /* XXX complain about weird lines? */
474 const dumpfile_t *file)
476 dbprintf(_("Contents of *(dumpfile_t *)%p:\n"), file);
477 dbprintf(_(" type = %d (%s)\n"),
478 file->type, filetype2str(file->type));
479 dbprintf(_(" datestamp = '%s'\n"), file->datestamp);
480 dbprintf(_(" dumplevel = %d\n"), file->dumplevel);
481 dbprintf(_(" compressed = %d\n"), file->compressed);
482 dbprintf(_(" encrypted = %d\n"), file->encrypted);
483 dbprintf(_(" comp_suffix = '%s'\n"), file->comp_suffix);
484 dbprintf(_(" encrypt_suffix = '%s'\n"), file->encrypt_suffix);
485 dbprintf(_(" name = '%s'\n"), file->name);
486 dbprintf(_(" disk = '%s'\n"), file->disk);
487 dbprintf(_(" program = '%s'\n"), file->program);
488 dbprintf(_(" dumper = '%s'\n"), file->dumper);
489 dbprintf(_(" srvcompprog = '%s'\n"), file->srvcompprog);
490 dbprintf(_(" clntcompprog = '%s'\n"), file->clntcompprog);
491 dbprintf(_(" srv_encrypt = '%s'\n"), file->srv_encrypt);
492 dbprintf(_(" clnt_encrypt = '%s'\n"), file->clnt_encrypt);
493 dbprintf(_(" recover_cmd = '%s'\n"), file->recover_cmd);
494 dbprintf(_(" uncompress_cmd = '%s'\n"), file->uncompress_cmd);
495 dbprintf(_(" encrypt_cmd = '%s'\n"), file->encrypt_cmd);
496 dbprintf(_(" decrypt_cmd = '%s'\n"), file->decrypt_cmd);
497 dbprintf(_(" srv_decrypt_opt = '%s'\n"), file->srv_decrypt_opt);
498 dbprintf(_(" clnt_decrypt_opt = '%s'\n"), file->clnt_decrypt_opt);
499 dbprintf(_(" cont_filename = '%s'\n"), file->cont_filename);
500 dbprintf(_(" is_partial = %d\n"), file->is_partial);
501 dbprintf(_(" partnum = %d\n"), file->partnum);
502 dbprintf(_(" totalparts = %d\n"), file->totalparts);
503 dbprintf(_(" blocksize = %zu\n"), file->blocksize);
510 if (strlen(name) == 0) {
511 error(_("Invalid name '%s'\n"), name);
518 const char *datestamp)
520 if (strcmp(datestamp, "X") == 0) {
524 if ((strlen(datestamp) == 8) && match("^[0-9]{8}$", datestamp)) {
527 if ((strlen(datestamp) == 14) && match("^[0-9]{14}$", datestamp)) {
530 error(_("Invalid datestamp '%s'\n"), datestamp);
537 const int totalparts)
540 error(_("Invalid partnum (%d)\n"), partnum);
544 if (partnum > totalparts && totalparts >= 0) {
545 error(_("Invalid partnum (%d) > totalparts (%d)\n"),
546 partnum, totalparts);
552 build_header(const dumpfile_t * file, size_t size)
554 GString *rval, *split_data;
558 dbprintf(_("Building type %d (%s) header of size %zu using:\n"),
559 file->type, filetype2str(file->type), size);
560 dump_dumpfile_t(file);
562 rval = g_string_sized_new(size);
563 split_data = g_string_sized_new(10);
565 switch (file->type) {
567 validate_name(file->name);
568 validate_datestamp(file->datestamp);
569 g_string_printf(rval,
570 "AMANDA: TAPESTART DATE %s TAPE %s\n014\n",
571 file->datestamp, file->name);
574 case F_SPLIT_DUMPFILE:
575 validate_parts(file->partnum, file->totalparts);
576 g_string_printf(split_data,
577 " part %d/%d ", file->partnum, file->totalparts);
581 case F_CONT_DUMPFILE:
583 validate_name(file->name);
584 validate_datestamp(file->datestamp);
585 qname = quote_string(file->disk);
586 program = stralloc(file->program);
587 if (match("^.*[.][Ee][Xx][Ee]$", program)) {
588 /* Trim ".exe" from program name */
589 program[strlen(program) - strlen(".exe")] = '\0';
591 g_string_printf(rval,
592 "AMANDA: %s %s %s %s %s lev %d comp %s program %s",
593 filetype2str(file->type),
594 file->datestamp, file->name, qname,
596 file->dumplevel, file->comp_suffix, program);
600 /* only output crypt if it's enabled */
601 if (strcmp(file->encrypt_suffix, "enc") == 0) {
602 g_string_append_printf(rval, " crypt %s", file->encrypt_suffix);
605 if (*file->srvcompprog) {
606 g_string_append_printf(rval, " server_custom_compress %s",
608 } else if (*file->clntcompprog) {
609 g_string_append_printf(rval, " client_custom_compress %s",
613 if (*file->srv_encrypt) {
614 g_string_append_printf(rval, " server_encrypt %s",
616 } else if (*file->clnt_encrypt) {
617 g_string_append_printf(rval, " client_encrypt %s",
621 if (*file->srv_decrypt_opt) {
622 g_string_append_printf(rval, " server_decrypt_option %s",
623 file->srv_decrypt_opt);
624 } else if (*file->clnt_decrypt_opt) {
625 g_string_append_printf(rval, " client_decrypt_option %s",
626 file->clnt_decrypt_opt);
629 g_string_append_printf(rval, "\n");
631 if (file->cont_filename[0] != '\0') {
632 g_string_append_printf(rval, "CONT_FILENAME=%s\n",
633 file->cont_filename);
635 if (file->dumper[0] != '\0') {
636 g_string_append_printf(rval, "DUMPER=%s\n", file->dumper);
638 if (file->is_partial != 0) {
639 g_string_append_printf(rval, "PARTIAL=YES\n");
642 g_string_append_printf(rval,
643 _("To restore, position tape at start of file and run:\n"));
645 /* \014 == ^L == form feed */
646 g_string_append_printf(rval,
647 "\tdd if=<tape> bs=%zuk skip=1 |%s %s %s\n\014\n",
648 file->blocksize / 1024,
649 file->decrypt_cmd, file->uncompress_cmd,
654 validate_datestamp(file->datestamp);
655 g_string_printf(rval, "AMANDA: TAPEEND DATE %s\n\014\n",
663 error(_("Invalid header type: %d (%s)"),
664 file->type, filetype2str(file->type));
668 g_string_free(split_data, TRUE);
670 /* Since we don't return the length, it is an error for the header to be
671 * more than 'size' bytes */
672 assert(rval->len <= size);
673 /* Clear extra bytes. */
674 if (rval->len < size) {
675 bzero(rval->str + rval->len, rval->allocated_len - rval->len);
677 return g_string_free(rval, FALSE);
681 * Prints the contents of the file structure.
686 const dumpfile_t * file)
689 char number[NUM_STR_SIZE*2];
693 g_fprintf(outf, _("EMPTY file\n"));
697 g_fprintf(outf, _("UNKNOWN file\n"));
701 g_fprintf(outf, _("WEIRD file\n"));
705 g_fprintf(outf, _("start of tape: date %s label %s\n"),
706 file->datestamp, file->name);
710 case F_CONT_DUMPFILE:
711 qdisk = quote_string(file->disk);
712 g_fprintf(outf, "%s: date %s host %s disk %s lev %d comp %s",
713 filetype2str(file->type), file->datestamp, file->name,
714 qdisk, file->dumplevel, file->comp_suffix);
716 g_fprintf(outf, " program %s", file->program);
717 if (strcmp(file->encrypt_suffix, "enc") == 0)
718 g_fprintf(outf, " crypt %s", file->encrypt_suffix);
719 if (*file->srvcompprog)
720 g_fprintf(outf, " server_custom_compress %s", file->srvcompprog);
721 if (*file->clntcompprog)
722 g_fprintf(outf, " client_custom_compress %s", file->clntcompprog);
723 if (*file->srv_encrypt)
724 g_fprintf(outf, " server_encrypt %s", file->srv_encrypt);
725 if (*file->clnt_encrypt)
726 g_fprintf(outf, " client_encrypt %s", file->clnt_encrypt);
727 if (*file->srv_decrypt_opt)
728 g_fprintf(outf, " server_decrypt_option %s", file->srv_decrypt_opt);
729 if (*file->clnt_decrypt_opt)
730 g_fprintf(outf, " client_decrypt_option %s", file->clnt_decrypt_opt);
731 g_fprintf(outf, "\n");
735 case F_SPLIT_DUMPFILE:
736 if(file->totalparts > 0){
737 g_snprintf(number, SIZEOF(number), "%d", file->totalparts);
739 else g_snprintf(number, SIZEOF(number), "UNKNOWN");
740 qdisk = quote_string(file->disk);
741 g_fprintf(outf, "split dumpfile: date %s host %s disk %s part %d/%s lev %d comp %s",
742 file->datestamp, file->name, qdisk, file->partnum,
743 number, file->dumplevel, file->comp_suffix);
745 g_fprintf(outf, " program %s",file->program);
746 if (strcmp(file->encrypt_suffix, "enc") == 0)
747 g_fprintf(outf, " crypt %s", file->encrypt_suffix);
748 if (*file->srvcompprog)
749 g_fprintf(outf, " server_custom_compress %s", file->srvcompprog);
750 if (*file->clntcompprog)
751 g_fprintf(outf, " client_custom_compress %s", file->clntcompprog);
752 if (*file->srv_encrypt)
753 g_fprintf(outf, " server_encrypt %s", file->srv_encrypt);
754 if (*file->clnt_encrypt)
755 g_fprintf(outf, " client_encrypt %s", file->clnt_encrypt);
756 if (*file->srv_decrypt_opt)
757 g_fprintf(outf, " server_decrypt_option %s", file->srv_decrypt_opt);
758 if (*file->clnt_decrypt_opt)
759 g_fprintf(outf, " client_decrypt_option %s", file->clnt_decrypt_opt);
760 g_fprintf(outf, "\n");
765 g_fprintf(outf, "end of tape: date %s\n", file->datestamp);
772 const dumpfile_t * file)
774 if(strcmp(file->comp_suffix, ".Z") == 0)
777 if(strcmp(file->comp_suffix, ".gz") == 0)
780 if(strcmp(file->comp_suffix, "cust") == 0)
785 static const struct {
789 { F_UNKNOWN, "UNKNOWN" },
790 { F_WEIRD, "WEIRD" },
791 { F_TAPESTART, "TAPESTART" },
792 { F_TAPEEND, "TAPEEND" },
793 { F_DUMPFILE, "FILE" },
794 { F_CONT_DUMPFILE, "CONT_FILE" },
795 { F_SPLIT_DUMPFILE, "SPLIT_FILE" }
797 #define NFILETYPES (size_t)(sizeof(filetypetab) / sizeof(filetypetab[0]))
805 for (i = 0; i < (int)NFILETYPES; i++)
806 if (filetypetab[i].type == type)
807 return (filetypetab[i].str);
817 for (i = 0; i < (int)NFILETYPES; i++)
818 if (strcmp(filetypetab[i].str, str) == 0)
819 return (filetypetab[i].type);
823 gboolean headers_are_equal(dumpfile_t * a, dumpfile_t * b) {
824 if (a == NULL && b == NULL)
827 if (a == NULL || b == NULL)
830 return 0 == memcmp(a, b, sizeof(*a));
833 dumpfile_t * dumpfile_copy(dumpfile_t* source) {
834 gpointer rval = malloc(sizeof(dumpfile_t));
835 memcpy(rval, source, sizeof(dumpfile_t));
840 * This function modify strtok context.
845 char * tok = strtok(NULL, " ");
849 if ((tok != NULL) && (tok[0] == '"') &&
850 (len > 1 && (tok[len - 1] != '"') && (tok[len - 2] != '\\'))) {
854 t = strtok(NULL, " ");
857 } while ((t != NULL) &&
858 (tok[len - 1] != '"') && (tok[len - 2] != '\\'));
870 FILE *stream = popen("od -c -x -", "w");
872 if (stream != NULL) {
874 rc = (ssize_t)fwrite(buffer, len, 1, stream);