From 3c4aa7c0dd0b6831656bdcc7703849f62471b689 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Mon, 9 Jun 2003 16:41:24 +0000 Subject: [PATCH] Big reorganization of restore code into lib/attr.c git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@574 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/kernstodo | 4 + bacula/src/baconfig.h | 49 ++- bacula/src/cats/sql_create.c | 6 +- bacula/src/dird/backup.c | 2 +- bacula/src/dird/catreq.c | 5 +- bacula/src/dird/job.c | 3 - bacula/src/dird/restore.c | 4 +- bacula/src/dird/ua_run.c | 18 +- bacula/src/filed/backup.c | 2 +- bacula/src/filed/estimate.c | 2 +- bacula/src/filed/job.c | 6 +- bacula/src/filed/restore.c | 318 +++++------------ bacula/src/filed/verify.c | 2 +- bacula/src/filed/verify_vol.c | 47 +-- bacula/src/findlib/attribs.c | 83 +++-- bacula/src/findlib/bfile.c | 58 +++ bacula/src/findlib/bfile.h | 43 +-- bacula/src/findlib/create_file.c | 106 +++--- bacula/src/findlib/find.c | 3 +- bacula/src/findlib/find.h | 21 -- bacula/src/findlib/protos.h | 38 +- bacula/src/jcr.h | 5 +- bacula/src/lib/Makefile.in | 4 +- bacula/src/lib/attr.c | 213 +++++++++++ bacula/src/lib/attr.h | 41 +++ bacula/src/lib/bnet.c | 19 +- bacula/src/lib/jcr.c | 4 + bacula/src/lib/lib.h | 1 + bacula/src/lib/message.c | 2 +- bacula/src/lib/message.h | 1 + bacula/src/lib/protos.h | 219 ++++++------ bacula/src/lib/util.c | 6 - bacula/src/stored/.cvsignore | 2 + bacula/src/stored/append.c | 8 +- bacula/src/stored/bextract.c | 351 ++++++++---------- bacula/src/stored/bls.c | 172 +++++---- bacula/src/stored/bscan.c | 594 ++++++++++++++----------------- bacula/src/stored/butil.c | 39 +- bacula/src/stored/record.c | 8 +- bacula/src/stored/stored.h | 6 +- 40 files changed, 1277 insertions(+), 1238 deletions(-) create mode 100644 bacula/src/lib/attr.c create mode 100644 bacula/src/lib/attr.h diff --git a/bacula/kernstodo b/bacula/kernstodo index 874ca22d7c..fe52edebff 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -34,10 +34,14 @@ Testing to do: (painful) - Figure out how to use ssh or stunnel to protect Bacula communications. For 1.31 release: +- Implement non-blocking writes and bsock->terminate in heartbeat thread, + or set it in status.c cancel. +- Add restore to specific date. - lstat() is not going to work on Win32 for testing date. - Implement a Recycle command - Something is not right in last block of fill command. - Check this below from Phil. + This was SD reported data rather than FD data! > When the job was done, Bacula reported 11084 files restored: > > JobId: 527 diff --git a/bacula/src/baconfig.h b/bacula/src/baconfig.h index ff4eef9e06..4a7dc15d97 100644 --- a/bacula/src/baconfig.h +++ b/bacula/src/baconfig.h @@ -89,19 +89,30 @@ #define DEV_BSIZE 512 #endif -/* Maximum number of bytes that you can push into a +/* + * Maximum number of bytes that you can push into a * socket. */ #define MAX_NETWORK_BUFFER_SIZE (32 * 1024) -/* Stream definitions. Once defined these must NEVER +/* + * Stream definitions. Once defined these must NEVER * change as they go on the storage media. + * Note, the following streams are passed from the SD to the DIR + * so that they may be put into the catalog (actually only the + * stat packet part of the attr record is put in the catalog. + * + * STREAM_UNIX_ATTRIBUTES + * STREAM_UNIX_ATTRIBUTES_EX + * STREAM_MD5_SIGNATURE + * STREAM_SHA1_SIGNATURE */ #define STREAM_UNIX_ATTRIBUTES 1 /* Generic Unix attributes */ #define STREAM_FILE_DATA 2 /* Standard uncompressed data */ #define STREAM_MD5_SIGNATURE 3 /* MD5 signature for the file */ #define STREAM_GZIP_DATA 4 /* GZip compressed file data */ -#define STREAM_UNIX_ATTRIBUTES_EX 5 /* Extended Unix attr. Win32Ex/FreeBSD */ +/* Extended Unix attributes with Win32 Extended data. Deprecated. */ +#define STREAM_UNIX_ATTRIBUTES_EX 5 /* Extended Unix attr for Win32 EX */ #define STREAM_SPARSE_DATA 6 /* Sparse data stream */ #define STREAM_SPARSE_GZIP_DATA 7 #define STREAM_PROGRAM_NAMES 8 /* program names for program data */ @@ -109,6 +120,38 @@ #define STREAM_SHA1_SIGNATURE 10 /* SHA1 signature for the file */ #define STREAM_WIN32_DATA 11 /* Win32 BackupRead data */ #define STREAM_WIN32_GZIP_DATA 12 /* Gzipped Win32 BackupRead data */ +#define STREAM_WIN32_ATTRIBUTES 13 /* Unix attribs, but WIN32_DATA follows */ + +/* + * File type (Bacula defined). + * NOTE!!! These are saved in the Attributes record on the tape, so + * do not change them. If need be, add to them. + * + * This is stored as 32 bits on tape, but only FT_MASK bits are + * used for the file type. The upper bits are used to indicate + * additional optional fields in the attribute record. + */ +#define FT_MASK 0xFFFF /* Bits used by FT (type) */ +#define FT_LNKSAVED 1 /* hard link to file already saved */ +#define FT_REGE 2 /* Regular file but empty */ +#define FT_REG 3 /* Regular file */ +#define FT_LNK 4 /* Soft Link */ +#define FT_DIR 5 /* Directory */ +#define FT_SPEC 6 /* Special file -- chr, blk, fifo, sock */ +#define FT_NOACCESS 7 /* Not able to access */ +#define FT_NOFOLLOW 8 /* Could not follow link */ +#define FT_NOSTAT 9 /* Could not stat file */ +#define FT_NOCHG 10 /* Incremental option, file not changed */ +#define FT_DIRNOCHG 11 /* Incremental option, directory not changed */ +#define FT_ISARCH 12 /* Trying to save archive file */ +#define FT_NORECURSE 13 /* No recursion into directory */ +#define FT_NOFSCHG 14 /* Different file system, prohibited */ +#define FT_NOOPEN 15 /* Could not open directory */ +#define FT_RAW 16 /* Raw block device */ +#define FT_FIFO 17 /* Raw fifo device */ + +/* Definitions for upper part of type word (see above). */ +#define AR_DATA_STREAM (1<<16) /* Data stream id present */ /* * Internal code for Signature types diff --git a/bacula/src/cats/sql_create.c b/bacula/src/cats/sql_create.c index 0b6c4183be..e8edba50b6 100644 --- a/bacula/src/cats/sql_create.c +++ b/bacula/src/cats/sql_create.c @@ -521,8 +521,8 @@ static int db_create_file_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar) /* Must create it */ Mmsg(&mdb->cmd, -"INSERT INTO File (FileIndex, JobId, PathId, FilenameId, \ -LStat, MD5) VALUES (%u, %u, %u, %u, '%s', '0')", +"INSERT INTO File (FileIndex,JobId,PathId,FilenameId," +"LStat,MD5) VALUES (%u,%u,%u,%u,'%s','0')", ar->FileIndex, ar->JobId, ar->PathId, ar->FilenameId, ar->attr); @@ -589,7 +589,7 @@ static int db_create_path_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar) sql_free_result(mdb); } - Mmsg(&mdb->cmd, "INSERT INTO Path (Path) VALUES ('%s')", mdb->esc_name); + Mmsg(&mdb->cmd, "INSERT INTO Path (Path) VALUES ('%s')", mdb->esc_name); if (!INSERT_DB(jcr, mdb, mdb->cmd)) { Mmsg2(&mdb->errmsg, _("Create db Path record %s failed. ERR=%s\n"), diff --git a/bacula/src/dird/backup.c b/bacula/src/dird/backup.c index 21ec4630c0..e9151ec85b 100644 --- a/bacula/src/dird/backup.c +++ b/bacula/src/dird/backup.c @@ -120,7 +120,7 @@ int do_backup(JCR *jcr) jcr->jr.JobId = 0; if (!db_find_job_start_time(jcr, jcr->db, &jcr->jr, &jcr->stime)) { Jmsg(jcr, M_INFO, 0, "%s", db_strerror(jcr->db)); - Jmsg(jcr, M_INFO, 0, _("No prior or suitable FULL backup found. Doing FULL backup.\n")); + Jmsg(jcr, M_INFO, 0, _("No prior or suitable Full backup found. Doing FULL backup.\n")); bsnprintf(since, sizeof(since), " (upgraded from %s)", level_to_str(jcr->jr.Level)); jcr->JobLevel = jcr->jr.Level = L_FULL; diff --git a/bacula/src/dird/catreq.c b/bacula/src/dird/catreq.c index 9abe3b509d..6c091d90fe 100644 --- a/bacula/src/dird/catreq.c +++ b/bacula/src/dird/catreq.c @@ -356,7 +356,10 @@ next_volume: /* * Update File Attributes in the catalog with data - * sent by the Storage daemon. + * sent by the Storage daemon. Note, we receive the whole + * attribute record, but we select out only the stat packet, + * VolSessionId, VolSessionTime, FileIndex, and file name + * to store in the catalog. */ void catalog_update(JCR *jcr, BSOCK *bs, char *msg) { diff --git a/bacula/src/dird/job.c b/bacula/src/dird/job.c index 23f2b98a4c..c67c4a0129 100644 --- a/bacula/src/dird/job.c +++ b/bacula/src/dird/job.c @@ -565,9 +565,6 @@ void dird_free_jcr(JCR *jcr) Dmsg0(200, "Close DB\n"); db_close_database(jcr, jcr->db); } - if (jcr->RestoreWhere) { - free(jcr->RestoreWhere); - } if (jcr->RestoreBootstrap) { free(jcr->RestoreBootstrap); } diff --git a/bacula/src/dird/restore.c b/bacula/src/dird/restore.c index a017ab6184..52c1b66f88 100644 --- a/bacula/src/dird/restore.c +++ b/bacula/src/dird/restore.c @@ -229,8 +229,8 @@ int do_restore(JCR *jcr) } else { replace = REPLACE_ALWAYS; /* always replace */ } - if (jcr->RestoreWhere) { - where = jcr->RestoreWhere; /* override */ + if (jcr->where) { + where = jcr->where; /* override */ } else if (jcr->job->RestoreWhere) { where = jcr->job->RestoreWhere; /* no override take from job */ } else { diff --git a/bacula/src/dird/ua_run.c b/bacula/src/dird/ua_run.c index e33543e408..2da53b44c4 100644 --- a/bacula/src/dird/ua_run.c +++ b/bacula/src/dird/ua_run.c @@ -288,10 +288,10 @@ int runcmd(UAContext *ua, char *cmd) jcr->fileset = fileset; jcr->pool = pool; if (where) { - if (jcr->RestoreWhere) { - free(jcr->RestoreWhere); + if (jcr->where) { + free(jcr->where); } - jcr->RestoreWhere = bstrdup(where); + jcr->where = bstrdup(where); } if (when) { @@ -414,7 +414,7 @@ Storage: %s\n\ When: %s\n"), job->hdr.name, NPRT(jcr->RestoreBootstrap), - jcr->RestoreWhere?jcr->RestoreWhere:NPRT(job->RestoreWhere), + jcr->where?jcr->where:NPRT(job->RestoreWhere), replace, jcr->fileset->hdr.name, jcr->client->hdr.name, @@ -432,7 +432,7 @@ Storage: %s\n\ When: %s\n"), job->hdr.name, NPRT(jcr->RestoreBootstrap), - jcr->RestoreWhere?jcr->RestoreWhere:NPRT(job->RestoreWhere), + jcr->where?jcr->where:NPRT(job->RestoreWhere), replace, jcr->fileset->hdr.name, jcr->client->hdr.name, @@ -619,14 +619,14 @@ When: %s\n"), if (!get_cmd(ua, _("Please enter path prefix for restore (/ for none): "))) { break; } - if (jcr->RestoreWhere) { - free(jcr->RestoreWhere); - jcr->RestoreWhere = NULL; + if (jcr->where) { + free(jcr->where); + jcr->where = NULL; } if (ua->cmd[0] == '/' && ua->cmd[1] == 0) { ua->cmd[0] = 0; } - jcr->RestoreWhere = bstrdup(ua->cmd); + jcr->where = bstrdup(ua->cmd); goto try_again; case 8: /* Replace */ diff --git a/bacula/src/filed/backup.c b/bacula/src/filed/backup.c index 8db9a7ebbb..a7f2ea0c24 100644 --- a/bacula/src/filed/backup.c +++ b/bacula/src/filed/backup.c @@ -71,7 +71,7 @@ int blast_data_to_storage_daemon(JCR *jcr, char *addr) jcr->compress_buf = get_memory(jcr->compress_buf_size); Dmsg1(100, "set_find_options ff=%p\n", jcr->ff); - set_find_options((FF_PKT *)jcr->ff, jcr->incremental, jcr->mtime); + set_find_options((FF_PKT *)jcr->ff, jcr->incremental, jcr->mtime, jcr->mtime_only); Dmsg0(110, "start find files\n"); start_heartbeat_monitor(jcr); diff --git a/bacula/src/filed/estimate.c b/bacula/src/filed/estimate.c index dbec154325..24d0471717 100644 --- a/bacula/src/filed/estimate.c +++ b/bacula/src/filed/estimate.c @@ -41,7 +41,7 @@ int make_estimate(JCR *jcr) jcr->JobStatus = JS_Running; - set_find_options((FF_PKT *)jcr->ff, jcr->incremental, jcr->mtime); + set_find_options((FF_PKT *)jcr->ff, jcr->incremental, jcr->mtime, jcr->mtime_only); stat = find_files(jcr, (FF_PKT *)jcr->ff, tally_file, (void *)jcr); diff --git a/bacula/src/filed/job.c b/bacula/src/filed/job.c index 274bb7426d..343f1d2f7e 100644 --- a/bacula/src/filed/job.c +++ b/bacula/src/filed/job.c @@ -739,7 +739,8 @@ static int restore_cmd(JCR *jcr) Dmsg2(150, "Got replace %c, where=%s\n", replace, where); unbash_spaces(where); - jcr->where = where; + jcr->where = bstrdup(where); + free_pool_memory(where); jcr->replace = replace; bnet_fsend(dir, OKrestore); @@ -854,9 +855,6 @@ static void filed_free_jcr(JCR *jcr) if (jcr->store_bsock) { bnet_close(jcr->store_bsock); } - if (jcr->where) { - free_pool_memory(jcr->where); - } if (jcr->RestoreBootstrap) { unlink(jcr->RestoreBootstrap); free_pool_memory(jcr->RestoreBootstrap); diff --git a/bacula/src/filed/restore.c b/bacula/src/filed/restore.c index 766dd74e81..8b4a7e0772 100644 --- a/bacula/src/filed/restore.c +++ b/bacula/src/filed/restore.c @@ -33,7 +33,6 @@ static char rec_header[] = "rechdr %ld %ld %ld %ld %ld"; /* Forward referenced functions */ -static void print_ls_output(JCR *jcr, char *fname, char *lname, int type, struct stat *statp); #define RETRY 10 /* retry wait time */ @@ -45,22 +44,21 @@ void do_restore(JCR *jcr) { int wherelen; BSOCK *sd; - POOLMEM *fname; /* original file name */ - POOLMEM *ofile; /* output name with possible prefix */ - POOLMEM *lname; /* link name with possible prefix */ - POOLMEM *attribsEx; /* Extended attributes (Win32) */ int32_t stream; uint32_t size; - uint32_t VolSessionId, VolSessionTime, file_index; - uint32_t record_file_index; - struct stat statp; + uint32_t VolSessionId, VolSessionTime; + int32_t file_index; int extract = FALSE; BFILE bfd; - int type, stat; + int stat; uint32_t total = 0; /* Job total but only 32 bits for debug */ char *wbuf; /* write buffer */ uint32_t wsize; /* write size */ uint64_t fileAddr = 0; /* file write address */ + int non_support_data = 0; + int non_support_attr = 0; + int prog_name_msg = 0; + ATTR *attr; wherelen = strlen(jcr->where); @@ -74,10 +72,7 @@ void do_restore(JCR *jcr) } jcr->buf_size = sd->msglen; - fname = get_pool_memory(PM_FNAME); - ofile = get_pool_memory(PM_FNAME); - lname = get_pool_memory(PM_FNAME); - attribsEx = get_pool_memory(PM_FNAME); + attr = new_attr(); #ifdef HAVE_LIBZ uint32_t compress_buf_size = jcr->buf_size + 12 + ((jcr->buf_size+999) / 1000) + 100; @@ -119,8 +114,9 @@ void do_restore(JCR *jcr) Dmsg1(30, "Got stream data, len=%d\n", sd->msglen); /* File Attributes stream */ - if (stream == STREAM_UNIX_ATTRIBUTES || stream == STREAM_WIN32_ATTRIBUTES) { - char *ap, *lp, *fp, *apex; + switch (stream) { + case STREAM_UNIX_ATTRIBUTES: + case STREAM_UNIX_ATTRIBUTES_EX: uint32_t LinkFI; Dmsg1(30, "Stream=Unix Attributes. extract=%d\n", extract); @@ -131,149 +127,33 @@ void do_restore(JCR *jcr) if (!is_bopen(&bfd)) { Jmsg0(jcr, M_ERROR, 0, _("Logic error output file should be open\n")); } - set_attributes(jcr, fname, ofile, lname, type, stream, - &statp, attribsEx, &bfd); + set_attributes(jcr, attr, &bfd); extract = FALSE; Dmsg0(30, "Stop extracting.\n"); } - if ((int)sizeof_pool_memory(fname) < sd->msglen) { - fname = realloc_pool_memory(fname, sd->msglen + 1); - } - if ((int)sizeof_pool_memory(ofile) < sd->msglen + wherelen + 1) { - ofile = realloc_pool_memory(ofile, sd->msglen + wherelen + 1); - } - if ((int)sizeof_pool_memory(lname) < sd->msglen + wherelen + 1) { - lname = realloc_pool_memory(lname, sd->msglen + wherelen + 1); - } - *fname = 0; - *lname = 0; - - /* - * An Attributes record consists of: - * File_index - * Type (FT_types) - * Filename - * Attributes - * Link name (if file linked i.e. FT_LNK) - * Extended attributes (Win32) - * - */ - Dmsg1(100, "Attr: %s\n", sd->msg); - if (sscanf(sd->msg, "%d %d", &record_file_index, &type) != 2) { - Jmsg(jcr, M_FATAL, 0, _("Error scanning attributes: %s\n"), sd->msg); - Dmsg1(100, "\nError scanning attributes. %s\n", sd->msg); + if (!unpack_attributes_record(jcr, stream, sd->msg, attr)) { goto bail_out; } - Dmsg2(100, "Got Attr: FilInx=%d type=%d\n", record_file_index, type); - if (record_file_index != file_index) { + if (file_index != attr->file_index) { Jmsg(jcr, M_FATAL, 0, _("Record header file index %ld not equal record index %ld\n"), - file_index, record_file_index); + file_index, attr->file_index); Dmsg0(100, "File index error\n"); goto bail_out; } - ap = sd->msg; - while (*ap++ != ' ') /* skip record file index */ - ; - while (*ap++ != ' ') /* skip type */ - ; - /* Save filename and position to attributes */ - fp = fname; - while (*ap != 0) { - *fp++ = *ap++; /* copy filename to fname */ - } - *fp = *ap++; /* terminate filename & point to attribs */ + + Dmsg3(200, "File %s\nattrib=%s\nattribsEx=%s\n", attr->fname, + attr->attr, attr->attrEx); - /* Skip to Link name */ - if (type == FT_LNK || type == FT_LNKSAVED) { - lp = ap; - while (*lp++ != 0) { - ; - } - } else { - lp = ""; - } + decode_stat(attr->attr, &attr->statp, &LinkFI); - if (stream == STREAM_WIN32_ATTRIBUTES) { - apex = ap; /* start at attributes */ - while (*apex++ != 0) { /* skip attributes */ - ; - } - while (*apex++ != 0) { /* skip link name */ - ; - } - pm_strcpy(&attribsEx, apex); /* make a copy */ - } else { - *attribsEx = 0; /* no extended attributes */ - } - - Dmsg3(200, "File %s\nattrib=%s\nattribsEx=%s\n", fname, ap, attribsEx); - - decode_stat(ap, &statp, &LinkFI); - /* - * Prepend the where directory so that the - * files are put where the user wants. - * - * We do a little jig here to handle Win32 files with - * a drive letter -- we simply strip the drive: from - * every filename if a prefix is supplied. - * - */ - if (jcr->where[0] == 0) { - strcpy(ofile, fname); - strcpy(lname, lp); - } else { - char *fn; - strcpy(ofile, jcr->where); /* copy prefix */ - if (win32_client && fname[1] == ':') { - fn = fname+2; /* skip over drive: */ - } else { - fn = fname; /* take whole name */ - } - /* Ensure where is terminated with a slash */ - if (jcr->where[wherelen-1] != '/' && fn[0] != '/') { - strcat(ofile, "/"); - } - strcat(ofile, fn); /* copy rest of name */ - /* - * Fixup link name -- if it is an absolute path - */ - if (type == FT_LNKSAVED || type == FT_LNK) { - int add_link; - /* Always add prefix to hard links (FT_LNKSAVED) and - * on user request to soft links - */ - if (lp[0] == '/' && - (type == FT_LNKSAVED || jcr->prefix_links)) { - strcpy(lname, jcr->where); - add_link = 1; - } else { - lname[0] = 0; - add_link = 0; - } - if (win32_client && lp[1] == ':') { - fn = lp+2; /* skip over drive: */ - } else { - fn = lp; /* take whole name */ - } - /* Ensure where is terminated with a slash */ - if (add_link && jcr->where[wherelen-1] != '/' && fn[0] != '/') { - strcat(lname, "/"); - } - strcat(lname, fn); /* copy rest of link */ - } - } + build_attr_output_fnames(jcr, attr); - P(jcr->mutex); - pm_strcpy(&jcr->last_fname, fname); - V(jcr->mutex); jcr->num_files_examined++; - Dmsg1(30, "Outfile=%s\n", ofile); + Dmsg1(30, "Outfile=%s\n", attr->ofname); extract = FALSE; - stat = create_file(jcr, fname, ofile, lname, type, - stream, &statp, attribsEx, &bfd, - jcr->replace); + stat = create_file(jcr, attr, &bfd, jcr->replace); switch (stat) { case CF_ERROR: case CF_SKIP: @@ -281,32 +161,43 @@ void do_restore(JCR *jcr) case CF_EXTRACT: extract = TRUE; P(jcr->mutex); - pm_strcpy(&jcr->last_fname, ofile); + pm_strcpy(&jcr->last_fname, attr->ofname); V(jcr->mutex); jcr->JobFiles++; fileAddr = 0; - print_ls_output(jcr, ofile, lname, type, &statp); + print_ls_output(jcr, attr); /* Set attributes after file extracted */ break; case CF_CREATED: + P(jcr->mutex); + pm_strcpy(&jcr->last_fname, attr->ofname); + V(jcr->mutex); jcr->JobFiles++; fileAddr = 0; - print_ls_output(jcr, ofile, lname, type, &statp); + print_ls_output(jcr, attr); /* set attributes now because file will not be extracted */ - set_attributes(jcr, fname, ofile, lname, type, stream, - &statp, attribsEx, &bfd); + set_attributes(jcr, attr, &bfd); break; } + break; - - /* Data stream */ - } else if (stream == STREAM_FILE_DATA || stream == STREAM_SPARSE_DATA || - stream == STREAM_WIN32_DATA) { - if (stream == STREAM_WIN32_DATA && !is_win32_backup()) { - Jmsg(jcr, M_ERROR, 0, _("Win32 backup data not supported on this Client.\n")); + /* Windows Backup data stream */ + case STREAM_WIN32_DATA: + if (!is_win32_backup()) { + if (!non_support_data) { + Jmsg(jcr, M_ERROR, 0, _("Win32 backup data not supported on this Client.\n")); + } extract = FALSE; + non_support_data++; continue; } + goto extract_data; + + /* Data stream */ + case STREAM_FILE_DATA: + case STREAM_SPARSE_DATA: + +extract_data: if (extract) { if (stream == STREAM_SPARSE_DATA) { ser_declare; @@ -321,7 +212,7 @@ void do_restore(JCR *jcr) fileAddr = faddr; if (blseek(&bfd, (off_t)fileAddr, SEEK_SET) < 0) { Jmsg3(jcr, M_ERROR, 0, _("Seek to %s error on %s: ERR=%s\n"), - edit_uint64(fileAddr, ec1), ofile, berror(&bfd)); + edit_uint64(fileAddr, ec1), attr->ofname, berror(&bfd)); extract = FALSE; continue; } @@ -333,7 +224,7 @@ void do_restore(JCR *jcr) Dmsg2(30, "Write %u bytes, total before write=%u\n", wsize, total); if ((uint32_t)bwrite(&bfd, wbuf, wsize) != wsize) { Dmsg0(0, "===Write error===\n"); - Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: ERR=%s\n"), ofile, berror(&bfd)); + Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: ERR=%s\n"), attr->ofname, berror(&bfd)); extract = FALSE; continue; } @@ -342,15 +233,23 @@ void do_restore(JCR *jcr) jcr->ReadBytes += wsize; fileAddr += wsize; } - - /* GZIP data stream */ - } else if (stream == STREAM_GZIP_DATA || stream == STREAM_SPARSE_GZIP_DATA || - stream == STREAM_WIN32_GZIP_DATA) { - if (stream == STREAM_WIN32_GZIP_DATA && !is_win32_backup()) { - Jmsg(jcr, M_ERROR, 0, _("Win32 GZIP backup data not supported on this Client.\n")); + break; + + /* Windows Backup GZIP data stream */ + case STREAM_WIN32_GZIP_DATA: + if (!is_win32_backup()) { + if (!non_support_attr) { + Jmsg(jcr, M_ERROR, 0, _("Win32 GZIP backup data not supported on this Client.\n")); + } extract = FALSE; + non_support_attr++; continue; } + /* Fall through desired */ + + /* GZIP data stream */ + case STREAM_GZIP_DATA: + case STREAM_SPARSE_GZIP_DATA: #ifdef HAVE_LIBZ if (extract) { ser_declare; @@ -368,7 +267,7 @@ void do_restore(JCR *jcr) fileAddr = faddr; if (blseek(&bfd, (off_t)fileAddr, SEEK_SET) < 0) { Jmsg3(jcr, M_ERROR, 0, _("Seek to %s error on %s: ERR=%s\n"), - edit_uint64(fileAddr, ec1), ofile, berror(&bfd)); + edit_uint64(fileAddr, ec1), attr->ofname, berror(&bfd)); extract = FALSE; continue; } @@ -389,7 +288,7 @@ void do_restore(JCR *jcr) Dmsg2(100, "Write uncompressed %d bytes, total before write=%d\n", compress_len, total); if ((uLong)bwrite(&bfd, jcr->compress_buf, compress_len) != compress_len) { Dmsg0(0, "===Write error===\n"); - Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: %s\n"), ofile, berror(&bfd)); + Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: %s\n"), attr->ofname, berror(&bfd)); extract = FALSE; continue; } @@ -405,26 +304,42 @@ void do_restore(JCR *jcr) continue; } #endif - /* If extracting, wierd stream (not 1 or 2), close output file anyway */ - } else if (extract) { - Dmsg1(30, "Found wierd stream %d\n", stream); - if (!is_bopen(&bfd)) { - Jmsg0(jcr, M_ERROR, 0, _("Logic error output file should be open but is not.\n")); + break; + + case STREAM_MD5_SIGNATURE: + case STREAM_SHA1_SIGNATURE: + break; + + case STREAM_PROGRAM_NAMES: + case STREAM_PROGRAM_DATA: + if (!prog_name_msg) { + Pmsg0(000, "Got Program Name or Data Stream. Ignored.\n"); + prog_name_msg++; } - set_attributes(jcr, fname, ofile, lname, type, stream, - &statp, attribsEx, &bfd); - extract = FALSE; - } else if (!(stream == STREAM_MD5_SIGNATURE || stream == STREAM_SHA1_SIGNATURE)) { + break; + + default: + /* If extracting, wierd stream (not 1 or 2), close output file anyway */ + if (extract) { + Dmsg1(30, "Found wierd stream %d\n", stream); + if (!is_bopen(&bfd)) { + Jmsg0(jcr, M_ERROR, 0, _("Logic error output file should be open but is not.\n")); + } + set_attributes(jcr, attr, &bfd); + extract = FALSE; + } + Jmsg(jcr, M_ERROR, 0, _("Unknown stream=%d ignored. This shouldn't happen!\n"), stream); Dmsg2(0, "None of above!!! stream=%d data=%s\n", stream,sd->msg); - } - } + break; + } /* end switch(stream) */ + + } /* end while get_msg() */ /* If output file is still open, it was the last one in the * archive since we just hit an end of file, so close the file. */ if (is_bopen(&bfd)) { - set_attributes(jcr, fname, ofile, lname, type, stream, - &statp, attribsEx, &bfd); + set_attributes(jcr, attr, &bfd); } set_jcr_job_status(jcr, JS_Terminated); goto ok_out; @@ -436,52 +351,11 @@ ok_out: free(jcr->compress_buf); jcr->compress_buf = NULL; } - free_pool_memory(fname); - free_pool_memory(ofile); - free_pool_memory(lname); - free_pool_memory(attribsEx); + free_attr(attr); Dmsg2(10, "End Do Restore. Files=%d Bytes=%" lld "\n", jcr->JobFiles, jcr->JobBytes); -} - -extern char *getuser(uid_t uid); -extern char *getgroup(gid_t gid); - -/* - * Print an ls style message, also send INFO - */ -static void print_ls_output(JCR *jcr, char *fname, char *lname, int type, struct stat *statp) -{ - char buf[5000]; - char ec1[30]; - char *p, *f; - int n; - - p = encode_mode(statp->st_mode, buf); - n = sprintf(p, " %2d ", (uint32_t)statp->st_nlink); - p += n; - n = sprintf(p, "%-8.8s %-8.8s", getuser(statp->st_uid), getgroup(statp->st_gid)); - p += n; - n = sprintf(p, "%8.8s ", edit_uint64(statp->st_size, ec1)); - p += n; - p = encode_time(statp->st_ctime, p); - *p++ = ' '; - *p++ = ' '; - for (f=fname; *f && (p-buf) < (int)sizeof(buf)-10; ) { - *p++ = *f++; + if (non_support_data > 1 || non_support_attr > 1) { + Jmsg(jcr, M_ERROR, 0, _("%d non-supported data streams and %d non-supported attrib streams ignored.\n"), + non_support_data, non_support_attr); } - if (type == FT_LNK) { - *p++ = ' '; - *p++ = '-'; - *p++ = '>'; - *p++ = ' '; - /* Copy link name */ - for (f=lname; *f && (p-buf) < (int)sizeof(buf)-10; ) { - *p++ = *f++; - } - } - *p++ = '\n'; - *p = 0; - Dmsg1(20, "%s", buf); - Jmsg(jcr, M_RESTORED, 0, "%s", buf); -} +} diff --git a/bacula/src/filed/verify.c b/bacula/src/filed/verify.c index 65b1607f8c..2919ad3fb2 100644 --- a/bacula/src/filed/verify.c +++ b/bacula/src/filed/verify.c @@ -43,7 +43,7 @@ void do_verify(JCR *jcr) if ((jcr->big_buf = (char *) malloc(jcr->buf_size)) == NULL) { Jmsg1(jcr, M_ABORT, 0, _("Cannot malloc %d network read buffer\n"), MAX_NETWORK_BUFFER_SIZE); } - set_find_options((FF_PKT *)jcr->ff, jcr->incremental, jcr->mtime); + set_find_options((FF_PKT *)jcr->ff, jcr->incremental, jcr->mtime, jcr->mtime_only); Dmsg0(10, "Start find files\n"); /* Subroutine verify_file() is called for each file */ find_files(jcr, (FF_PKT *)jcr->ff, verify_file, (void *)jcr); diff --git a/bacula/src/filed/verify_vol.c b/bacula/src/filed/verify_vol.c index 839874e633..0fc907a9bc 100644 --- a/bacula/src/filed/verify_vol.c +++ b/bacula/src/filed/verify_vol.c @@ -34,9 +34,6 @@ static char rec_header[] = "rechdr %ld %ld %ld %ld %ld"; /* Forward referenced functions */ -#ifdef needed -static void print_ls_output(JCR *jcr, char *fname, char *lname, int type, struct stat *statp); -#endif /* @@ -102,7 +99,7 @@ void do_verify_volume(JCR *jcr) /* File Attributes stream */ switch (stream) { case STREAM_UNIX_ATTRIBUTES: - case STREAM_WIN32_ATTRIBUTES: + case STREAM_UNIX_ATTRIBUTES_EX: char *ap, *lp, *fp; Dmsg0(400, "Stream=Unix Attributes.\n"); @@ -246,45 +243,3 @@ ok_out: Dmsg2(050, "End Verify-Vol. Files=%d Bytes=%" lld "\n", jcr->JobFiles, jcr->JobBytes); } - -extern char *getuser(uid_t uid); -extern char *getgroup(gid_t gid); - -/* - * Print an ls style message, also send INFO - */ -#ifdef needed -static void print_ls_output(JCR *jcr, char *fname, char *lname, int type, struct stat *statp) -{ - char buf[2000]; - char ec1[30]; - char *p, *f; - int n; - - p = encode_mode(statp->st_mode, buf); - n = sprintf(p, " %2d ", (uint32_t)statp->st_nlink); - p += n; - n = sprintf(p, "%-8.8s %-8.8s", getuser(statp->st_uid), getgroup(statp->st_gid)); - p += n; - n = sprintf(p, "%8.8s ", edit_uint64(statp->st_size, ec1)); - p += n; - p = encode_time(statp->st_ctime, p); - *p++ = ' '; - *p++ = ' '; - for (f=fname; *f && (p-buf) < (int)sizeof(buf)-10; ) - *p++ = *f++; - if (type == FT_LNK) { - *p++ = ' '; - *p++ = '-'; - *p++ = '>'; - *p++ = ' '; - /* Copy link name */ - for (f=lname; *f && (p-buf) < (int)sizeof(buf)-10; ) - *p++ = *f++; - } - *p++ = '\n'; - *p = 0; - Dmsg0(20, buf); - Jmsg(jcr, M_INFO, 0, "%s", buf); -} -#endif diff --git a/bacula/src/findlib/attribs.c b/bacula/src/findlib/attribs.c index 07f9092e47..9ee69f574a 100755 --- a/bacula/src/findlib/attribs.c +++ b/bacula/src/findlib/attribs.c @@ -35,9 +35,7 @@ /* Forward referenced subroutines */ static -int set_win32_attributes(JCR *jcr, char *fname, char *ofile, char *lname, - int type, int stream, struct stat *statp, - char *attribsEx, BFILE *ofd); +int set_win32_attributes(JCR *jcr, ATTR *attr, BFILE *ofd); void unix_name_to_win32(POOLMEM **win32_name, char *name); void win_error(JCR *jcr, char *prefix, POOLMEM *ofile); HANDLE bget_handle(BFILE *bfd); @@ -55,7 +53,17 @@ HANDLE bget_handle(BFILE *bfd); /*=============================================================*/ -/* Encode a stat structure into a base64 character string */ +/* + * Encode a stat structure into a base64 character string + * All systems must create such a structure. + * In addition, we tack on the LinkFI, which is non-zero in + * the case of a hard linked file that has no data. This + * is a File Index pointing to the link that does have the + * data (always the first one encountered in a save). + * You may piggyback attributes on this packet by encoding + * them in the encode_attribsEx() subroutine, but this is + * not recommended. + */ void encode_stat(char *buf, struct stat *statp, uint32_t LinkFI) { char *p = buf; @@ -180,17 +188,15 @@ decode_stat(char *buf, struct stat *statp, uint32_t *LinkFI) * Returns: 1 on success * 0 on failure */ -int set_attributes(JCR *jcr, char *fname, char *ofile, char *lname, - int type, int stream, struct stat *statp, - char *attribsEx, BFILE *ofd) +int set_attributes(JCR *jcr, ATTR *attr, BFILE *ofd) { struct utimbuf ut; mode_t old_mask; int stat = 1; #ifdef HAVE_CYGWIN - if (set_win32_attributes(jcr, fname, ofile, lname, type, stream, - statp, attribsEx, ofd)) { + if (stream == STREAM_UNIX_ATTRIBUTES_EX && + set_win32_attributes(jcr, attr, ofd)) { return 1; } /* @@ -205,47 +211,47 @@ int set_attributes(JCR *jcr, char *fname, char *ofile, char *lname, bclose(ofd); /* first close file */ } - ut.actime = statp->st_atime; - ut.modtime = statp->st_mtime; + ut.actime = attr->statp.st_atime; + ut.modtime = attr->statp.st_mtime; /* ***FIXME**** optimize -- don't do if already correct */ /* * For link, change owner of link using lchown, but don't * try to do a chmod as that will update the file behind it. */ - if (type == FT_LNK) { + if (attr->type == FT_LNK) { /* Change owner of link, not of real file */ - if (lchown(ofile, statp->st_uid, statp->st_gid) < 0) { + if (lchown(attr->ofname, attr->statp.st_uid, attr->statp.st_gid) < 0) { Jmsg2(jcr, M_WARNING, 0, _("Unable to set file owner %s: ERR=%s\n"), - ofile, strerror(errno)); + attr->ofname, strerror(errno)); stat = 0; } } else { - if (chown(ofile, statp->st_uid, statp->st_gid) < 0) { + if (chown(attr->ofname, attr->statp.st_uid, attr->statp.st_gid) < 0) { Jmsg2(jcr, M_WARNING, 0, _("Unable to set file owner %s: ERR=%s\n"), - ofile, strerror(errno)); + attr->ofname, strerror(errno)); stat = 0; } - if (chmod(ofile, statp->st_mode) < 0) { + if (chmod(attr->ofname, attr->statp.st_mode) < 0) { Jmsg2(jcr, M_WARNING, 0, _("Unable to set file modes %s: ERR=%s\n"), - ofile, strerror(errno)); + attr->ofname, strerror(errno)); stat = 0; } /* FreeBSD user flags */ #ifdef HAVE_CHFLAGS - if (chflags(ofile, statp->st_flags) < 0) { + if (chflags(attr->ofname, attr->statp.st_flags) < 0) { Jmsg2(jcr, M_WARNING, 0, _("Unable to set file flags %s: ERR=%s\n"), - ofile, strerror(errno)); + attr->ofname, strerror(errno)); stat = 0; } #endif /* * Reset file times. */ - if (utime(ofile, &ut) < 0) { + if (utime(attr->ofname, &ut) < 0) { Jmsg2(jcr, M_ERROR, 0, _("Unable to set file times %s: ERR=%s\n"), - ofile, strerror(errno)); + attr->ofname, strerror(errno)); stat = 0; } } @@ -263,8 +269,13 @@ int set_attributes(JCR *jcr, char *fname, char *ofile, char *lname, #ifndef HAVE_CYGWIN /* - * If you have a Unix system with extended attributes (e.g. - * ACLs for Solaris, do it here. + * It is possible to piggyback additional data e.g. ACLs on + * the encode_stat() data by returning the extended attributes + * here. They must be "self-contained" (i.e. you keep track + * of your own length), and they must be in ASCII string + * format. Using this feature is not recommended. + * The code below shows how to return nothing. See the Win32 + * code below for returning something in the attributes. */ int encode_attribsEx(JCR *jcr, char *attribsEx, FF_PKT *ff_pkt) { @@ -300,7 +311,7 @@ int encode_attribsEx(JCR *jcr, char *attribsEx, FF_PKT *ff_pkt) if (!p_GetFileAttributesEx(ff_pkt->sys_fname, GetFileExInfoStandard, (LPVOID)&atts)) { win_error(jcr, "GetFileAttributesEx:", ff_pkt->sys_fname); - return STREAM_WIN32_ATTRIBUTES; + return STREAM_UNIX_ATTRIBUTES_EX; } p += to_base64((uint64_t)atts.dwFileAttributes, p); @@ -321,7 +332,7 @@ int encode_attribsEx(JCR *jcr, char *attribsEx, FF_PKT *ff_pkt) *p++ = ' '; p += to_base64((uint64_t)atts.nFileSizeLow, p); *p = 0; - return STREAM_WIN32_ATTRIBUTES; + return STREAM_UNIX_ATTRIBUTES_EX; } /* Define attributes that are legal to set with SetFileAttributes() */ @@ -346,24 +357,22 @@ int encode_attribsEx(JCR *jcr, char *attribsEx, FF_PKT *ff_pkt) * 0 on failure */ static -int set_win32_attributes(JCR *jcr, char *fname, char *ofile, char *lname, - int type, int stream, struct stat *statp, - char *attribsEx, BFILE *ofd) +int set_win32_attributes(JCR *jcr, ATTR *attr, BFILE *ofd) { - char *p = attribsEx; + char *p = attr->attrEx; int64_t val; WIN32_FILE_ATTRIBUTE_DATA atts; ULARGE_INTEGER li; POOLMEM *win32_ofile; if (!p || !*p) { /* we should have attributes */ - Dmsg2(100, "Attributes missing. of=%s ofd=%d\n", ofile, ofd->fid); + Dmsg2(100, "Attributes missing. of=%s ofd=%d\n", attr->ofname, ofd->fid); if (is_bopen(ofd)) { bclose(ofd); } return 0; } else { - Dmsg2(100, "Attribs %s = %s\n", ofile, attribsEx); + Dmsg2(100, "Attribs %s = %s\n", attr->ofname, attr->attrEx); } p += from_base64(&val, p); @@ -392,7 +401,7 @@ int set_win32_attributes(JCR *jcr, char *fname, char *ofile, char *lname, /* Convert to Windows path format */ win32_ofile = get_pool_memory(PM_FNAME); - unix_name_to_win32(&win32_ofile, ofile); + unix_name_to_win32(&win32_ofile, attr->ofname); @@ -400,12 +409,12 @@ int set_win32_attributes(JCR *jcr, char *fname, char *ofile, char *lname, if (!is_bopen(ofd)) { - Dmsg1(100, "File not open: %s\n", ofile); - bopen(ofd, ofile, O_WRONLY|O_BINARY, 0); /* attempt to open the file */ + Dmsg1(100, "File not open: %s\n", attr->ofname); + bopen(ofd, attr->ofname, O_WRONLY|O_BINARY, 0); /* attempt to open the file */ } if (is_bopen(ofd)) { - Dmsg1(100, "SetFileTime %s\n", ofile); + Dmsg1(100, "SetFileTime %s\n", attr->ofname); if (!SetFileTime(bget_handle(ofd), &atts.ftCreationTime, &atts.ftLastAccessTime, @@ -415,7 +424,7 @@ int set_win32_attributes(JCR *jcr, char *fname, char *ofile, char *lname, bclose(ofd); } - Dmsg1(100, "SetFileAtts %s\n", ofile); + Dmsg1(100, "SetFileAtts %s\n", attr->ofname); if (!(atts.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { if (!SetFileAttributes(win32_ofile, atts.dwFileAttributes & SET_ATTRS)) { win_error(jcr, "SetFileAttributes:", win32_ofile); diff --git a/bacula/src/findlib/bfile.c b/bacula/src/findlib/bfile.c index adbd0ac208..a42eb03006 100644 --- a/bacula/src/findlib/bfile.c +++ b/bacula/src/findlib/bfile.c @@ -63,11 +63,44 @@ int set_win32_backup(BFILE *bfd, int enable) return bfd->use_backup_api; } +/* + * Return 1 if we can do Win32 backup + * return 0 if not + */ int is_win32_backup(void) { return p_BackupRead && p_BackupWrite; } +int is_stream_supported(int stream) +{ + if (is_win32_backup()) { + return 1; + } + /* No Win32 backup on this machine */ + switch (stream) { + case STREAM_WIN32_ATTRIBUTES: + case STREAM_WIN32_DATA: + case STREAM_WIN32_GZIP_DATA: + return 0; + + /* Known streams */ + case STREAM_UNIX_ATTRIBUTES: + case STREAM_FILE_DATA: + case STREAM_MD5_SIGNATURE: + case STREAM_GZIP_DATA: + case STREAM_UNIX_ATTRIBUTES_EX: + case STREAM_SPARSE_DATA: + case STREAM_SPARSE_GZIP_DATA: + case STREAM_PROGRAM_NAMES: + case STREAM_PROGRAM_DATA: + case STREAM_SHA1_SIGNATURE: + return 1; + + } + return 0; +} + HANDLE bget_handle(BFILE *bfd) { return bfd->fh; @@ -308,6 +341,31 @@ int is_win32_backup(void) return 0; } +int is_stream_supported(int stream) +{ + /* No Win32 backup on this machine */ + switch (stream) { + case STREAM_WIN32_ATTRIBUTES: + case STREAM_WIN32_DATA: + case STREAM_WIN32_GZIP_DATA: + return 0; + + /* Known streams */ + case STREAM_UNIX_ATTRIBUTES: + case STREAM_FILE_DATA: + case STREAM_MD5_SIGNATURE: + case STREAM_GZIP_DATA: + case STREAM_UNIX_ATTRIBUTES_EX: + case STREAM_SPARSE_DATA: + case STREAM_SPARSE_GZIP_DATA: + case STREAM_PROGRAM_NAMES: + case STREAM_PROGRAM_DATA: + case STREAM_SHA1_SIGNATURE: + return 1; + + } + return 0; +} int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode) { diff --git a/bacula/src/findlib/bfile.h b/bacula/src/findlib/bfile.h index a666072e3e..5250847eb9 100644 --- a/bacula/src/findlib/bfile.h +++ b/bacula/src/findlib/bfile.h @@ -34,47 +34,48 @@ #include "winapi.h" #define BF_CLOSED 0 -#define BF_READ 1 /* BackupRead */ -#define BF_WRITE 2 /* BackupWrite */ +#define BF_READ 1 /* BackupRead */ +#define BF_WRITE 2 /* BackupWrite */ /* In bfile.c */ /* Basic low level I/O file packet */ typedef struct s_bfile { #ifdef xxx - int use_win_api; /* set if using WinAPI */ + int use_win_api; /* set if using WinAPI */ #endif - int use_backup_api; /* set if using BackupRead/Write */ - int mode; /* set if file is open */ - HANDLE fh; /* Win32 file handle */ - int fid; /* fd if doing Unix style */ - LPVOID lpContext; /* BackupRead/Write context */ - POOLMEM *errmsg; /* error message buffer */ - DWORD rw_bytes; /* Bytes read or written */ - DWORD lerror; /* Last error code */ + int use_backup_api; /* set if using BackupRead/Write */ + int mode; /* set if file is open */ + HANDLE fh; /* Win32 file handle */ + int fid; /* fd if doing Unix style */ + LPVOID lpContext; /* BackupRead/Write context */ + POOLMEM *errmsg; /* error message buffer */ + DWORD rw_bytes; /* Bytes read or written */ + DWORD lerror; /* Last error code */ } BFILE; HANDLE bget_handle(BFILE *bfd); -#else /* Linux/Unix systems */ +#else /* Linux/Unix systems */ /* Basic low level I/O file packet */ typedef struct s_bfile { - int fid; /* file id on Unix */ + int fid; /* file id on Unix */ int berrno; } BFILE; #endif -void binit(BFILE *bfd); -int is_bopen(BFILE *bfd); -int set_win32_backup(BFILE *bfd, int enable); -int is_win32_backup(); -char *berror(BFILE *bfd); -int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode); -int bclose(BFILE *bfd); +void binit(BFILE *bfd); +int is_bopen(BFILE *bfd); +int set_win32_backup(BFILE *bfd, int enable); +int is_win32_backup(); +int is_stream_supported(int stream); +char *berror(BFILE *bfd); +int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode); +int bclose(BFILE *bfd); ssize_t bread(BFILE *bfd, void *buf, size_t count); ssize_t bwrite(BFILE *bfd, void *buf, size_t count); -off_t blseek(BFILE *bfd, off_t offset, int whence); +off_t blseek(BFILE *bfd, off_t offset, int whence); #endif /* __BFILE_H */ diff --git a/bacula/src/findlib/create_file.c b/bacula/src/findlib/create_file.c index 37e7c3e84b..279f209ad9 100644 --- a/bacula/src/findlib/create_file.c +++ b/bacula/src/findlib/create_file.c @@ -61,9 +61,7 @@ static int path_already_seen(char *path, int pnl); * files. * */ -int create_file(JCR *jcr, char *fname, char *ofile, char *lname, - int type, int stream, struct stat *statp, - char *attribsEx, BFILE *ofd, int replace) +int create_file(JCR *jcr, ATTR *attr, BFILE *ofd, int replace) { int new_mode, parent_mode, mode; uid_t uid; @@ -71,37 +69,37 @@ int create_file(JCR *jcr, char *fname, char *ofile, char *lname, int pnl; binit(ofd); - new_mode = statp->st_mode; - Dmsg2(300, "newmode=%x file=%s\n", new_mode, ofile); + new_mode = attr->statp.st_mode; + Dmsg2(300, "newmode=%x file=%s\n", new_mode, attr->ofname); parent_mode = S_IWUSR | S_IXUSR | new_mode; - gid = statp->st_gid; - uid = statp->st_uid; + gid = attr->statp.st_gid; + uid = attr->statp.st_uid; Dmsg2(400, "Replace=%c %d\n", (char)replace, replace); /* If not always replacing, do a stat and decide */ if (replace != REPLACE_ALWAYS) { struct stat mstatp; - if (lstat(ofile, &mstatp) == 0) { + if (lstat(attr->ofname, &mstatp) == 0) { switch (replace) { case REPLACE_IFNEWER: - if (statp->st_mtime <= mstatp.st_mtime) { - Jmsg(jcr, M_SKIPPED, 0, _("File skipped. Not newer: %s\n"), ofile); + if (attr->statp.st_mtime <= mstatp.st_mtime) { + Jmsg(jcr, M_SKIPPED, 0, _("File skipped. Not newer: %s\n"), attr->ofname); return CF_SKIP; } break; case REPLACE_IFOLDER: - if (statp->st_mtime >= mstatp.st_mtime) { - Jmsg(jcr, M_SKIPPED, 0, _("File skipped. Not older: %s\n"), ofile); + if (attr->statp.st_mtime >= mstatp.st_mtime) { + Jmsg(jcr, M_SKIPPED, 0, _("File skipped. Not older: %s\n"), attr->ofname); return CF_SKIP; } break; case REPLACE_NEVER: - Jmsg(jcr, M_SKIPPED, 0, _("File skipped. Already exists: %s\n"), ofile); + Jmsg(jcr, M_SKIPPED, 0, _("File skipped. Already exists: %s\n"), attr->ofname); return CF_SKIP; } } } - switch (type) { + switch (attr->type) { case FT_LNKSAVED: /* Hard linked, file already saved */ case FT_LNK: case FT_RAW: @@ -115,7 +113,7 @@ int create_file(JCR *jcr, char *fname, char *ofile, char *lname, * not already exist. Below, we will split to * do the file type specific work */ - pnl = separate_path_and_file(jcr, fname, ofile); + pnl = separate_path_and_file(jcr, attr->fname, attr->ofname); if (pnl < 0) { return CF_ERROR; } @@ -126,37 +124,37 @@ int create_file(JCR *jcr, char *fname, char *ofile, char *lname, */ if (pnl > 0) { char savechr; - savechr = ofile[pnl]; - ofile[pnl] = 0; /* terminate path */ + savechr = attr->ofname[pnl]; + attr->ofname[pnl] = 0; /* terminate path */ - if (!path_already_seen(ofile, pnl)) { - Dmsg1(50, "Make path %s\n", ofile); + if (!path_already_seen(attr->ofname, pnl)) { + Dmsg1(50, "Make path %s\n", attr->ofname); /* * If we need to make the directory, ensure that it is with * execute bit set (i.e. parent_mode), and preserve what already * exists. Normally, this should do nothing. */ - if (make_path(jcr, ofile, parent_mode, parent_mode, uid, gid, 1, NULL) != 0) { - Dmsg1(0, "Could not make path. %s\n", ofile); + if (make_path(jcr, attr->ofname, parent_mode, parent_mode, uid, gid, 1, NULL) != 0) { + Dmsg1(0, "Could not make path. %s\n", attr->ofname); return CF_ERROR; } } - ofile[pnl] = savechr; /* restore full name */ + attr->ofname[pnl] = savechr; /* restore full name */ } /* Now we do the specific work for each file type */ - switch(type) { + switch(attr->type) { case FT_REGE: case FT_REG: - Dmsg1(100, "Create file %s\n", ofile); + Dmsg1(100, "Create file %s\n", attr->ofname); mode = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY; /* O_NOFOLLOW; */ - if (IS_CTG(statp->st_mode)) { + if (IS_CTG(attr->statp.st_mode)) { mode |= O_CTG; /* set contiguous bit if needed */ } - Dmsg1(50, "Create file: %s\n", ofile); - if ((bopen(ofd, ofile, mode, S_IRUSR | S_IWUSR)) < 0) { + Dmsg1(50, "Create file: %s\n", attr->ofname); + if ((bopen(ofd, attr->ofname, mode, S_IRUSR | S_IWUSR)) < 0) { Jmsg2(jcr, M_ERROR, 0, _("Could not create %s: ERR=%s\n"), - ofile, berror(ofd)); + attr->ofname, berror(ofd)); return CF_ERROR; } return CF_EXTRACT; @@ -164,57 +162,57 @@ int create_file(JCR *jcr, char *fname, char *ofile, char *lname, case FT_RAW: /* Bacula raw device e.g. /dev/sda1 */ case FT_FIFO: /* Bacula fifo to save data */ case FT_SPEC: - if (S_ISFIFO(statp->st_mode)) { - Dmsg1(200, "Restore fifo: %s\n", ofile); - if (mkfifo(ofile, statp->st_mode) != 0 && errno != EEXIST) { + if (S_ISFIFO(attr->statp.st_mode)) { + Dmsg1(200, "Restore fifo: %s\n", attr->ofname); + if (mkfifo(attr->ofname, attr->statp.st_mode) != 0 && errno != EEXIST) { Jmsg2(jcr, M_ERROR, 0, _("Cannot make fifo %s: ERR=%s\n"), - ofile, strerror(errno)); + attr->ofname, strerror(errno)); return CF_ERROR; } } else { - Dmsg1(200, "Restore node: %s\n", ofile); - if (mknod(ofile, statp->st_mode, statp->st_rdev) != 0 && errno != EEXIST) { + Dmsg1(200, "Restore node: %s\n", attr->ofname); + if (mknod(attr->ofname, attr->statp.st_mode, attr->statp.st_rdev) != 0 && errno != EEXIST) { Jmsg2(jcr, M_ERROR, 0, _("Cannot make node %s: ERR=%s\n"), - ofile, strerror(errno)); + attr->ofname, strerror(errno)); return CF_ERROR; } } - if (type == FT_RAW || type == FT_FIFO) { + if (attr->type == FT_RAW || attr->type == FT_FIFO) { btimer_id tid; - Dmsg1(200, "FT_RAW|FT_FIFO %s\n", ofile); + Dmsg1(200, "FT_RAW|FT_FIFO %s\n", attr->ofname); mode = O_WRONLY | O_BINARY; /* Timeout open() in 60 seconds */ - if (type == FT_FIFO) { + if (attr->type == FT_FIFO) { tid = start_thread_timer(pthread_self(), 60); } else { tid = NULL; } - if ((bopen(ofd, ofile, mode, 0)) < 0) { + if ((bopen(ofd, attr->ofname, mode, 0)) < 0) { Jmsg2(jcr, M_ERROR, 0, _("Could not open %s: ERR=%s\n"), - ofile, berror(ofd)); + attr->ofname, berror(ofd)); stop_thread_timer(tid); return CF_ERROR; } stop_thread_timer(tid); return CF_EXTRACT; } - Dmsg1(200, "FT_SPEC %s\n", ofile); + Dmsg1(200, "FT_SPEC %s\n", attr->ofname); return CF_CREATED; case FT_LNK: - Dmsg2(130, "FT_LNK should restore: %s -> %s\n", ofile, lname); - if (symlink(lname, ofile) != 0 && errno != EEXIST) { + Dmsg2(130, "FT_LNK should restore: %s -> %s\n", attr->ofname, attr->olname); + if (symlink(attr->olname, attr->ofname) != 0 && errno != EEXIST) { Jmsg3(jcr, M_ERROR, 0, _("Could not symlink %s -> %s: ERR=%s\n"), - ofile, lname, strerror(errno)); + attr->ofname, attr->olname, strerror(errno)); return CF_ERROR; } return CF_CREATED; case FT_LNKSAVED: /* Hard linked, file already saved */ - Dmsg2(130, "Hard link %s => %s\n", ofile, lname); - if (link(lname, ofile) != 0) { + Dmsg2(130, "Hard link %s => %s\n", attr->ofname, attr->olname); + if (link(attr->olname, attr->ofname) != 0) { Jmsg3(jcr, M_ERROR, 0, _("Could not hard link %s -> %s: ERR=%s\n"), - ofile, lname, strerror(errno)); + attr->ofname, attr->olname, strerror(errno)); return CF_ERROR; } return CF_CREATED; @@ -222,8 +220,8 @@ int create_file(JCR *jcr, char *fname, char *ofile, char *lname, } /* End inner switch */ case FT_DIR: - Dmsg2(300, "Make dir mode=%o dir=%s\n", new_mode, ofile); - if (make_path(jcr, ofile, new_mode, parent_mode, uid, gid, 0, NULL) != 0) { + Dmsg2(300, "Make dir mode=%o dir=%s\n", new_mode, attr->ofname); + if (make_path(jcr, attr->ofname, new_mode, parent_mode, uid, gid, 0, NULL) != 0) { return CF_ERROR; } /* @@ -232,9 +230,9 @@ int create_file(JCR *jcr, char *fname, char *ofile, char *lname, * and saved. */ if (is_win32_backup()) { - if ((bopen(ofd, ofile, O_WRONLY|O_BINARY, 0)) < 0) { + if ((bopen(ofd, attr->ofname, O_WRONLY|O_BINARY, 0)) < 0) { Jmsg2(jcr, M_ERROR, 0, _("Could not open %s: ERR=%s\n"), - ofile, berror(ofd)); + attr->ofname, berror(ofd)); return CF_ERROR; } return CF_EXTRACT; @@ -252,9 +250,11 @@ int create_file(JCR *jcr, char *fname, char *ofile, char *lname, case FT_NORECURSE: case FT_NOFSCHG: case FT_NOOPEN: - Jmsg2(jcr, M_ERROR, 0, _("Original file %s not saved: type=%d\n"), fname, type); + Jmsg2(jcr, M_ERROR, 0, _("Original file %s not saved: type=%d\n"), attr->fname, attr->type); + break; default: - Jmsg2(jcr, M_ERROR, 0, _("Unknown file type %d; not restored: %s\n"), type, fname); + Jmsg2(jcr, M_ERROR, 0, _("Unknown file type %d; not restored: %s\n"), attr->type, attr->fname); + break; } return CF_ERROR; } diff --git a/bacula/src/findlib/find.c b/bacula/src/findlib/find.c index e26a7fb09d..348d965398 100644 --- a/bacula/src/findlib/find.c +++ b/bacula/src/findlib/find.c @@ -76,11 +76,12 @@ FF_PKT *init_find_files() * of save_time. For additional options, see above */ void -set_find_options(FF_PKT *ff, int incremental, time_t save_time) +set_find_options(FF_PKT *ff, int incremental, time_t save_time, int mtime_only) { Dmsg0(100, "Enter set_find_options()\n"); ff->incremental = incremental; ff->save_time = save_time; + ff->mtime_only = mtime_only; Dmsg0(100, "Leave set_find_options()\n"); } diff --git a/bacula/src/findlib/find.h b/bacula/src/findlib/find.h index e0ed71836b..22c272ccd9 100755 --- a/bacula/src/findlib/find.h +++ b/bacula/src/findlib/find.h @@ -67,27 +67,6 @@ int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result); #define CF_EXTRACT 3 /* file created, data to extract */ #define CF_CREATED 4 /* file created, no data to extract */ -/* - * NOTE!!! These go on the tape, so don't change them. If - * need be, add to them. - */ -#define FT_LNKSAVED 1 /* hard link to file already saved */ -#define FT_REGE 2 /* Regular file but empty */ -#define FT_REG 3 /* Regular file */ -#define FT_LNK 4 /* Soft Link */ -#define FT_DIR 5 /* Directory */ -#define FT_SPEC 6 /* Special file -- chr, blk, fifo, sock */ -#define FT_NOACCESS 7 /* Not able to access */ -#define FT_NOFOLLOW 8 /* Could not follow link */ -#define FT_NOSTAT 9 /* Could not stat file */ -#define FT_NOCHG 10 /* Incremental option, file not changed */ -#define FT_DIRNOCHG 11 /* Incremental option, directory not changed */ -#define FT_ISARCH 12 /* Trying to save archive file */ -#define FT_NORECURSE 13 /* No recursion into directory */ -#define FT_NOFSCHG 14 /* Different file system, prohibited */ -#define FT_NOOPEN 15 /* Could not open directory */ -#define FT_RAW 16 /* Raw block device */ -#define FT_FIFO 17 /* Raw fifo device */ /* Options saved in "flag" of ff packet */ #define FO_MD5 0x001 /* Do MD5 checksum */ diff --git a/bacula/src/findlib/protos.h b/bacula/src/findlib/protos.h index bab7afd7d0..f1f5a188e8 100644 --- a/bacula/src/findlib/protos.h +++ b/bacula/src/findlib/protos.h @@ -24,42 +24,38 @@ */ /* from attribs.c */ -void encode_stat (char *buf, struct stat *statp, uint32_t LinkFI); -void decode_stat (char *buf, struct stat *statp, uint32_t *LinkFI); -int encode_attribsEx (JCR *jcr, char *attribsEx, FF_PKT *ff_pkt); -int set_attributes(JCR *jcr, char *fname, char *ofile, char *lname, - int type, int stream, struct stat *statp, - char *attribsEx, BFILE *ofd); +void encode_stat (char *buf, struct stat *statp, uint32_t LinkFI); +void decode_stat (char *buf, struct stat *statp, uint32_t *LinkFI); +int encode_attribsEx (JCR *jcr, char *attribsEx, FF_PKT *ff_pkt); +int set_attributes (JCR *jcr, ATTR *attr, BFILE *ofd); /* from create_file.c */ -int create_file(JCR *jcr, char *fname, char *ofile, char *lname, - int type, int stream, struct stat *statp, - char *attribsEx, BFILE *ofd, int replace); +int create_file (JCR *jcr, ATTR *attr, BFILE *ofd, int replace); /* From find.c */ FF_PKT *init_find_files(); -void set_find_options(FF_PKT *ff, int incremental, time_t mtime); -int find_files(JCR *jcr, FF_PKT *ff, int sub(FF_PKT *ff_pkt, void *hpkt), void *pkt); -int term_find_files(FF_PKT *ff); +void set_find_options(FF_PKT *ff, int incremental, time_t mtime, int mtime_only); +int find_files(JCR *jcr, FF_PKT *ff, int sub(FF_PKT *ff_pkt, void *hpkt), void *pkt); +int term_find_files(FF_PKT *ff); /* From match.c */ -void init_include_exclude_files(FF_PKT *ff); -void term_include_exclude_files(FF_PKT *ff); -void add_fname_to_include_list(FF_PKT *ff, int prefixed, char *fname); -void add_fname_to_exclude_list(FF_PKT *ff, char *fname); -int file_is_excluded(FF_PKT *ff, char *file); -int file_is_included(FF_PKT *ff, char *file); +void init_include_exclude_files(FF_PKT *ff); +void term_include_exclude_files(FF_PKT *ff); +void add_fname_to_include_list(FF_PKT *ff, int prefixed, char *fname); +void add_fname_to_exclude_list(FF_PKT *ff, char *fname); +int file_is_excluded(FF_PKT *ff, char *file); +int file_is_included(FF_PKT *ff, char *file); struct s_included_file *get_next_included_file(FF_PKT *ff, struct s_included_file *inc); /* From find_one.c */ -int find_one_file(JCR *jcr, FF_PKT *ff, int handle_file(FF_PKT *ff_pkt, void *hpkt), +int find_one_file(JCR *jcr, FF_PKT *ff, int handle_file(FF_PKT *ff_pkt, void *hpkt), void *pkt, char *p, dev_t parent_device, int top_level); -int term_find_one(FF_PKT *ff); +int term_find_one(FF_PKT *ff); /* From get_priv.c */ -int get_backup_privileges(JCR *jcr, int ignore_errors); +int enable_backup_privileges(JCR *jcr, int ignore_errors); /* from makepath.c */ diff --git a/bacula/src/jcr.h b/bacula/src/jcr.h index f54d15b15d..be78fcdae4 100644 --- a/bacula/src/jcr.h +++ b/bacula/src/jcr.h @@ -117,6 +117,8 @@ struct JCR { char *sd_auth_key; /* SD auth key */ MSGS *jcr_msgs; /* Copy of message resource -- actually used */ uint32_t ClientId; /* Client associated with Job */ + char *where; /* prefix to restore files to */ + int prefix_links; /* Prefix links with Where path */ /* Daemon specific part of JCR */ /* This should be empty in the library */ @@ -148,7 +150,6 @@ struct JCR { POOLMEM *stime; /* start time for incremental/differential */ JOB_DBR jr; /* Job record in Database */ uint32_t RestoreJobId; /* Id specified by UA */ - char *RestoreWhere; /* Where to restore the files */ POOLMEM *client_uname; /* client uname */ int replace; /* Replace option */ int acquired_resource_locks; /* set if resource locks acquired */ @@ -170,9 +171,7 @@ struct JCR { char *big_buf; /* I/O buffer */ POOLMEM *compress_buf; /* Compression buffer */ int32_t compress_buf_size; /* Length of compression buffer */ - POOLMEM *where; /* Root where to restore */ int replace; /* Replace options */ - int prefix_links; /* Prefix links with Where path */ int buf_size; /* length of buffer */ void *ff; /* Find Files packet */ char stored_addr[MAX_NAME_LENGTH]; /* storage daemon address */ diff --git a/bacula/src/lib/Makefile.in b/bacula/src/lib/Makefile.in index 03fccf1956..8229502d37 100644 --- a/bacula/src/lib/Makefile.in +++ b/bacula/src/lib/Makefile.in @@ -31,7 +31,7 @@ GMP_INC=@GMP_INC@ first_rule: all dummy: -LIBSRCS = alloc.c base64.c bsys.c bget_msg.c \ +LIBSRCS = alloc.c attr.c base64.c bsys.c bget_msg.c \ bnet.c bnet_server.c \ bpipe.c bshm.c btime.c \ cram-md5.c crc32.c daemon.c edit.c fnmatch.c \ @@ -42,7 +42,7 @@ LIBSRCS = alloc.c base64.c bsys.c bget_msg.c \ util.c watchdog.c workq.c -LIBOBJS = alloc.o base64.o bsys.o bget_msg.o \ +LIBOBJS = alloc.o attr.o base64.o bsys.o bget_msg.o \ bnet.o bnet_server.o \ bpipe.o bshm.o btime.o \ cram-md5.o crc32.o daemon.o edit.o fnmatch.o \ diff --git a/bacula/src/lib/attr.c b/bacula/src/lib/attr.c new file mode 100644 index 0000000000..bd30d9e792 --- /dev/null +++ b/bacula/src/lib/attr.c @@ -0,0 +1,213 @@ +/* + * attr.c Unpack an Attribute record returned from the tape + * + * Kern Sibbald, June MMIII (code pulled from filed/restore.c and updated) + * + * Version $Id$ + */ + +/* + Copyright (C) 2000, 2001, 2002 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 + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + */ + +#include "bacula.h" +#include "jcr.h" + +extern int win32_client; + +ATTR *new_attr() +{ + ATTR *attr = (ATTR *)malloc(sizeof(ATTR)); + memset(attr, 0, sizeof(ATTR)); + attr->ofname = get_pool_memory(PM_FNAME); + attr->olname = get_pool_memory(PM_FNAME); + return attr; +} + +void free_attr(ATTR *attr) +{ + free_pool_memory(attr->olname); + free_pool_memory(attr->ofname); + free(attr); +} + +int unpack_attributes_record(JCR *jcr, int32_t stream, char *rec, ATTR *attr) +{ + char *p; + /* + * An Attributes record consists of: + * File_index + * Type (FT_types) + * Filename + * Attributes + * Link name (if file linked i.e. FT_LNK) + * Extended attributes (Win32) + * plus optional values determined by AR_ flags in upper bits of Type + * Data_stream + * + */ + attr->stream = stream; + Dmsg1(100, "Attr: %s\n", rec); + if (sscanf(rec, "%d %d", &attr->file_index, &attr->type) != 2) { + Jmsg(jcr, M_FATAL, 0, _("Error scanning attributes: %s\n"), rec); + Dmsg1(100, "\nError scanning attributes. %s\n", rec); + return 0; + } + Dmsg2(100, "Got Attr: FilInx=%d type=%d\n", attr->file_index, attr->type); + if (attr->type & AR_DATA_STREAM) { + attr->data_stream = 1; + } else { + attr->data_stream = 0; + } + attr->type &= FT_MASK; /* keep only type bits */ + p = rec; + while (*p++ != ' ') /* skip record file index */ + { } + while (*p++ != ' ') /* skip type */ + { } + + attr->fname = p; /* set filname position */ + while (*p++ != 0) /* skip filename */ + { } + attr->attr = p; /* set attributes position */ + while (*p++ != 0) /* skip attributes */ + { } + attr->lname = p; /* set link position */ + while (*p++ != 0) /* skip link */ + { } + attr->attrEx = p; /* set extended attributes position */ + + if (attr->data_stream) { + int64_t val; + while (*p++ != 0) /* skip extended attributes */ + { } + from_base64(&val, p); + attr->data_stream = (int32_t)val; + } + Dmsg7(200, "unpack_attr FI=%d Type=%d fname=%s attr=%s lname=%s attrEx=%s ds=%d\n", + attr->file_index, attr->type, attr->fname, attr->attr, attr->lname, + attr->attrEx, attr->data_stream); + *attr->ofname = 0; + *attr->olname = 0; + return 1; +} + +/* + * Build attr->ofname from attr->fname and + * attr->olname from attr->olname + */ +void build_attr_output_fnames(JCR *jcr, ATTR *attr) +{ + /* + * Prepend the where directory so that the + * files are put where the user wants. + * + * We do a little jig here to handle Win32 files with + * a drive letter -- we simply strip the drive: from + * every filename if a prefix is supplied. + * + */ + if (jcr->where[0] == 0) { + pm_strcpy(&attr->ofname, attr->fname); + pm_strcpy(&attr->olname, attr->lname); + } else { + char *fn; + int wherelen = strlen(jcr->where); + pm_strcpy(&attr->ofname, jcr->where); /* copy prefix */ + if (win32_client && attr->fname[1] == ':') { + fn = attr->fname+2; /* skip over drive: */ + } else { + fn = attr->fname; /* take whole name */ + } + /* Ensure where is terminated with a slash */ + if (jcr->where[wherelen-1] != '/' && fn[0] != '/') { + pm_strcat(&attr->ofname, "/"); + } + pm_strcat(&attr->ofname, fn); /* copy rest of name */ + /* + * Fixup link name -- if it is an absolute path + */ + if (attr->type == FT_LNKSAVED || attr->type == FT_LNK) { + bool add_link; + /* Always add prefix to hard links (FT_LNKSAVED) and + * on user request to soft links + */ + if (attr->lname[0] == '/' && + (attr->type == FT_LNKSAVED || jcr->prefix_links)) { + pm_strcpy(&attr->olname, jcr->where); + add_link = true; + } else { + attr->olname[0] = 0; + add_link = false; + } + if (win32_client && attr->lname[1] == ':') { + fn = attr->lname+2; /* skip over drive: */ + } else { + fn = attr->lname; /* take whole name */ + } + /* Ensure where is terminated with a slash */ + if (add_link && jcr->where[wherelen-1] != '/' && fn[0] != '/') { + pm_strcat(&attr->olname, "/"); + } + pm_strcat(&attr->olname, fn); /* copy rest of link */ + } + } +} + +extern char *getuser(uid_t uid); +extern char *getgroup(gid_t gid); + +/* + * Print an ls style message, also send M_RESTORED + */ +void print_ls_output(JCR *jcr, ATTR *attr) +{ + char buf[5000]; + char ec1[30]; + char *p, *f; + int n; + + p = encode_mode(attr->statp.st_mode, buf); + n = sprintf(p, " %2d ", (uint32_t)attr->statp.st_nlink); + p += n; + n = sprintf(p, "%-8.8s %-8.8s", getuser(attr->statp.st_uid), getgroup(attr->statp.st_gid)); + p += n; + n = sprintf(p, "%8.8s ", edit_uint64(attr->statp.st_size, ec1)); + p += n; + p = encode_time(attr->statp.st_ctime, p); + *p++ = ' '; + *p++ = ' '; + for (f=attr->ofname; *f && (p-buf) < (int)sizeof(buf)-10; ) { + *p++ = *f++; + } + if (attr->type == FT_LNK) { + *p++ = ' '; + *p++ = '-'; + *p++ = '>'; + *p++ = ' '; + /* Copy link name */ + for (f=attr->olname; *f && (p-buf) < (int)sizeof(buf)-10; ) { + *p++ = *f++; + } + } + *p++ = '\n'; + *p = 0; + Dmsg1(20, "%s", buf); + Jmsg(jcr, M_RESTORED, 0, "%s", buf); +} diff --git a/bacula/src/lib/attr.h b/bacula/src/lib/attr.h new file mode 100644 index 0000000000..7b19eddddc --- /dev/null +++ b/bacula/src/lib/attr.h @@ -0,0 +1,41 @@ +/* + * attr.h Definition of attributes packet for unpacking from tape + * + * Kern Sibbald, June MMIII + * + * Version $Id$ + */ + +/* + Copyright (C) 2000, 2001, 2002 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 + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + */ + +struct ATTR { + int32_t stream; /* attribute stream id */ + int32_t data_stream; /* id of data stream to follow */ + int32_t type; /* file type FT */ + int32_t file_index; /* file index */ + struct stat statp; /* decoded stat packet */ + char *attr; /* attributes position */ + char *attrEx; /* extended attributes if any */ + char *fname; /* filename */ + char *lname; /* link name if any */ + POOLMEM *ofname; /* output filename */ + POOLMEM *olname; /* output link name */ +}; diff --git a/bacula/src/lib/bnet.c b/bacula/src/lib/bnet.c index fdc37d8c0d..b274f93781 100644 --- a/bacula/src/lib/bnet.c +++ b/bacula/src/lib/bnet.c @@ -58,7 +58,10 @@ static int32_t read_nbytes(BSOCK *bsock, char *ptr, int32_t nbytes) do { errno = 0; nread = read(bsock->fd, ptr, nleft); - } while (!bsock->timed_out && nread == -1 && (errno == EINTR || errno == EAGAIN)); + if (bsock->timed_out || bsock->terminated) { + return nread; + } + } while (nread == -1 && (errno == EINTR || errno == EAGAIN)); if (nread <= 0) { return nread; /* error, or EOF */ } @@ -91,7 +94,19 @@ static int32_t write_nbytes(BSOCK *bsock, char *ptr, int32_t nbytes) do { errno = 0; nwritten = write(bsock->fd, ptr, nleft); - } while (!bsock->timed_out && nwritten == -1 && (errno == EINTR || errno == EAGAIN)); + if (bsock->timed_out || bsock->terminated) { + return nwritten; + } + } while (nwritten == -1 && errno == EINTR); + /* + * If connection is non-blocking, we will get eagain, so + * sleep long enough to keep from consuming all the CPU + * and try again. + */ + if (nwritten == -1 && errno == EAGAIN) { + bmicrosleep(0, 50); /* sleep 50 ms */ + continue; + } if (nwritten <= 0) { return nwritten; /* error */ } diff --git a/bacula/src/lib/jcr.c b/bacula/src/lib/jcr.c index fa716293ba..25435d1277 100755 --- a/bacula/src/lib/jcr.c +++ b/bacula/src/lib/jcr.c @@ -156,6 +156,10 @@ static void free_common_jcr(JCR *jcr) free_pool_memory(jcr->errmsg); jcr->errmsg = NULL; } + if (jcr->where) { + free(jcr->where); + jcr->where = NULL; + } free(jcr); } diff --git a/bacula/src/lib/lib.h b/bacula/src/lib/lib.h index 9eeb48fed3..bc2b74fdc7 100644 --- a/bacula/src/lib/lib.h +++ b/bacula/src/lib/lib.h @@ -50,5 +50,6 @@ #include "tree.h" #include "watchdog.h" #include "bpipe.h" +#include "attr.h" #include "protos.h" diff --git a/bacula/src/lib/message.c b/bacula/src/lib/message.c index da1c76c3b7..b68c96b823 100755 --- a/bacula/src/lib/message.c +++ b/bacula/src/lib/message.c @@ -58,7 +58,7 @@ char catalog_db[] = "MySQL"; char catalog_db[] = "SQLite"; #endif #ifdef HAVE_BACULA_DB -char catlog_db[] = "Internal"; +char catalog_db[] = "Internal"; #endif diff --git a/bacula/src/lib/message.h b/bacula/src/lib/message.h index 17315c2062..06b248e1c5 100644 --- a/bacula/src/lib/message.h +++ b/bacula/src/lib/message.h @@ -114,3 +114,4 @@ extern int verbose; extern char my_name[]; extern char *working_directory; extern time_t daemon_start_time; +extern char catalog_db[]; diff --git a/bacula/src/lib/protos.h b/bacula/src/lib/protos.h index d7cffe259c..33e4998131 100644 --- a/bacula/src/lib/protos.h +++ b/bacula/src/lib/protos.h @@ -25,152 +25,159 @@ struct JCR; +/* attr.c */ +ATTR *new_attr(); +void free_attr(ATTR *attr); +int unpack_attributes_record(JCR *jcr, int32_t stream, char *rec, ATTR *attr); +void build_attr_output_fnames(JCR *jcr, ATTR *attr); +void print_ls_output(JCR *jcr, ATTR *attr); + /* base64.c */ -void base64_init (void); -int to_base64 (intmax_t value, char *where); -int from_base64 (intmax_t *value, char *where); -int bin_to_base64 (char *buf, char *bin, int len); +void base64_init (void); +int to_base64 (intmax_t value, char *where); +int from_base64 (intmax_t *value, char *where); +int bin_to_base64 (char *buf, char *bin, int len); /* bsys.c */ -char *bstrncpy (char *dest, const char *src, int maxlen); -char *bstrncat (char *dest, const char *src, int maxlen); -void *b_malloc (char *file, int line, size_t size); +char *bstrncpy (char *dest, const char *src, int maxlen); +char *bstrncat (char *dest, const char *src, int maxlen); +void *b_malloc (char *file, int line, size_t size); #ifndef DEBUG -void *bmalloc (size_t size); +void *bmalloc (size_t size); #endif -void *brealloc (void *buf, size_t size); -void *bcalloc (size_t size1, size_t size2); -int bsnprintf (char *str, size_t size, const char *format, ...); -int bvsnprintf (char *str, size_t size, const char *format, va_list ap); -int pool_sprintf (char *pool_buf, char *fmt, ...); -void create_pid_file (char *dir, char *progname, int port); -int delete_pid_file (char *dir, char *progname, int port); -void drop (char *uid, char *gid); -int bmicrosleep (time_t sec, long msec); +void *brealloc (void *buf, size_t size); +void *bcalloc (size_t size1, size_t size2); +int bsnprintf (char *str, size_t size, const char *format, ...); +int bvsnprintf (char *str, size_t size, const char *format, va_list ap); +int pool_sprintf (char *pool_buf, char *fmt, ...); +void create_pid_file (char *dir, char *progname, int port); +int delete_pid_file (char *dir, char *progname, int port); +void drop (char *uid, char *gid); +int bmicrosleep (time_t sec, long msec); #ifndef HAVE_STRTOLL long long int strtoll(const char *ptr, char **endptr, int base); #endif /* bnet.c */ -int32_t bnet_recv (BSOCK *bsock); -int bnet_send (BSOCK *bsock); -int bnet_fsend (BSOCK *bs, char *fmt, ...); -int bnet_set_buffer_size (BSOCK *bs, uint32_t size, int rw); -int bnet_sig (BSOCK *bs, int sig); -int bnet_ssl_server (BSOCK *bsock, char *password, int ssl_need, int ssl_has); -int bnet_ssl_client (BSOCK *bsock, char *password, int ssl_need); -BSOCK * bnet_connect (JCR *jcr, int retry_interval, - int max_retry_time, char *name, char *host, char *service, - int port, int verbose); -void bnet_close (BSOCK *bsock); -BSOCK * init_bsock (JCR *jcr, int sockfd, char *who, char *ip, int port); -BSOCK * dup_bsock (BSOCK *bsock); -void term_bsock (BSOCK *bsock); -char * bnet_strerror (BSOCK *bsock); -char * bnet_sig_to_ascii (BSOCK *bsock); -int bnet_wait_data (BSOCK *bsock, int sec); -int bnet_wait_data_intr (BSOCK *bsock, int sec); -int bnet_despool (BSOCK *bsock); -int is_bnet_stop (BSOCK *bsock); -int is_bnet_error (BSOCK *bsock); -void bnet_suppress_error_messages(BSOCK *bsock, int flag); +int32_t bnet_recv (BSOCK *bsock); +int bnet_send (BSOCK *bsock); +int bnet_fsend (BSOCK *bs, char *fmt, ...); +int bnet_set_buffer_size (BSOCK *bs, uint32_t size, int rw); +int bnet_sig (BSOCK *bs, int sig); +int bnet_ssl_server (BSOCK *bsock, char *password, int ssl_need, int ssl_has); +int bnet_ssl_client (BSOCK *bsock, char *password, int ssl_need); +BSOCK * bnet_connect (JCR *jcr, int retry_interval, + int max_retry_time, char *name, char *host, char *service, + int port, int verbose); +void bnet_close (BSOCK *bsock); +BSOCK * init_bsock (JCR *jcr, int sockfd, char *who, char *ip, int port); +BSOCK * dup_bsock (BSOCK *bsock); +void term_bsock (BSOCK *bsock); +char * bnet_strerror (BSOCK *bsock); +char * bnet_sig_to_ascii (BSOCK *bsock); +int bnet_wait_data (BSOCK *bsock, int sec); +int bnet_wait_data_intr (BSOCK *bsock, int sec); +int bnet_despool (BSOCK *bsock); +int is_bnet_stop (BSOCK *bsock); +int is_bnet_error (BSOCK *bsock); +void bnet_suppress_error_messages(BSOCK *bsock, int flag); /* bget_msg.c */ -int bget_msg(BSOCK *sock); +int bget_msg(BSOCK *sock); /* bpipe.c */ -BPIPE * open_bpipe(char *prog, int wait, char *mode); -int close_wpipe(BPIPE *bpipe); -int close_bpipe(BPIPE *bpipe); +BPIPE * open_bpipe(char *prog, int wait, char *mode); +int close_wpipe(BPIPE *bpipe); +int close_bpipe(BPIPE *bpipe); /* cram-md5.c */ int cram_md5_get_auth(BSOCK *bs, char *password, int ssl_need); int cram_md5_auth(BSOCK *bs, char *password, int ssl_need); void hmac_md5(uint8_t* text, int text_len, uint8_t* key, - int key_len, uint8_t *hmac); + int key_len, uint8_t *hmac); /* crc32.c */ uint32_t bcrc32(uint8_t *buf, int len); /* daemon.c */ -void daemon_start (); +void daemon_start (); /* edit.c */ -uint64_t str_to_uint64(char *str); -int64_t str_to_int64(char *str); -char * edit_uint64_with_commas (uint64_t val, char *buf); -char * add_commas (char *val, char *buf); -char * edit_uint64 (uint64_t val, char *buf); -int duration_to_utime (char *str, utime_t *value); -int size_to_uint64(char *str, int str_len, uint64_t *rtn_value); -char *edit_utime (utime_t val, char *buf); -int is_a_number (const char *num); -int is_an_integer (const char *n); +uint64_t str_to_uint64(char *str); +int64_t str_to_int64(char *str); +char * edit_uint64_with_commas (uint64_t val, char *buf); +char * add_commas (char *val, char *buf); +char * edit_uint64 (uint64_t val, char *buf); +int duration_to_utime (char *str, utime_t *value); +int size_to_uint64(char *str, int str_len, uint64_t *rtn_value); +char *edit_utime (utime_t val, char *buf); +int is_a_number (const char *num); +int is_an_integer (const char *n); /* lex.c */ -LEX * lex_close_file (LEX *lf); -LEX * lex_open_file (LEX *lf, char *fname, LEX_ERROR_HANDLER *scan_error); -int lex_get_char (LEX *lf); -void lex_unget_char (LEX *lf); -char * lex_tok_to_str (int token); -int lex_get_token (LEX *lf, int expect); +LEX * lex_close_file (LEX *lf); +LEX * lex_open_file (LEX *lf, char *fname, LEX_ERROR_HANDLER *scan_error); +int lex_get_char (LEX *lf); +void lex_unget_char (LEX *lf); +char * lex_tok_to_str (int token); +int lex_get_token (LEX *lf, int expect); /* message.c */ -void my_name_is (int argc, char *argv[], char *name); -void init_msg (JCR *jcr, MSGS *msg); -void term_msg (void); -void close_msg (JCR *jcr); -void add_msg_dest (MSGS *msg, int dest, int type, char *where, char *dest_code); -void rem_msg_dest (MSGS *msg, int dest, int type, char *where); -void Jmsg (JCR *jcr, int type, int level, char *fmt, ...); -void dispatch_message (JCR *jcr, int type, int level, char *buf); -void init_console_msg (char *wd); -void free_msgs_res (MSGS *msgs); -int open_spool_file (JCR *jcr, BSOCK *bs); -int close_spool_file (JCR *jcr, BSOCK *bs); +void my_name_is (int argc, char *argv[], char *name); +void init_msg (JCR *jcr, MSGS *msg); +void term_msg (void); +void close_msg (JCR *jcr); +void add_msg_dest (MSGS *msg, int dest, int type, char *where, char *dest_code); +void rem_msg_dest (MSGS *msg, int dest, int type, char *where); +void Jmsg (JCR *jcr, int type, int level, char *fmt, ...); +void dispatch_message (JCR *jcr, int type, int level, char *buf); +void init_console_msg (char *wd); +void free_msgs_res (MSGS *msgs); +int open_spool_file (JCR *jcr, BSOCK *bs); +int close_spool_file (JCR *jcr, BSOCK *bs); /* bnet_server.c */ -void bnet_thread_server(char *bind_addr, int port, int max_clients, workq_t *client_wq, - void *handle_client_request(void *bsock)); -void bnet_server (int port, void handle_client_request(BSOCK *bsock)); -int net_connect (int port); -BSOCK * bnet_bind (int port); -BSOCK * bnet_accept (BSOCK *bsock, char *who); +void bnet_thread_server(char *bind_addr, int port, int max_clients, workq_t *client_wq, + void *handle_client_request(void *bsock)); +void bnet_server (int port, void handle_client_request(BSOCK *bsock)); +int net_connect (int port); +BSOCK * bnet_bind (int port); +BSOCK * bnet_accept (BSOCK *bsock, char *who); /* signal.c */ -void init_signals (void terminate(int sig)); -void init_stack_dump (void); +void init_signals (void terminate(int sig)); +void init_stack_dump (void); /* scan.c */ -void strip_trailing_junk (char *str); -void strip_trailing_slashes (char *dir); -int skip_spaces (char **msg); -int skip_nonspaces (char **msg); -int fstrsch (char *a, char *b); -int parse_args(POOLMEM *cmd, POOLMEM *args, int *argc, - char **argk, char **argv, int max_args); -char *next_arg(char **s); +void strip_trailing_junk (char *str); +void strip_trailing_slashes (char *dir); +int skip_spaces (char **msg); +int skip_nonspaces (char **msg); +int fstrsch (char *a, char *b); +int parse_args(POOLMEM *cmd, POOLMEM *args, int *argc, + char **argk, char **argv, int max_args); +char *next_arg(char **s); /* util.c */ -int is_buf_zero (char *buf, int len); -void lcase (char *str); -void bash_spaces (char *str); -void unbash_spaces (char *str); -char * encode_time (time_t time, char *buf); -char * encode_mode (mode_t mode, char *buf); -int do_shell_expansion (char *name, int name_len); -void jobstatus_to_ascii (int JobStatus, char *msg, int maxlen); -void pm_strcat (POOLMEM **pm, char *str); -void pm_strcpy (POOLMEM **pm, char *str); -int run_program (char *prog, int wait, POOLMEM *results); -char * job_type_to_str (int type); -char * job_status_to_str (int stat); -char * job_level_to_str (int level); -void make_session_key (char *key, char *seed, int mode); -POOLMEM *edit_job_codes(JCR *jcr, char *omsg, char *imsg, char *to); -void set_working_directory(char *wd); +int is_buf_zero (char *buf, int len); +void lcase (char *str); +void bash_spaces (char *str); +void unbash_spaces (char *str); +char * encode_time (time_t time, char *buf); +char * encode_mode (mode_t mode, char *buf); +int do_shell_expansion (char *name, int name_len); +void jobstatus_to_ascii (int JobStatus, char *msg, int maxlen); +void pm_strcat (POOLMEM **pm, char *str); +void pm_strcpy (POOLMEM **pm, char *str); +int run_program (char *prog, int wait, POOLMEM *results); +char * job_type_to_str (int type); +char * job_status_to_str (int stat); +char * job_level_to_str (int level); +void make_session_key (char *key, char *seed, int mode); +POOLMEM *edit_job_codes(JCR *jcr, char *omsg, char *imsg, char *to); +void set_working_directory(char *wd); /* watchdog.c */ diff --git a/bacula/src/lib/util.c b/bacula/src/lib/util.c index 8331f3899b..fda802a52d 100644 --- a/bacula/src/lib/util.c +++ b/bacula/src/lib/util.c @@ -350,12 +350,6 @@ int do_shell_expansion(char *name, int name_len) if ((shellcmd = getenv("SHELL")) == NULL) { shellcmd = "/bin/sh"; } -#ifdef xxx - close(1); dup(pfd[1]); /* attach pipes to stdout and stderr */ - close(2); dup(pfd[1]); - for (i = 3; i < 32; i++) /* close everything else */ - close(i); -#endif close(pfd[0]); /* close stdin */ dup2(pfd[1], 1); /* attach to stdout */ dup2(pfd[1], 2); /* and stderr */ diff --git a/bacula/src/stored/.cvsignore b/bacula/src/stored/.cvsignore index 7446154068..a3104e4eea 100644 --- a/bacula/src/stored/.cvsignore +++ b/bacula/src/stored/.cvsignore @@ -16,3 +16,5 @@ job2.bsr restore.bsr startit stopit +changer.out +mtx-changer diff --git a/bacula/src/stored/append.c b/bacula/src/stored/append.c index 73a8c1ef7e..020817636b 100644 --- a/bacula/src/stored/append.c +++ b/bacula/src/stored/append.c @@ -115,8 +115,8 @@ int do_append_data(JCR *jcr) /* Read Stream header from the File daemon. * The stream header consists of the following: - * file_index (sequential Bacula file index) - * stream (arbitrary Bacula number to distinguish parts of data) + * file_index (sequential Bacula file index, base 1) + * stream (Bacula number to distinguish parts of data) * info (Info for Storage daemon -- compressed, encryped, ...) * info is not currently used, so is read, but ignored! */ @@ -189,8 +189,8 @@ int do_append_data(JCR *jcr) stream_to_ascii(rec.Stream, rec.FileIndex), rec.data_len); /* Send attributes and MD5 to Director for Catalog */ - if (stream == STREAM_UNIX_ATTRIBUTES || stream == STREAM_MD5_SIGNATURE || - stream == STREAM_WIN32_ATTRIBUTES || stream == STREAM_SHA1_SIGNATURE) { + if (stream == STREAM_UNIX_ATTRIBUTES || stream == STREAM_MD5_SIGNATURE || + stream == STREAM_UNIX_ATTRIBUTES_EX || stream == STREAM_SHA1_SIGNATURE) { if (!jcr->no_attributes) { if (jcr->spool_attributes && jcr->dir_bsock->spool_fd) { jcr->dir_bsock->spool = 1; diff --git a/bacula/src/stored/bextract.c b/bacula/src/stored/bextract.c index 5e507ebe09..ba9f4443bc 100644 --- a/bacula/src/stored/bextract.c +++ b/bacula/src/stored/bextract.c @@ -48,20 +48,14 @@ static FF_PKT my_ff; static FF_PKT *ff = &my_ff; static BSR *bsr = NULL; static int extract = FALSE; -static long record_file_index; +static int non_support_data = 0; +static int non_support_attr = 0; static long total = 0; -static POOLMEM *fname; /* original file name */ -static POOLMEM *ofile; /* output name with prefix */ -static POOLMEM *lname; /* link name */ -static POOLMEM *attribsEx; /* extended attributes (Win32) */ +static ATTR *attr; static char *where; -static int wherelen; /* prefix length */ static uint32_t num_files = 0; -static struct stat statp; static uint32_t compress_buf_size = 70000; static POOLMEM *compress_buf; -static int type; -static int stream; static int prog_name_msg = 0; static int win32_data_msg = 0; static char *VolumeName = NULL; @@ -107,63 +101,63 @@ int main (int argc, char *argv[]) while ((ch = getopt(argc, argv, "b:c:d:e:i:?")) != -1) { switch (ch) { - case 'b': /* bootstrap file */ - bsr = parse_bsr(NULL, optarg); -// dump_bsr(bsr); - break; - - case 'c': /* specify config file */ - if (configfile != NULL) { - free(configfile); - } - configfile = bstrdup(optarg); - break; - - case 'd': /* debug level */ - debug_level = atoi(optarg); - if (debug_level <= 0) - debug_level = 1; - break; - - case 'e': /* exclude list */ - if ((fd = fopen(optarg, "r")) == NULL) { - Pmsg2(0, "Could not open exclude file: %s, ERR=%s\n", - optarg, strerror(errno)); - exit(1); - } - while (fgets(line, sizeof(line), fd) != NULL) { - strip_trailing_junk(line); - Dmsg1(900, "add_exclude %s\n", line); - add_fname_to_exclude_list(ff, line); - } - fclose(fd); - break; - - case 'i': /* include list */ - if ((fd = fopen(optarg, "r")) == NULL) { - Pmsg2(0, "Could not open include file: %s, ERR=%s\n", - optarg, strerror(errno)); - exit(1); - } - while (fgets(line, sizeof(line), fd) != NULL) { - strip_trailing_junk(line); - Dmsg1(900, "add_include %s\n", line); - add_fname_to_include_list(ff, 0, line); - } - fclose(fd); - got_inc = TRUE; - break; + case 'b': /* bootstrap file */ + bsr = parse_bsr(NULL, optarg); +// dump_bsr(bsr); + break; + + case 'c': /* specify config file */ + if (configfile != NULL) { + free(configfile); + } + configfile = bstrdup(optarg); + break; + + case 'd': /* debug level */ + debug_level = atoi(optarg); + if (debug_level <= 0) + debug_level = 1; + break; + + case 'e': /* exclude list */ + if ((fd = fopen(optarg, "r")) == NULL) { + Pmsg2(0, "Could not open exclude file: %s, ERR=%s\n", + optarg, strerror(errno)); + exit(1); + } + while (fgets(line, sizeof(line), fd) != NULL) { + strip_trailing_junk(line); + Dmsg1(900, "add_exclude %s\n", line); + add_fname_to_exclude_list(ff, line); + } + fclose(fd); + break; + + case 'i': /* include list */ + if ((fd = fopen(optarg, "r")) == NULL) { + Pmsg2(0, "Could not open include file: %s, ERR=%s\n", + optarg, strerror(errno)); + exit(1); + } + while (fgets(line, sizeof(line), fd) != NULL) { + strip_trailing_junk(line); + Dmsg1(900, "add_include %s\n", line); + add_fname_to_include_list(ff, 0, line); + } + fclose(fd); + got_inc = TRUE; + break; - case 'V': /* Volume name */ - VolumeName = optarg; - break; + case 'V': /* Volume name */ + VolumeName = optarg; + break; - case '?': - default: - usage(); + case '?': + default: + usage(); - } - } + } /* end switch */ + } /* end while */ argc -= optind; argv += optind; @@ -201,7 +195,7 @@ int main (int argc, char *argv[]) static void do_extract(char *devname) { - + struct stat statp; jcr = setup_jcr("bextract", devname, bsr, VolumeName); dev = setup_to_access_device(jcr, 1); /* acquire for read */ if (!dev) { @@ -217,11 +211,9 @@ static void do_extract(char *devname) Emsg1(M_ERROR_TERM, 0, "%s must be a directory.\n", where); } - wherelen = strlen(where); - fname = get_pool_memory(PM_FNAME); - ofile = get_pool_memory(PM_FNAME); - lname = get_pool_memory(PM_FNAME); - attribsEx = get_pool_memory(PM_FNAME); + free(jcr->where); + jcr->where = bstrdup(where); + attr = new_attr(); compress_buf = get_memory(compress_buf_size); @@ -230,15 +222,11 @@ static void do_extract(char *devname) * archive since we just hit an end of file, so close the file. */ if (is_bopen(&bfd)) { - set_attributes(jcr, fname, ofile, lname, type, stream, &statp, - attribsEx, &bfd); + set_attributes(jcr, attr, &bfd); } release_device(jcr, dev); - free_pool_memory(fname); - free_pool_memory(ofile); - free_pool_memory(lname); - free_pool_memory(compress_buf); + free_attr(attr); term_dev(dev); free_jcr(jcr); printf("%u files restored.\n", num_files); @@ -257,155 +245,77 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) } /* File Attributes stream */ - if (rec->Stream == STREAM_UNIX_ATTRIBUTES || rec->Stream == STREAM_WIN32_ATTRIBUTES) { - char *ap, *lp, *fp, *apex; - stream = rec->Stream; + switch (rec->Stream) { + case STREAM_UNIX_ATTRIBUTES: + case STREAM_UNIX_ATTRIBUTES_EX: /* If extracting, it was from previous stream, so * close the output file. */ if (extract) { if (!is_bopen(&bfd)) { - Emsg0(M_ERROR, 0, "Logic error output file should be open but is not.\n"); + Emsg0(M_ERROR, 0, _("Logic error output file should be open but is not.\n")); } extract = FALSE; - set_attributes(jcr, fname, ofile, lname, type, stream, &statp, - attribsEx, &bfd); + set_attributes(jcr, attr, &bfd); } - if (sizeof_pool_memory(fname) < rec->data_len) { - fname = realloc_pool_memory(fname, rec->data_len + 1); - } - if (sizeof_pool_memory(ofile) < rec->data_len + wherelen + 1) { - ofile = realloc_pool_memory(ofile, rec->data_len + wherelen + 1); + if (!unpack_attributes_record(jcr, rec->Stream, rec->data, attr)) { + Emsg0(M_ERROR_TERM, 0, _("Cannot continue.\n")); } - if (sizeof_pool_memory(lname) < rec->data_len) { - lname = realloc_pool_memory(lname, rec->data_len + wherelen + 1); - } - *fname = 0; - *lname = 0; - - /* - * An Attributes record consists of: - * File_index - * Type (FT_types) - * Filename - * Attributes - * Link name (if file linked i.e. FT_LNK) - * Extended Attributes (Win32) - * - */ - sscanf(rec->data, "%ld %d", &record_file_index, &type); - if (record_file_index != rec->FileIndex) - Emsg2(M_ERROR_TERM, 0, "Record header file index %ld not equal record index %ld\n", - rec->FileIndex, record_file_index); - ap = rec->data; - while (*ap++ != ' ') /* skip record file index */ - ; - while (*ap++ != ' ') /* skip type */ - ; - /* Save filename and position to attributes */ - fp = fname; - while (*ap != 0) { - *fp++ = *ap++; - } - *fp = *ap++; /* terminate filename & point to attribs */ - /* Skip to Link name */ - if (type == FT_LNK || type == FT_LNKSAVED) { - lp = ap; - while (*lp++ != 0) { - ; - } - } else { - lp = ""; + if (attr->file_index != rec->FileIndex) { + Emsg2(M_ERROR_TERM, 0, _("Record header file index %ld not equal record index %ld\n"), + rec->FileIndex, attr->file_index); } - - if (rec->Stream == STREAM_WIN32_ATTRIBUTES) { - apex = ap; /* start at attributes */ - while (*apex++ != 0) { /* skip attributes */ - ; - } - while (*apex++ != 0) { /* skip link name */ - ; - } - pm_strcpy(&attribsEx, apex); /* make a copy of Extended attributes */ - } else { - *attribsEx = 0; /* no extended attributes */ - } - - if (file_is_included(ff, fname) && !file_is_excluded(ff, fname)) { + if (file_is_included(ff, attr->fname) && !file_is_excluded(ff, attr->fname)) { uint32_t LinkFI; - decode_stat(ap, &statp, &LinkFI); - /* - * Prepend the where directory so that the - * files are put where the user wants. - * - * We do a little jig here to handle Win32 files with - * a drive letter -- we simply strip the drive: from - * every filename if a prefix is supplied. - */ - if (where[0] == 0) { - strcpy(ofile, fname); - strcpy(lname, lp); - } else { - char *fn; - strcpy(ofile, where); - if (win32_client && fname[1] == ':') { - fn = fname+2; /* skip over drive: */ - } else { - fn = fname; /* take whole name */ - } - /* Ensure where is terminated with a slash */ - if (where[wherelen-1] != '/' && fn[0] != '/') { - strcat(ofile, "/"); - } - strcat(ofile, fn); /* copy rest of name */ - /* Fixup link name for hard links, but not for - * soft links - */ - if (type == FT_LNKSAVED) { - if (lp[0] == '/') { /* if absolute path */ - strcpy(lname, where); - } - if (win32_client && lp[1] == ':') { - strcat(lname, lp+2); /* copy rest of name */ - } else { - strcat(lname, lp); /* On Unix systems we take everything */ - } - } - } + decode_stat(attr->attr, &attr->statp, &LinkFI); - /* Pmsg1(000, "Restoring: %s\n", ofile); */ + build_attr_output_fnames(jcr, attr); extract = FALSE; - stat = create_file(jcr, fname, ofile, lname, type, stream, - &statp, attribsEx, &bfd, REPLACE_ALWAYS); + stat = create_file(jcr, attr, &bfd, REPLACE_ALWAYS); switch (stat) { case CF_ERROR: case CF_SKIP: break; case CF_EXTRACT: extract = TRUE; - print_ls_output(ofile, lname, type, &statp); + print_ls_output(jcr, attr); num_files++; fileAddr = 0; break; case CF_CREATED: - set_attributes(jcr, fname, ofile, lname, type, stream, &statp, - attribsEx, &bfd); - print_ls_output(ofile, lname, type, &statp); + set_attributes(jcr, attr, &bfd); + print_ls_output(jcr, attr); num_files++; fileAddr = 0; break; } } + /* Windows Backup data stream */ + case STREAM_WIN32_DATA: + if (!is_win32_backup()) { + if (!non_support_data) { + Jmsg(jcr, M_ERROR, 0, _("Win32 backup data not supported on this Client.\n")); + } + extract = FALSE; + non_support_data++; + return; + } + goto extract_data; + + /* Data stream and extracting */ - } else if (rec->Stream == STREAM_FILE_DATA || rec->Stream == STREAM_SPARSE_DATA) { + case STREAM_FILE_DATA: + case STREAM_SPARSE_DATA: + +extract_data: if (extract) { if (rec->Stream == STREAM_SPARSE_DATA) { ser_declare; @@ -417,7 +327,8 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) if (fileAddr != faddr) { fileAddr = faddr; if (blseek(&bfd, (off_t)fileAddr, SEEK_SET) < 0) { - Emsg2(M_ERROR_TERM, 0, _("Seek error on %s: %s\n"), ofile, strerror(errno)); + Emsg2(M_ERROR_TERM, 0, _("Seek error on %s: %s\n"), + attr->ofname, strerror(errno)); } } } else { @@ -427,12 +338,27 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) total += wsize; Dmsg2(8, "Write %u bytes, total=%u\n", wsize, total); if ((uint32_t)bwrite(&bfd, wbuf, wsize) != wsize) { - Emsg2(M_ERROR_TERM, 0, _("Write error on %s: %s\n"), ofile, strerror(errno)); + Emsg2(M_ERROR_TERM, 0, _("Write error on %s: %s\n"), + attr->ofname, strerror(errno)); } fileAddr += wsize; } - } else if (rec->Stream == STREAM_GZIP_DATA || rec->Stream == STREAM_SPARSE_GZIP_DATA) { + /* Windows Backup GZIP data stream */ + case STREAM_WIN32_GZIP_DATA: + if (!is_win32_backup()) { + if (!non_support_attr) { + Jmsg(jcr, M_ERROR, 0, _("Win32 GZIP backup data not supported on this Client.\n")); + } + extract = FALSE; + non_support_attr++; + return; + } + /* Fall through desired */ + + /* GZIP data stream */ + case STREAM_GZIP_DATA: + case STREAM_SPARSE_GZIP_DATA: #ifdef HAVE_LIBZ if (extract) { uLongf compress_len; @@ -448,7 +374,8 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) if (fileAddr != faddr) { fileAddr = faddr; if (blseek(&bfd, (off_t)fileAddr, SEEK_SET) < 0) { - Emsg2(M_ERROR, 0, _("Seek error on %s: %s\n"), ofile, strerror(errno)); + Emsg2(M_ERROR, 0, _("Seek error on %s: %s\n"), + attr->ofname, strerror(errno)); } } } else { @@ -464,7 +391,8 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) Dmsg2(100, "Write uncompressed %d bytes, total before write=%d\n", compress_len, total); if ((uLongf)bwrite(&bfd, compress_buf, (size_t)compress_len) != compress_len) { Pmsg0(0, "===Write error===\n"); - Emsg2(M_ERROR_TERM, 0, _("Write error on %s: %s\n"), ofile, strerror(errno)); + Emsg2(M_ERROR_TERM, 0, _("Write error on %s: %s\n"), + attr->ofname, strerror(errno)); } total += compress_len; fileAddr += compress_len; @@ -474,32 +402,37 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) #else if (extract) { Emsg0(M_ERROR, 0, "GZIP data stream found, but GZIP not configured!\n"); + extract = FALSE; + return; } #endif + case STREAM_MD5_SIGNATURE: + case STREAM_SHA1_SIGNATURE: + break; - /* If extracting, wierd stream (not 1 or 2), close output file anyway */ - } else if (extract) { - if (!is_bopen(&bfd)) { - Emsg0(M_ERROR, 0, "Logic error output file should be open but is not.\n"); - } - extract = FALSE; - set_attributes(jcr, fname, ofile, lname, type, stream, &statp, - attribsEx, &bfd); - } else if (rec->Stream == STREAM_PROGRAM_NAMES || rec->Stream == STREAM_PROGRAM_DATA) { + case STREAM_PROGRAM_NAMES: + case STREAM_PROGRAM_DATA: if (!prog_name_msg) { Pmsg0(000, "Got Program Name or Data Stream. Ignored.\n"); prog_name_msg++; } - } else if (rec->Stream == STREAM_WIN32_DATA || rec->Stream == STREAM_WIN32_GZIP_DATA) { - if (!win32_data_msg) { - Pmsg0(000, "Got Win32 data or Win32 gzip data stream. Ignored.\n"); - win32_data_msg++; + break; + + default: + /* If extracting, wierd stream (not 1 or 2), close output file anyway */ + if (extract) { + if (!is_bopen(&bfd)) { + Emsg0(M_ERROR, 0, "Logic error output file should be open but is not.\n"); + } + extract = FALSE; + set_attributes(jcr, attr, &bfd); } - } else if (!(rec->Stream == STREAM_MD5_SIGNATURE || - rec->Stream == STREAM_SHA1_SIGNATURE)) { - Pmsg2(0, "None of above!!! stream=%d data=%s\n", rec->Stream, rec->data); - } + Jmsg(jcr, M_ERROR, 0, _("Unknown stream=%d ignored. This shouldn't happen!\n"), + rec->Stream); + break; + + } /* end switch */ } diff --git a/bacula/src/stored/bls.c b/bacula/src/stored/bls.c index 1e0a3b908a..4a72d54390 100644 --- a/bacula/src/stored/bls.c +++ b/bacula/src/stored/bls.c @@ -28,6 +28,13 @@ #include "stored.h" #include "findlib/find.h" +#ifdef HAVE_CYGWIN +int win32_client = 1; +#else +int win32_client = 0; +#endif + + static void do_blocks(char *infname); static void do_jobs(char *infname); static void do_ls(char *fname); @@ -44,7 +51,7 @@ static DEV_BLOCK *block; static JCR *jcr; static SESSION_LABEL sessrec; static uint32_t num_files = 0; -static long record_file_index; +static ATTR *attr; #define CONFIG_FILE "bacula-sd.conf" char *configfile; @@ -91,77 +98,77 @@ int main (int argc, char *argv[]) while ((ch = getopt(argc, argv, "b:c:d:e:i:jkLtvV:?")) != -1) { switch (ch) { - case 'b': - bsrName = optarg; - break; + case 'b': + bsrName = optarg; + break; - case 'c': /* specify config file */ - if (configfile != NULL) { - free(configfile); - } - configfile = bstrdup(optarg); - break; + case 'c': /* specify config file */ + if (configfile != NULL) { + free(configfile); + } + configfile = bstrdup(optarg); + break; - case 'd': /* debug level */ - debug_level = atoi(optarg); - if (debug_level <= 0) - debug_level = 1; - break; + case 'd': /* debug level */ + debug_level = atoi(optarg); + if (debug_level <= 0) + debug_level = 1; + break; - case 'e': /* exclude list */ - if ((fd = fopen(optarg, "r")) == NULL) { - Pmsg2(0, _("Could not open exclude file: %s, ERR=%s\n"), - optarg, strerror(errno)); - exit(1); - } - while (fgets(line, sizeof(line), fd) != NULL) { - strip_trailing_junk(line); - Dmsg1(100, "add_exclude %s\n", line); - add_fname_to_exclude_list(&ff, line); - } - fclose(fd); - break; + case 'e': /* exclude list */ + if ((fd = fopen(optarg, "r")) == NULL) { + Pmsg2(0, _("Could not open exclude file: %s, ERR=%s\n"), + optarg, strerror(errno)); + exit(1); + } + while (fgets(line, sizeof(line), fd) != NULL) { + strip_trailing_junk(line); + Dmsg1(100, "add_exclude %s\n", line); + add_fname_to_exclude_list(&ff, line); + } + fclose(fd); + break; - case 'i': /* include list */ - if ((fd = fopen(optarg, "r")) == NULL) { - Pmsg2(0, "Could not open include file: %s, ERR=%s\n", - optarg, strerror(errno)); - exit(1); - } - while (fgets(line, sizeof(line), fd) != NULL) { - strip_trailing_junk(line); - Dmsg1(100, "add_include %s\n", line); - add_fname_to_include_list(&ff, 0, line); - } - fclose(fd); - break; + case 'i': /* include list */ + if ((fd = fopen(optarg, "r")) == NULL) { + Pmsg2(0, "Could not open include file: %s, ERR=%s\n", + optarg, strerror(errno)); + exit(1); + } + while (fgets(line, sizeof(line), fd) != NULL) { + strip_trailing_junk(line); + Dmsg1(100, "add_include %s\n", line); + add_fname_to_include_list(&ff, 0, line); + } + fclose(fd); + break; - case 'j': - list_jobs = TRUE; - break; + case 'j': + list_jobs = TRUE; + break; - case 'k': - list_blocks = TRUE; - break; + case 'k': + list_blocks = TRUE; + break; - case 'L': - dump_label = TRUE; - break; + case 'L': + dump_label = TRUE; + break; - case 'v': - verbose++; - break; + case 'v': + verbose++; + break; - case 'V': /* Volume name */ - VolumeName = optarg; - break; + case 'V': /* Volume name */ + VolumeName = optarg; + break; - case '?': - default: - usage(); + case '?': + default: + usage(); - } - } + } /* end switch */ + } /* end while */ argc -= optind; argv += optind; @@ -191,6 +198,7 @@ int main (int argc, char *argv[]) } rec = new_record(); block = new_block(dev); + attr = new_attr(); /* * Assume that we have already read the volume label. * If on second or subsequent volume, adjust buffer pointer @@ -220,6 +228,7 @@ Warning, this Volume is a continuation of Volume %s\n", static void do_close(JCR *jcr) { release_device(jcr, dev); + free_attr(attr); term_dev(dev); free_record(rec); free_block(block); @@ -319,43 +328,28 @@ static void do_ls(char *infname) */ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) { - char fname[2000]; - struct stat statp; - int type; - if (rec->FileIndex < 0) { get_session_record(dev, rec, &sessrec); return; } /* File Attributes stream */ - if (rec->Stream == STREAM_UNIX_ATTRIBUTES || rec->Stream == STREAM_WIN32_ATTRIBUTES) { - char *ap, *fp; + if (rec->Stream == STREAM_UNIX_ATTRIBUTES || + rec->Stream == STREAM_UNIX_ATTRIBUTES_EX) { uint32_t LinkFI; - sscanf(rec->data, "%ld %d", &record_file_index, &type); - if (record_file_index != rec->FileIndex) { - Emsg2(M_ERROR_TERM, 0, "Record header file index %ld not equal record index %ld\n", - rec->FileIndex, record_file_index); + if (!unpack_attributes_record(jcr, rec->Stream, rec->data, attr)) { + Emsg0(M_ERROR_TERM, 0, _("Cannot continue.\n")); } - ap = rec->data; - - while (*ap++ != ' ') /* skip record file index */ - ; - while (*ap++ != ' ') /* skip type */ - ; - /* Save filename and position to attributes */ - fp = fname; - while (*ap != 0) { - *fp++ = *ap++; + + if (attr->file_index != rec->FileIndex) { + Emsg2(M_ERROR_TERM, 0, _("Record header file index %ld not equal record index %ld\n"), + rec->FileIndex, attr->file_index); } - *fp = *ap++; /* terminate filename & point to attribs */ - - decode_stat(ap, &statp, &LinkFI); - /* Skip to link name */ - while (*ap++ != 0) - ; - if (file_is_included(&ff, fname) && !file_is_excluded(&ff, fname)) { - print_ls_output(fname, ap, type, &statp); + + decode_stat(attr->attr, &attr->statp, &LinkFI); + + if (file_is_included(&ff, attr->fname) && !file_is_excluded(&ff, attr->fname)) { + print_ls_output(jcr, attr); num_files++; } } diff --git a/bacula/src/stored/bscan.c b/bacula/src/stored/bscan.c index 99b9f23be9..9056f635f7 100644 --- a/bacula/src/stored/bscan.c +++ b/bacula/src/stored/bscan.c @@ -55,18 +55,18 @@ static int update_SIG_record(B_DB *db, char *SIGbuf, DEV_RECORD *rec, int type); /* Global variables */ STORES *me; +#ifdef HAVE_CYGWIN +int win32_client = 1; +#else +int win32_client = 0; +#endif + /* Local variables */ static DEVICE *dev = NULL; static B_DB *db; static JCR *bjcr; /* jcr for bscan */ static BSR *bsr = NULL; -static struct stat statp; -static int type; -static long record_file_index; -static POOLMEM *fname; /* original file name */ -static POOLMEM *ofile; /* output name with prefix */ -static POOLMEM *lname; /* link name */ static MEDIA_DBR mr; static POOL_DBR pr; static JOB_DBR jr; @@ -76,6 +76,7 @@ static ATTR_DBR ar; static FILE_DBR fr; static SESSION_LABEL label; static SESSION_LABEL elabel; +static ATTR *attr; static time_t lasttime = 0; @@ -126,62 +127,62 @@ int main (int argc, char *argv[]) while ((ch = getopt(argc, argv, "b:c:d:mn:p:rsu:vw:?")) != -1) { switch (ch) { - case 'b': - bsr = parse_bsr(NULL, optarg); - break; + case 'b': + bsr = parse_bsr(NULL, optarg); + break; - case 'c': /* specify config file */ - if (configfile != NULL) { - free(configfile); - } - configfile = bstrdup(optarg); - break; + case 'c': /* specify config file */ + if (configfile != NULL) { + free(configfile); + } + configfile = bstrdup(optarg); + break; - case 'd': /* debug level */ - debug_level = atoi(optarg); - if (debug_level <= 0) - debug_level = 1; - break; + case 'd': /* debug level */ + debug_level = atoi(optarg); + if (debug_level <= 0) + debug_level = 1; + break; - case 'm': - update_vol_info = 1; - break; + case 'm': + update_vol_info = 1; + break; - case 'n': - db_name = optarg; - break; + case 'n': + db_name = optarg; + break; - case 'u': - db_user = optarg; - break; + case 'u': + db_user = optarg; + break; - case 'p': - db_password = optarg; - break; + case 'p': + db_password = optarg; + break; - case 'r': - list_records = 1; - break; + case 'r': + list_records = 1; + break; - case 's': - update_db = 1; - break; + case 's': + update_db = 1; + break; - case 'v': - verbose++; - break; + case 'v': + verbose++; + break; - case 'V': /* Volume name */ - VolumeName = optarg; - break; + case 'V': /* Volume name */ + VolumeName = optarg; + break; - case 'w': - wd = optarg; - break; + case 'w': + wd = optarg; + break; - case '?': - default: - usage(); + case '?': + default: + usage(); } } @@ -252,9 +253,7 @@ int main (int argc, char *argv[]) static void do_scan() { - fname = get_pool_memory(PM_FNAME); - ofile = get_pool_memory(PM_FNAME); - lname = get_pool_memory(PM_FNAME); + attr = new_attr(); memset(&ar, 0, sizeof(ar)); memset(&pr, 0, sizeof(pr)); @@ -268,9 +267,7 @@ static void do_scan() read_records(bjcr, dev, record_cb, mount_next_read_volume); release_device(bjcr, dev); - free_pool_memory(fname); - free_pool_memory(ofile); - free_pool_memory(lname); + free_attr(attr); term_dev(dev); } @@ -298,255 +295,225 @@ static void record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) dump_label_record(dev, rec, 1); } switch (rec->FileIndex) { - case PRE_LABEL: - Pmsg0(000, _("Volume is prelabeled. This tape cannot be scanned.\n")); - return; - break; - case VOL_LABEL: - unser_volume_label(dev, rec); - /* Check Pool info */ - strcpy(pr.Name, dev->VolHdr.PoolName); - strcpy(pr.PoolType, dev->VolHdr.PoolType); - if (db_get_pool_record(bjcr, db, &pr)) { - if (verbose) { - Pmsg1(000, _("Pool record for %s found in DB.\n"), pr.Name); - } - } else { - if (!update_db) { - Pmsg1(000, _("VOL_LABEL: Pool record not found for Pool: %s\n"), - pr.Name); - } - create_pool_record(db, &pr); + case PRE_LABEL: + Pmsg0(000, _("Volume is prelabeled. This tape cannot be scanned.\n")); + return; + break; + case VOL_LABEL: + unser_volume_label(dev, rec); + /* Check Pool info */ + strcpy(pr.Name, dev->VolHdr.PoolName); + strcpy(pr.PoolType, dev->VolHdr.PoolType); + if (db_get_pool_record(bjcr, db, &pr)) { + if (verbose) { + Pmsg1(000, _("Pool record for %s found in DB.\n"), pr.Name); } - if (strcmp(pr.PoolType, dev->VolHdr.PoolType) != 0) { - Pmsg2(000, _("VOL_LABEL: PoolType mismatch. DB=%s Vol=%s\n"), - pr.PoolType, dev->VolHdr.PoolType); - return; - } else if (verbose) { - Pmsg1(000, _("Pool type \"%s\" is OK.\n"), pr.PoolType); + } else { + if (!update_db) { + Pmsg1(000, _("VOL_LABEL: Pool record not found for Pool: %s\n"), + pr.Name); } + create_pool_record(db, &pr); + } + if (strcmp(pr.PoolType, dev->VolHdr.PoolType) != 0) { + Pmsg2(000, _("VOL_LABEL: PoolType mismatch. DB=%s Vol=%s\n"), + pr.PoolType, dev->VolHdr.PoolType); + return; + } else if (verbose) { + Pmsg1(000, _("Pool type \"%s\" is OK.\n"), pr.PoolType); + } - /* Check Media Info */ - memset(&mr, 0, sizeof(mr)); - strcpy(mr.VolumeName, dev->VolHdr.VolName); - mr.PoolId = pr.PoolId; - if (db_get_media_record(bjcr, db, &mr)) { - if (verbose) { - Pmsg1(000, _("Media record for %s found in DB.\n"), mr.VolumeName); - } - /* Clear out some volume statistics that will be updated */ - mr.VolJobs = mr.VolFiles = mr.VolBlocks = 0; - mr.VolBytes = rec->data_len + 20; - } else { - if (!update_db) { - Pmsg1(000, _("VOL_LABEL: Media record not found for Volume: %s\n"), - mr.VolumeName); - } - strcpy(mr.MediaType, dev->VolHdr.MediaType); - create_media_record(db, &mr, &dev->VolHdr); - } - if (strcmp(mr.MediaType, dev->VolHdr.MediaType) != 0) { - Pmsg2(000, _("VOL_LABEL: MediaType mismatch. DB=%s Vol=%s\n"), - mr.MediaType, dev->VolHdr.MediaType); - return; - } else if (verbose) { - Pmsg1(000, _("Media type \"%s\" is OK.\n"), mr.MediaType); + /* Check Media Info */ + memset(&mr, 0, sizeof(mr)); + strcpy(mr.VolumeName, dev->VolHdr.VolName); + mr.PoolId = pr.PoolId; + if (db_get_media_record(bjcr, db, &mr)) { + if (verbose) { + Pmsg1(000, _("Media record for %s found in DB.\n"), mr.VolumeName); } - /* Reset some JCR variables */ - for (mjcr=NULL; (mjcr=next_attached_jcr(dev, mjcr)); ) { - mjcr->VolFirstIndex = mjcr->FileIndex = 0; - mjcr->StartBlock = mjcr->EndBlock = 0; - mjcr->StartFile = mjcr->EndFile = 0; + /* Clear out some volume statistics that will be updated */ + mr.VolJobs = mr.VolFiles = mr.VolBlocks = 0; + mr.VolBytes = rec->data_len + 20; + } else { + if (!update_db) { + Pmsg1(000, _("VOL_LABEL: Media record not found for Volume: %s\n"), + mr.VolumeName); } + strcpy(mr.MediaType, dev->VolHdr.MediaType); + create_media_record(db, &mr, &dev->VolHdr); + } + if (strcmp(mr.MediaType, dev->VolHdr.MediaType) != 0) { + Pmsg2(000, _("VOL_LABEL: MediaType mismatch. DB=%s Vol=%s\n"), + mr.MediaType, dev->VolHdr.MediaType); + return; + } else if (verbose) { + Pmsg1(000, _("Media type \"%s\" is OK.\n"), mr.MediaType); + } + /* Reset some JCR variables */ + for (mjcr=NULL; (mjcr=next_attached_jcr(dev, mjcr)); ) { + mjcr->VolFirstIndex = mjcr->FileIndex = 0; + mjcr->StartBlock = mjcr->EndBlock = 0; + mjcr->StartFile = mjcr->EndFile = 0; + } - Pmsg1(000, _("VOL_LABEL: OK for Volume: %s\n"), mr.VolumeName); - break; - case SOS_LABEL: - mr.VolJobs++; - if (ignored_msgs > 0) { - Pmsg1(000, _("%d \"errors\" ignored before first Start of Session record.\n"), - ignored_msgs); - ignored_msgs = 0; - } - unser_session_label(&label, rec); - memset(&jr, 0, sizeof(jr)); - jr.JobId = label.JobId; - if (db_get_job_record(bjcr, db, &jr)) { - /* Job record already exists in DB */ - update_db = 0; /* don't change db in create_job_record */ - if (verbose) { - Pmsg1(000, _("SOS_LABEL: Found Job record for JobId: %d\n"), jr.JobId); - } - } else { - /* Must create a Job record in DB */ - if (!update_db) { - Pmsg1(000, _("SOS_LABEL: Job record not found for JobId: %d\n"), - jr.JobId); - } - } - /* Create Client record if not already there */ - strcpy(cr.Name, label.ClientName); - create_client_record(db, &cr); - jr.ClientId = cr.ClientId; - - /* process label, if Job record exists don't update db */ - mjcr = create_job_record(db, &jr, &label, rec); - update_db = save_update_db; - - jr.PoolId = pr.PoolId; - /* Set start positions into JCR */ - if (dev->state & ST_TAPE) { - mjcr->StartBlock = dev->block_num; - mjcr->StartFile = dev->file; - } else { - mjcr->StartBlock = (uint32_t)dev->file_addr; - mjcr->StartFile = (uint32_t)(dev->file_addr >> 32); - } - mjcr->start_time = jr.StartTime; - mjcr->JobLevel = jr.Level; - - mjcr->client_name = get_pool_memory(PM_FNAME); - pm_strcpy(&mjcr->client_name, label.ClientName); - mjcr->pool_type = get_pool_memory(PM_FNAME); - pm_strcpy(&mjcr->pool_type, label.PoolType); - mjcr->fileset_name = get_pool_memory(PM_FNAME); - pm_strcpy(&mjcr->fileset_name, label.FileSetName); - mjcr->pool_name = get_pool_memory(PM_FNAME); - pm_strcpy(&mjcr->pool_name, label.PoolName); - - if (rec->VolSessionId != jr.VolSessionId) { - Pmsg3(000, _("SOS_LABEL: VolSessId mismatch for JobId=%u. DB=%d Vol=%d\n"), - jr.JobId, - jr.VolSessionId, rec->VolSessionId); - return; - } - if (rec->VolSessionTime != jr.VolSessionTime) { - Pmsg3(000, _("SOS_LABEL: VolSessTime mismatch for JobId=%u. DB=%d Vol=%d\n"), - jr.JobId, - jr.VolSessionTime, rec->VolSessionTime); - return; + Pmsg1(000, _("VOL_LABEL: OK for Volume: %s\n"), mr.VolumeName); + break; + case SOS_LABEL: + mr.VolJobs++; + if (ignored_msgs > 0) { + Pmsg1(000, _("%d \"errors\" ignored before first Start of Session record.\n"), + ignored_msgs); + ignored_msgs = 0; + } + unser_session_label(&label, rec); + memset(&jr, 0, sizeof(jr)); + jr.JobId = label.JobId; + if (db_get_job_record(bjcr, db, &jr)) { + /* Job record already exists in DB */ + update_db = 0; /* don't change db in create_job_record */ + if (verbose) { + Pmsg1(000, _("SOS_LABEL: Found Job record for JobId: %d\n"), jr.JobId); } - if (jr.PoolId != pr.PoolId) { - Pmsg3(000, _("SOS_LABEL: PoolId mismatch for JobId=%u. DB=%d Vol=%d\n"), - jr.JobId, - jr.PoolId, pr.PoolId); - return; + } else { + /* Must create a Job record in DB */ + if (!update_db) { + Pmsg1(000, _("SOS_LABEL: Job record not found for JobId: %d\n"), + jr.JobId); } + } + /* Create Client record if not already there */ + strcpy(cr.Name, label.ClientName); + create_client_record(db, &cr); + jr.ClientId = cr.ClientId; + + /* process label, if Job record exists don't update db */ + mjcr = create_job_record(db, &jr, &label, rec); + update_db = save_update_db; + + jr.PoolId = pr.PoolId; + /* Set start positions into JCR */ + if (dev->state & ST_TAPE) { + mjcr->StartBlock = dev->block_num; + mjcr->StartFile = dev->file; + } else { + mjcr->StartBlock = (uint32_t)dev->file_addr; + mjcr->StartFile = (uint32_t)(dev->file_addr >> 32); + } + mjcr->start_time = jr.StartTime; + mjcr->JobLevel = jr.Level; + + mjcr->client_name = get_pool_memory(PM_FNAME); + pm_strcpy(&mjcr->client_name, label.ClientName); + mjcr->pool_type = get_pool_memory(PM_FNAME); + pm_strcpy(&mjcr->pool_type, label.PoolType); + mjcr->fileset_name = get_pool_memory(PM_FNAME); + pm_strcpy(&mjcr->fileset_name, label.FileSetName); + mjcr->pool_name = get_pool_memory(PM_FNAME); + pm_strcpy(&mjcr->pool_name, label.PoolName); + + if (rec->VolSessionId != jr.VolSessionId) { + Pmsg3(000, _("SOS_LABEL: VolSessId mismatch for JobId=%u. DB=%d Vol=%d\n"), + jr.JobId, + jr.VolSessionId, rec->VolSessionId); + return; + } + if (rec->VolSessionTime != jr.VolSessionTime) { + Pmsg3(000, _("SOS_LABEL: VolSessTime mismatch for JobId=%u. DB=%d Vol=%d\n"), + jr.JobId, + jr.VolSessionTime, rec->VolSessionTime); + return; + } + if (jr.PoolId != pr.PoolId) { + Pmsg3(000, _("SOS_LABEL: PoolId mismatch for JobId=%u. DB=%d Vol=%d\n"), + jr.JobId, + jr.PoolId, pr.PoolId); + return; + } + break; + case EOS_LABEL: + unser_session_label(&elabel, rec); + + /* Create FileSet record */ + strcpy(fsr.FileSet, label.FileSetName); + strcpy(fsr.MD5, label.FileSetMD5); + create_fileset_record(db, &fsr); + jr.FileSetId = fsr.FileSetId; + + mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime); + if (!mjcr) { + Pmsg2(000, _("Could not find SessId=%d SessTime=%d for EOS record.\n"), + rec->VolSessionId, rec->VolSessionTime); break; - case EOS_LABEL: - unser_session_label(&elabel, rec); - - /* Create FileSet record */ - strcpy(fsr.FileSet, label.FileSetName); - strcpy(fsr.MD5, label.FileSetMD5); - create_fileset_record(db, &fsr); - jr.FileSetId = fsr.FileSetId; - - mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime); - if (!mjcr) { - Pmsg2(000, _("Could not find SessId=%d SessTime=%d for EOS record.\n"), - rec->VolSessionId, rec->VolSessionTime); - break; - } + } - /* Do the final update to the Job record */ - update_job_record(db, &jr, &elabel, rec); + /* Do the final update to the Job record */ + update_job_record(db, &jr, &elabel, rec); - mjcr->end_time = jr.EndTime; - mjcr->JobStatus = JS_Terminated; + mjcr->end_time = jr.EndTime; + mjcr->JobStatus = JS_Terminated; - /* Create JobMedia record */ - create_jobmedia_record(db, mjcr); - detach_jcr_from_device(dev, mjcr); - free_jcr(mjcr); + /* Create JobMedia record */ + create_jobmedia_record(db, mjcr); + detach_jcr_from_device(dev, mjcr); + free_jcr(mjcr); - break; - case EOM_LABEL: - break; - case EOT_LABEL: /* end of all tapes */ - /* - * Wiffle through all jobs still open and close - * them. - */ - if (update_db) { - for (mjcr=NULL; (mjcr=next_attached_jcr(dev, mjcr)); ) { - jr.JobId = mjcr->JobId; - jr.JobStatus = JS_ErrorTerminated; - jr.JobFiles = mjcr->JobFiles; - jr.JobBytes = mjcr->JobBytes; - jr.VolSessionId = mjcr->VolSessionId; - jr.VolSessionTime = mjcr->VolSessionTime; - jr.JobTDate = (utime_t)mjcr->start_time; - jr.ClientId = mjcr->ClientId; - free_jcr(mjcr); - if (!db_update_job_end_record(bjcr, db, &jr)) { - Pmsg1(0, _("Could not update job record. ERR=%s\n"), db_strerror(db)); - } + break; + case EOM_LABEL: + break; + case EOT_LABEL: /* end of all tapes */ + /* + * Wiffle through all jobs still open and close + * them. + */ + if (update_db) { + for (mjcr=NULL; (mjcr=next_attached_jcr(dev, mjcr)); ) { + jr.JobId = mjcr->JobId; + jr.JobStatus = JS_ErrorTerminated; + jr.JobFiles = mjcr->JobFiles; + jr.JobBytes = mjcr->JobBytes; + jr.VolSessionId = mjcr->VolSessionId; + jr.VolSessionTime = mjcr->VolSessionTime; + jr.JobTDate = (utime_t)mjcr->start_time; + jr.ClientId = mjcr->ClientId; + free_jcr(mjcr); + if (!db_update_job_end_record(bjcr, db, &jr)) { + Pmsg1(0, _("Could not update job record. ERR=%s\n"), db_strerror(db)); } } - mr.VolFiles = rec->File; - mr.VolBlocks = rec->Block; - mr.VolBytes += mr.VolBlocks * WRITE_BLKHDR_LENGTH; /* approx. */ - mr.VolMounts++; - update_media_record(db, &mr); - Pmsg3(0, _("End of Volume. VolFiles=%u VolBlocks=%u VolBytes=%s\n"), mr.VolFiles, - mr.VolBlocks, edit_uint64_with_commas(mr.VolBytes, ec1)); - break; - default: - break; - } + } + mr.VolFiles = rec->File; + mr.VolBlocks = rec->Block; + mr.VolBytes += mr.VolBlocks * WRITE_BLKHDR_LENGTH; /* approx. */ + mr.VolMounts++; + update_media_record(db, &mr); + Pmsg3(0, _("End of Volume. VolFiles=%u VolBlocks=%u VolBytes=%s\n"), mr.VolFiles, + mr.VolBlocks, edit_uint64_with_commas(mr.VolBytes, ec1)); + break; + default: + break; + } /* end switch */ return; } /* File Attributes stream */ - if (rec->Stream == STREAM_UNIX_ATTRIBUTES || rec->Stream == STREAM_WIN32_ATTRIBUTES) { - char *ap, *lp, *fp; + switch (rec->Stream) { + case STREAM_UNIX_ATTRIBUTES: + case STREAM_UNIX_ATTRIBUTES_EX: - if (sizeof_pool_memory(fname) < rec->data_len) { - fname = realloc_pool_memory(fname, rec->data_len + 1); + if (!unpack_attributes_record(bjcr, rec->Stream, rec->data, attr)) { + Emsg0(M_ERROR_TERM, 0, _("Cannot continue.\n")); } - if (sizeof_pool_memory(lname) < rec->data_len) { - lname = realloc_pool_memory(lname, rec->data_len + 1); - } - *fname = 0; - *lname = 0; - - /* - * An Attributes record consists of: - * File_index - * Type (FT_types) - * Filename - * Attributes - * Link name (if file linked i.e. FT_LNK) - * - */ - sscanf(rec->data, "%ld %d", &record_file_index, &type); - if (record_file_index != rec->FileIndex) - Emsg2(M_ERROR_TERM, 0, "Record header file index %ld not equal record index %ld\n", - rec->FileIndex, record_file_index); - ap = rec->data; - while (*ap++ != ' ') /* skip record file index */ - ; - while (*ap++ != ' ') /* skip type */ - ; - /* Save filename and position to attributes */ - fp = fname; - while (*ap != 0) { - *fp++ = *ap++; - } - *fp = *ap++; /* terminate filename & point to attribs */ - /* Skip through attributes to link name */ - lp = ap; - while (*lp++ != 0) { - ; + if (attr->file_index != rec->FileIndex) { + Emsg2(M_ERROR_TERM, 0, _("Record header file index %ld not equal record index %ld\n"), + rec->FileIndex, attr->file_index); } - strcat(lname, lp); /* "save" link name */ + if (verbose > 1) { uint32_t LinkFI; - decode_stat(ap, &statp, &LinkFI); - print_ls_output(fname, lname, type, &statp); + decode_stat(attr->attr, &attr->statp, &LinkFI); + print_ls_output(bjcr, attr); } mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime); if (!mjcr) { @@ -560,17 +527,21 @@ static void record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) } fr.JobId = mjcr->JobId; fr.FileId = 0; - if (db_get_file_attributes_record(bjcr, db, fname, &fr)) { + if (db_get_file_attributes_record(bjcr, db, attr->fname, &fr)) { if (verbose > 1) { - Pmsg1(000, _("File record already exists for: %s\n"), fname); + Pmsg1(000, _("File record already exists for: %s\n"), attr->fname); } } else { - create_file_attributes_record(db, mjcr, fname, lname, type, ap, rec); + create_file_attributes_record(db, mjcr, attr->fname, attr->lname, + attr->type, attr->attr, rec); } free_jcr(mjcr); + break; /* Data stream */ - } else if (rec->Stream == STREAM_FILE_DATA) { + case STREAM_WIN32_DATA: + case STREAM_FILE_DATA: + case STREAM_SPARSE_DATA: mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime); if (!mjcr) { if (mr.VolJobs > 0) { @@ -582,23 +553,14 @@ static void record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) return; } mjcr->JobBytes += rec->data_len; - free_jcr(mjcr); /* done using JCR */ - - } else if (rec->Stream == STREAM_SPARSE_DATA) { - mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime); - if (!mjcr) { - if (mr.VolJobs > 0) { - Pmsg2(000, _("Could not find Job SessId=%d SessTime=%d for Sparse Data record.\n"), - rec->VolSessionId, rec->VolSessionTime); - } else { - ignored_msgs++; - } - return; + if (rec->Stream == STREAM_SPARSE_DATA) { + mjcr->JobBytes -= sizeof(uint64_t); } - mjcr->JobBytes += rec->data_len - sizeof(uint64_t); + free_jcr(mjcr); /* done using JCR */ + break; - } else if (rec->Stream == STREAM_GZIP_DATA) { + case STREAM_GZIP_DATA: mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime); if (!mjcr) { if (mr.VolJobs > 0) { @@ -611,8 +573,9 @@ static void record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) } mjcr->JobBytes += rec->data_len; /* No correct, we should expand it */ free_jcr(mjcr); /* done using JCR */ + break; - } else if (rec->Stream == STREAM_SPARSE_GZIP_DATA) { + case STREAM_SPARSE_GZIP_DATA: mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime); if (!mjcr) { if (mr.VolJobs > 0) { @@ -625,24 +588,10 @@ static void record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) } mjcr->JobBytes += rec->data_len - sizeof(uint64_t); /* No correct, we should expand it */ free_jcr(mjcr); /* done using JCR */ - - /* Win32 Data stream */ - } else if (rec->Stream == STREAM_WIN32_DATA) { - mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime); - if (!mjcr) { - if (mr.VolJobs > 0) { - Pmsg2(000, _("Could not find Job SessId=%d SessTime=%d for Win32 Data record.\n"), - rec->VolSessionId, rec->VolSessionTime); - } else { - ignored_msgs++; - } - return; - } - mjcr->JobBytes += rec->data_len; - free_jcr(mjcr); /* done using JCR */ + break; /* Win32 GZIP stream */ - } else if (rec->Stream == STREAM_WIN32_GZIP_DATA) { + case STREAM_WIN32_GZIP_DATA: mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime); if (!mjcr) { if (mr.VolJobs > 0) { @@ -655,34 +604,41 @@ static void record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) } mjcr->JobBytes += rec->data_len; free_jcr(mjcr); /* done using JCR */ + break; - } else if (rec->Stream == STREAM_MD5_SIGNATURE) { + case STREAM_MD5_SIGNATURE: char MD5buf[50]; bin_to_base64(MD5buf, (char *)rec->data, 16); /* encode 16 bytes */ if (verbose > 1) { Pmsg1(000, _("Got MD5 record: %s\n"), MD5buf); } update_SIG_record(db, MD5buf, rec, MD5_SIG); + break; - } else if (rec->Stream == STREAM_SHA1_SIGNATURE) { + case STREAM_SHA1_SIGNATURE: char SIGbuf[50]; bin_to_base64(SIGbuf, (char *)rec->data, 20); /* encode 20 bytes */ if (verbose > 1) { Pmsg1(000, _("Got SHA1 record: %s\n"), SIGbuf); } update_SIG_record(db, SIGbuf, rec, SHA1_SIG); + break; - } else if (rec->Stream == STREAM_PROGRAM_NAMES) { + case STREAM_PROGRAM_NAMES: if (verbose) { Pmsg1(000, _("Got Prog Names Stream: %s\n"), rec->data); } - } else if (rec->Stream == STREAM_PROGRAM_DATA) { + break; + + case STREAM_PROGRAM_DATA: if (verbose > 1) { Pmsg0(000, _("Got Prog Data Stream record.\n")); } - } else { + break; + default: Pmsg2(0, _("Unknown stream type!!! stream=%d data=%s\n"), rec->Stream, rec->data); + break; } return; } diff --git a/bacula/src/stored/butil.c b/bacula/src/stored/butil.c index a9cad0198e..a23bb1646f 100644 --- a/bacula/src/stored/butil.c +++ b/bacula/src/stored/butil.c @@ -226,6 +226,7 @@ JCR *setup_jcr(char *name, char *device, BSR *bsr, char *VolumeName) if (!bsr && VolumeName) { pm_strcpy(&jcr->VolumeName, VolumeName); } + jcr->where = bstrdup(""); return jcr; } @@ -253,41 +254,3 @@ void display_tape_error_status(JCR *jcr, DEVICE *dev) else Jmsg(jcr, M_ERROR, 0, _("Read error on Record Header %s: %s\n"), dev_name(dev), strerror(errno)); } - - -extern char *getuser(uid_t uid); -extern char *getgroup(gid_t gid); - -void print_ls_output(char *fname, char *link, int type, struct stat *statp) -{ - char buf[1000]; - char ec1[30]; - char *p, *f; - int n; - - p = encode_mode(statp->st_mode, buf); - n = sprintf(p, " %2d ", (uint32_t)statp->st_nlink); - p += n; - n = sprintf(p, "%-8.8s %-8.8s", getuser(statp->st_uid), getgroup(statp->st_gid)); - p += n; - n = sprintf(p, "%8.8s ", edit_uint64(statp->st_size, ec1)); - p += n; - p = encode_time(statp->st_ctime, p); - *p++ = ' '; - *p++ = ' '; - /* Copy file name */ - for (f=fname; *f && (p-buf) < (int)sizeof(buf); ) - *p++ = *f++; - if (type == FT_LNK) { - *p++ = ' '; - *p++ = '-'; - *p++ = '>'; - *p++ = ' '; - /* Copy link name */ - for (f=link; *f && (p-buf) < (int)sizeof(buf); ) - *p++ = *f++; - } - *p++ = '\n'; - *p = 0; - fputs(buf, stdout); -} diff --git a/bacula/src/stored/record.c b/bacula/src/stored/record.c index 22b3c4ebdf..e560ad0385 100644 --- a/bacula/src/stored/record.c +++ b/bacula/src/stored/record.c @@ -102,8 +102,8 @@ char *stream_to_ascii(int stream, int fi) return "SHA1"; case STREAM_GZIP_DATA: return "GZIP"; - case STREAM_WIN32_ATTRIBUTES: - return "WIN32-ATTR"; + case STREAM_UNIX_ATTRIBUTES_EX: + return "UNIX-ATTR-EX"; case STREAM_SPARSE_DATA: return "SPARSE-DATA"; case STREAM_SPARSE_GZIP_DATA: @@ -126,8 +126,8 @@ char *stream_to_ascii(int stream, int fi) return "contSHA1"; case -STREAM_GZIP_DATA: return "contGZIP"; - case -STREAM_WIN32_ATTRIBUTES: - return "contWIN32-ATTR"; + case -STREAM_UNIX_ATTRIBUTES_EX: + return "contUNIX-ATTR-EX"; case -STREAM_SPARSE_DATA: return "contSPARSE-DATA"; case -STREAM_SPARSE_GZIP_DATA: diff --git a/bacula/src/stored/stored.h b/bacula/src/stored/stored.h index 11cc78e6f0..ff27271b44 100644 --- a/bacula/src/stored/stored.h +++ b/bacula/src/stored/stored.h @@ -42,14 +42,12 @@ #include "jcr.h" #include "protos.h" #ifdef HAVE_LIBZ -#include /* compression headers */ +#include /* compression headers */ #else #define uLongf uint32_t #endif -#include "findlib/find.h" - -extern char errmsg[]; /* general error message */ +extern char errmsg[]; /* general error message */ extern STORES *me; /* "Global" daemon resource */ -- 2.39.2