X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fstored%2Frecord.c;h=c0c564c0be5f1375b430d74005803308b49fc8cb;hb=b9265a6898ae36e450755721acfbf4a52342bc2f;hp=2183f49817119d763a31978456ad5a7c7c04d2db;hpb=f52955c3e03b6fef083df5b77ce25a75213e2539;p=bacula%2Fbacula diff --git a/bacula/src/stored/record.c b/bacula/src/stored/record.c index 2183f49817..c0c564c0be 100644 --- a/bacula/src/stored/record.c +++ b/bacula/src/stored/record.c @@ -3,12 +3,13 @@ * record.c -- tape record handling functions * * Kern Sibbald, April MMI + * added BB02 format October MMII * * Version $Id$ * */ /* - Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker + Copyright (C) 2000-2004 Kern Sibbald and John Walker This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -40,7 +41,7 @@ extern int debug_level; * record as a Label, otherwise it is simply * the FileIndex of the current file. */ -char *FI_to_ascii(int fi) +const char *FI_to_ascii(int fi) { static char buf[20]; if (fi >= 0) { @@ -58,6 +59,9 @@ char *FI_to_ascii(int fi) return "SOS_LABEL"; case EOS_LABEL: return "EOS_LABEL"; + case EOT_LABEL: + return "EOT_LABEL"; + break; default: sprintf(buf, "unknown: %d", fi); return buf; @@ -68,19 +72,70 @@ char *FI_to_ascii(int fi) /* * Convert a Stream ID into a printable * ASCII string. Not reentrant. + + * A negative stream number represents + * stream data that is continued from a + * record in the previous block. + * If the FileIndex is negative, we are + * dealing with a Label, hence the + * stream is the JobId. */ -char *stream_to_ascii(int stream) +const char *stream_to_ascii(int stream, int fi) { static char buf[20]; + if (fi < 0) { + sprintf(buf, "%d", stream); + return buf; + } switch (stream) { case STREAM_UNIX_ATTRIBUTES: return "UATTR"; case STREAM_FILE_DATA: return "DATA"; + case STREAM_WIN32_DATA: + return "WIN32-DATA"; + case STREAM_WIN32_GZIP_DATA: + return "WIN32-GZIP"; case STREAM_MD5_SIGNATURE: return "MD5"; + case STREAM_SHA1_SIGNATURE: + return "SHA1"; case STREAM_GZIP_DATA: return "GZIP"; + case STREAM_UNIX_ATTRIBUTES_EX: + return "UNIX-ATTR-EX"; + case STREAM_SPARSE_DATA: + return "SPARSE-DATA"; + case STREAM_SPARSE_GZIP_DATA: + return "SPARSE-GZIP"; + case STREAM_PROGRAM_NAMES: + return "PROG-NAMES"; + case STREAM_PROGRAM_DATA: + return "PROG-DATA"; + case -STREAM_UNIX_ATTRIBUTES: + return "contUATTR"; + case -STREAM_FILE_DATA: + return "contDATA"; + case -STREAM_WIN32_DATA: + return "contWIN32-DATA"; + case -STREAM_WIN32_GZIP_DATA: + return "contWIN32-GZIP"; + case -STREAM_MD5_SIGNATURE: + return "contMD5"; + case -STREAM_SHA1_SIGNATURE: + return "contSHA1"; + case -STREAM_GZIP_DATA: + return "contGZIP"; + case -STREAM_UNIX_ATTRIBUTES_EX: + return "contUNIX-ATTR-EX"; + case -STREAM_SPARSE_DATA: + return "contSPARSE-DATA"; + case -STREAM_SPARSE_GZIP_DATA: + return "contSPARSE-GZIP"; + case -STREAM_PROGRAM_NAMES: + return "contPROG-NAMES"; + case -STREAM_PROGRAM_DATA: + return "contPROG-DATA"; default: sprintf(buf, "%d", stream); return buf; @@ -94,7 +149,7 @@ DEV_RECORD *new_record(void) { DEV_RECORD *rec; - rec = (DEV_RECORD *) get_memory(sizeof(DEV_RECORD)); + rec = (DEV_RECORD *)get_memory(sizeof(DEV_RECORD)); memset(rec, 0, sizeof(DEV_RECORD)); rec->data = get_pool_memory(PM_MESSAGE); return rec; @@ -107,7 +162,9 @@ DEV_RECORD *new_record(void) void free_record(DEV_RECORD *rec) { Dmsg0(150, "Enter free_record.\n"); - free_pool_memory(rec->data); + if (rec->data) { + free_pool_memory(rec->data); + } Dmsg0(150, "Data buf is freed.\n"); free_pool_memory((POOLMEM *)rec); Dmsg0(150, "Leave free_record.\n"); @@ -133,16 +190,15 @@ int write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec) ser_declare; uint32_t remlen; - sm_check(__FILE__, __LINE__, False); remlen = block->buf_len - block->binbuf; ASSERT(block->binbuf == (uint32_t) (block->bufp - block->buf)); - ASSERT(remlen >= 0); + ASSERT(block->buf_len >= block->binbuf); Dmsg6(190, "write_record_to_block() FI=%s SessId=%d Strm=%s len=%d\n\ rem=%d remainder=%d\n", FI_to_ascii(rec->FileIndex), rec->VolSessionId, - stream_to_ascii(rec->Stream), rec->data_len, + stream_to_ascii(rec->Stream, rec->FileIndex), rec->data_len, remlen, rec->remainder); /* @@ -152,22 +208,32 @@ rem=%d remainder=%d\n", */ if (rec->remainder == 0) { /* Require enough room to write a full header */ - if (remlen >= RECHDR_LENGTH) { - ser_begin(block->bufp, RECHDR_LENGTH); - ser_uint32(rec->VolSessionId); - ser_uint32(rec->VolSessionTime); + if (remlen >= WRITE_RECHDR_LENGTH) { + ser_begin(block->bufp, WRITE_RECHDR_LENGTH); + if (BLOCK_VER == 1) { + ser_uint32(rec->VolSessionId); + ser_uint32(rec->VolSessionTime); + } else { + block->VolSessionId = rec->VolSessionId; + block->VolSessionTime = rec->VolSessionTime; + } ser_int32(rec->FileIndex); ser_int32(rec->Stream); ser_uint32(rec->data_len); - ASSERT(ser_length(block->bufp) == RECHDR_LENGTH); - block->bufp += RECHDR_LENGTH; - block->binbuf += RECHDR_LENGTH; - remlen -= RECHDR_LENGTH; + block->bufp += WRITE_RECHDR_LENGTH; + block->binbuf += WRITE_RECHDR_LENGTH; + remlen -= WRITE_RECHDR_LENGTH; rec->remainder = rec->data_len; + if (rec->FileIndex > 0) { + /* If data record, update what we have in this block */ + if (block->FirstIndex == 0) { + block->FirstIndex = rec->FileIndex; + } + block->LastIndex = rec->FileIndex; + } } else { - rec->remainder = rec->data_len + RECHDR_LENGTH; - sm_check(__FILE__, __LINE__, False); + rec->remainder = rec->data_len + WRITE_RECHDR_LENGTH; return 0; } } else { @@ -176,8 +242,8 @@ rem=%d remainder=%d\n", * time. Presumably we have a new buffer (possibly * containing a volume label), so the new header * should be able to fit in the block -- otherwise we have - * an error. Note, we may have to continue splitting the - * data record though. + * an error. Note, we have to continue splitting the + * data record if it is longer than the block. * * First, write the header, then write as much as * possible of the data record. @@ -186,9 +252,14 @@ rem=%d remainder=%d\n", * of a previous partially written record, we store the * Stream as -Stream in the record header. */ - ser_begin(block->bufp, RECHDR_LENGTH); - ser_uint32(rec->VolSessionId); - ser_uint32(rec->VolSessionTime); + ser_begin(block->bufp, WRITE_RECHDR_LENGTH); + if (BLOCK_VER == 1) { + ser_uint32(rec->VolSessionId); + ser_uint32(rec->VolSessionTime); + } else { + block->VolSessionId = rec->VolSessionId; + block->VolSessionTime = rec->VolSessionTime; + } ser_int32(rec->FileIndex); if (rec->remainder > rec->data_len) { ser_int32(rec->Stream); /* normal full header */ @@ -198,17 +269,22 @@ rem=%d remainder=%d\n", ser_int32(-rec->Stream); /* mark this as a continuation record */ ser_uint32(rec->remainder); /* bytes to do */ } - ASSERT(ser_length(block->bufp) == RECHDR_LENGTH); /* Require enough room to write a full header */ - ASSERT(remlen >= RECHDR_LENGTH); - - block->bufp += RECHDR_LENGTH; - block->binbuf += RECHDR_LENGTH; - remlen -= RECHDR_LENGTH; + ASSERT(remlen >= WRITE_RECHDR_LENGTH); + + block->bufp += WRITE_RECHDR_LENGTH; + block->binbuf += WRITE_RECHDR_LENGTH; + remlen -= WRITE_RECHDR_LENGTH; + if (rec->FileIndex > 0) { + /* If data record, update what we have in this block */ + if (block->FirstIndex == 0) { + block->FirstIndex = rec->FileIndex; + } + block->LastIndex = rec->FileIndex; + } } if (remlen == 0) { - sm_check(__FILE__, __LINE__, False); return 0; /* partial transfer */ } @@ -227,12 +303,13 @@ rem=%d remainder=%d\n", } else { memcpy(block->bufp, rec->data+rec->data_len-rec->remainder, remlen); +#ifdef xxxxxSMCHECK if (!sm_check_rtn(__FILE__, __LINE__, False)) { /* We damaged a buffer */ Dmsg6(0, "Damaged block FI=%s SessId=%d Strm=%s len=%d\n\ rem=%d remainder=%d\n", FI_to_ascii(rec->FileIndex), rec->VolSessionId, - stream_to_ascii(rec->Stream), rec->data_len, + stream_to_ascii(rec->Stream, rec->FileIndex), rec->data_len, remlen, rec->remainder); Dmsg5(0, "Damaged block: bufp=%x binbuf=%d buf_len=%d rem=%d moved=%d\n", block->bufp, block->binbuf, block->buf_len, block->buf_len-block->binbuf, @@ -242,6 +319,7 @@ rem=%d remainder=%d\n", Emsg0(M_ABORT, 0, "Damaged buffer\n"); } +#endif block->bufp += remlen; block->binbuf += remlen; @@ -250,7 +328,6 @@ rem=%d remainder=%d\n", } } rec->remainder = 0; /* did whole transfer */ - sm_check(__FILE__, __LINE__, False); return 1; } @@ -267,8 +344,8 @@ int can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec) remlen = block->buf_len - block->binbuf; if (rec->remainder == 0) { - if (remlen >= RECHDR_LENGTH) { - remlen -= RECHDR_LENGTH; + if (remlen >= WRITE_RECHDR_LENGTH) { + remlen -= WRITE_RECHDR_LENGTH; rec->remainder = rec->data_len; } else { return 0; @@ -300,34 +377,60 @@ int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec) int32_t FileIndex; int32_t Stream; uint32_t data_bytes; + uint32_t rhl; remlen = block->binbuf; + rec->Block = block->BlockNumber; + rec->File = ((DEVICE *)block->dev)->file; - /* Clear state flags */ + /* Clear state flags */ rec->state = 0; + if (((DEVICE *)block->dev)->state & ST_TAPE) { + rec->state |= REC_ISTAPE; + } + /* * Get the header. There is always a full header, * otherwise we find it in the next block. */ - if (remlen >= RECHDR_LENGTH) { - Dmsg3(90, "read_record_block: remlen=%d data_len=%d rem=%d\n", - remlen, rec->data_len, rec->remainder); - - unser_begin(block->bufp, RECHDR_LENGTH); - unser_uint32(VolSessionId); - unser_uint32(VolSessionTime); + Dmsg3(100, "Block=%d Ver=%d size=%u\n", block->BlockNumber, block->BlockVer, + block->block_len); + if (block->BlockVer == 1) { + rhl = RECHDR1_LENGTH; + } else { + rhl = RECHDR2_LENGTH; + } + if (remlen >= rhl) { + Dmsg4(90, "Enter read_record_block: remlen=%d data_len=%d rem=%d blkver=%d\n", + remlen, rec->data_len, rec->remainder, block->BlockVer); + + unser_begin(block->bufp, WRITE_RECHDR_LENGTH); + if (block->BlockVer == 1) { + unser_uint32(VolSessionId); + unser_uint32(VolSessionTime); + } else { + VolSessionId = block->VolSessionId; + VolSessionTime = block->VolSessionTime; + } unser_int32(FileIndex); unser_int32(Stream); unser_uint32(data_bytes); - ASSERT(unser_length(block->bufp) == RECHDR_LENGTH); - block->bufp += RECHDR_LENGTH; - block->binbuf -= RECHDR_LENGTH; - remlen -= RECHDR_LENGTH; + block->bufp += rhl; + block->binbuf -= rhl; + remlen -= rhl; - /* - * if Stream is negative, it means that this is a continuation + /* If we are looking for more (remainder!=0), we reject anything + * where the VolSessionId and VolSessionTime don't agree + */ + if (rec->remainder && (rec->VolSessionId != VolSessionId || + rec->VolSessionTime != VolSessionTime)) { + rec->state |= REC_NO_MATCH; + return 0; /* This is from some other Session */ + } + + /* if Stream is negative, it means that this is a continuation * of a previous partially written record. */ if (Stream < 0) { /* continuation record? */ @@ -336,9 +439,7 @@ int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec) rec->state |= REC_CONTINUATION; if (!rec->remainder) { /* if we didn't read previously */ rec->data_len = 0; /* return data as if no continuation */ - } else if (rec->VolSessionId != VolSessionId || - rec->VolSessionTime != VolSessionTime || - rec->Stream != -Stream) { + } else if (rec->Stream != -Stream) { rec->state |= REC_NO_MATCH; return 0; /* This is from some other Session */ } @@ -350,11 +451,18 @@ int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec) rec->VolSessionId = VolSessionId; rec->VolSessionTime = VolSessionTime; rec->FileIndex = FileIndex; + if (FileIndex > 0) { + if (block->FirstIndex == 0) { + block->FirstIndex = FileIndex; + } + block->LastIndex = FileIndex; + } - Dmsg6(90, "rd_rec_blk() got FI=%s SessId=%d Strm=%s len=%d\n\ -remlen=%d data_len=%d\n", + Dmsg6(100, "rd_rec_blk() got FI=%s SessId=%d Strm=%s len=%u\n" + "remlen=%d data_len=%d\n", FI_to_ascii(rec->FileIndex), rec->VolSessionId, - stream_to_ascii(rec->Stream), data_bytes, remlen, rec->data_len); + stream_to_ascii(rec->Stream, rec->FileIndex), data_bytes, remlen, + rec->data_len); } else { /* * No more records in this block because the number @@ -365,11 +473,14 @@ remlen=%d data_len=%d\n", * then reread. */ Dmsg0(90, "read_record_block: nothing\n"); +#ifdef xxx if (!rec->remainder) { rec->remainder = 1; /* set to expect continuation */ rec->data_len = 0; /* no data transferred */ } +#endif rec->state |= (REC_NO_HEADER | REC_BLOCK_EMPTY); + empty_block(block); /* mark block empty */ return 0; } @@ -405,6 +516,6 @@ remlen=%d data_len=%d\n", rec->remainder = 0; Dmsg4(90, "Rtn full rd_rec_blk FI=%s SessId=%d Strm=%s len=%d\n", FI_to_ascii(rec->FileIndex), rec->VolSessionId, - stream_to_ascii(rec->Stream), rec->data_len); + stream_to_ascii(rec->Stream, rec->FileIndex), rec->data_len); return 1; /* transferred full record */ }