コード例 #1
0
ファイル: btime.c プロジェクト: halgandd/bacula
/* Deprecated. Do not use. */
void get_current_time(struct date_time *dt)
{
   struct tm tm;
   time_t now;

   now = time(NULL);
   (void)gmtime_r(&now, &tm);
   Dmsg6(200, "m=%d d=%d y=%d h=%d m=%d s=%d\n", tm.tm_mon+1, tm.tm_mday, tm.tm_year+1900,
      tm.tm_hour, tm.tm_min, tm.tm_sec);
   tm_encode(dt, &tm);
#ifdef DEBUG
   Dmsg2(200, "jday=%f jmin=%f\n", dt->julian_day_number, dt->julian_day_fraction);
   tm_decode(dt, &tm);
   Dmsg6(200, "m=%d d=%d y=%d h=%d m=%d s=%d\n", tm.tm_mon+1, tm.tm_mday, tm.tm_year+1900,
      tm.tm_hour, tm.tm_min, tm.tm_sec);
#endif
}
コード例 #2
0
ファイル: record.c プロジェクト: aussendorf/bareos
static inline bool write_data_to_block(DEV_BLOCK *block, DEV_RECORD *rec)
{
   rec->remlen = block->buf_len - block->binbuf;

   /*
    * Write as much of data as possible
    */
   if (rec->remlen >= rec->remainder) {
      memcpy(block->bufp, rec->data + (rec->data_len - rec->remainder), rec->remainder);
      block->bufp += rec->remainder;
      block->binbuf += rec->remainder;
   } else {
      memcpy(block->bufp, rec->data + (rec->data_len - rec->remainder), rec->remlen);
#ifdef xxxxxSMCHECK
      if (!sm_check_rtn(__FILE__, __LINE__, False)) {
         /*
          * We damaged a buffer
          */
         Dmsg6(0, "Damaged block FI=%s SessId=%d Strm=%s len=%d\n"
            "rem=%d remainder=%d\n",
            FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId,
            stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len,
            rec->remlen, rec->remainder);
         Dmsg5(0, "Damaged block: bufp=%x binbuf=%d buf_len=%d rem=%d moved=%d\n",
            block->bufp, block->binbuf, block->buf_len, block->buf_len-block->binbuf,
            rec->remlen);
         Dmsg2(0, "Damaged block: buf=%x binbuffrombuf=%d \n",
            block->buf, block->bufp-block->buf);
         Emsg0(M_ABORT, 0, _("Damaged buffer\n"));
      }
#endif

      block->bufp += rec->remlen;
      block->binbuf += rec->remlen;
      rec->remainder -= rec->remlen;

      return false;                /* did partial transfer */
   }

   return true;
}
コード例 #3
0
ファイル: catreq.c プロジェクト: NilByMouth/bareos
void catalog_request(JCR *jcr, BSOCK *bs)
{
   MEDIA_DBR mr, sdmr;
   JOBMEDIA_DBR jm;
   char Job[MAX_NAME_LENGTH];
   char pool_name[MAX_NAME_LENGTH];
   int index, ok, label, writing;
   POOLMEM *omsg;
   POOL_DBR pr;
   uint32_t Stripe, Copy;
   uint64_t MediaId;
   utime_t VolFirstWritten;
   utime_t VolLastWritten;

   memset(&sdmr, 0, sizeof(sdmr));
   memset(&jm, 0, sizeof(jm));
   Dsm_check(100);

   /*
    * Request to find next appendable Volume for this Job
    */
   Dmsg1(100, "catreq %s", bs->msg);
   if (!jcr->db) {
      omsg = get_memory(bs->msglen+1);
      pm_strcpy(omsg, bs->msg);
      bs->fsend(_("1990 Invalid Catalog Request: %s"), omsg);
      Jmsg1(jcr, M_FATAL, 0, _("Invalid Catalog request; DB not open: %s"), omsg);
      free_memory(omsg);
      return;
   }
   /*
    * Find next appendable medium for SD
    */
   if (sscanf(bs->msg, Find_media, &Job, &index, &pool_name, &mr.MediaType) == 4) {
      memset(&pr, 0, sizeof(pr));
      bstrncpy(pr.Name, pool_name, sizeof(pr.Name));
      unbash_spaces(pr.Name);
      ok = db_get_pool_record(jcr, jcr->db, &pr);
      if (ok) {
         mr.PoolId = pr.PoolId;
         set_storageid_in_mr(jcr->res.wstore, &mr);
         mr.ScratchPoolId = pr.ScratchPoolId;
         ok = find_next_volume_for_append(jcr, &mr, index, fnv_create_vol, fnv_prune);
         Dmsg3(050, "find_media ok=%d idx=%d vol=%s\n", ok, index, mr.VolumeName);
      }
      /*
       * Send Find Media response to Storage daemon
       */
      if (ok) {
         send_volume_info_to_storage_daemon(jcr, bs, &mr);
      } else {
         bs->fsend(_("1901 No Media.\n"));
         Dmsg0(500, "1901 No Media.\n");
      }

   /*
    * Request to find specific Volume information
    */
   } else if (sscanf(bs->msg, Get_Vol_Info, &Job, &mr.VolumeName, &writing) == 3) {
      Dmsg1(100, "CatReq GetVolInfo Vol=%s\n", mr.VolumeName);
      /*
       * Find the Volume
       */
      unbash_spaces(mr.VolumeName);
      if (db_get_media_record(jcr, jcr->db, &mr)) {
         const char *reason = NULL;           /* detailed reason for rejection */
         /*
          * If we are reading, accept any volume (reason == NULL)
          * If we are writing, check if the Volume is valid
          *   for this job, and do a recycle if necessary
          */
         if (writing) {
            /*
             * SD wants to write this Volume, so make
             *   sure it is suitable for this job, i.e.
             *   Pool matches, and it is either Append or Recycle
             *   and Media Type matches and Pool allows any volume.
             */
            if (mr.PoolId != jcr->jr.PoolId) {
               reason = _("not in Pool");
            } else if (!bstrcmp(mr.MediaType, jcr->res.wstore->media_type)) {
               reason = _("not correct MediaType");
            } else {
               /*
                * Now try recycling if necessary
                *   reason set non-NULL if we cannot use it
                */
               check_if_volume_valid_or_recyclable(jcr, &mr, &reason);
            }
         }
         if (!reason && mr.Enabled != 1) {
            reason = _("is not Enabled");
         }
         if (reason == NULL) {
            /*
             * Send Find Media response to Storage daemon
             */
            send_volume_info_to_storage_daemon(jcr, bs, &mr);
         } else {
            /* Not suitable volume */
            bs->fsend(_("1998 Volume \"%s\" catalog status is %s, %s.\n"), mr.VolumeName,
               mr.VolStatus, reason);
         }

      } else {
         bs->fsend(_("1997 Volume \"%s\" not in catalog.\n"), mr.VolumeName);
         Dmsg1(100, "1997 Volume \"%s\" not in catalog.\n", mr.VolumeName);
      }

   /*
    * Request to update Media record. Comes typically at the end
    *  of a Storage daemon Job Session, when labeling/relabeling a
    *  Volume, or when an EOF mark is written.
    */
   } else if (sscanf(bs->msg, Update_media, &Job, &sdmr.VolumeName,
                     &sdmr.VolJobs, &sdmr.VolFiles, &sdmr.VolBlocks, &sdmr.VolBytes,
                     &sdmr.VolMounts, &sdmr.VolErrors, &sdmr.VolWrites, &sdmr.MaxVolBytes,
                     &VolLastWritten, &sdmr.VolStatus, &sdmr.Slot, &label, &sdmr.InChanger,
                     &sdmr.VolReadTime, &sdmr.VolWriteTime, &VolFirstWritten) == 18) {
      db_lock(jcr->db);
      Dmsg3(400, "Update media %s oldStat=%s newStat=%s\n", sdmr.VolumeName,
         mr.VolStatus, sdmr.VolStatus);
      bstrncpy(mr.VolumeName, sdmr.VolumeName, sizeof(mr.VolumeName)); /* copy Volume name */
      unbash_spaces(mr.VolumeName);
      if (!db_get_media_record(jcr, jcr->db, &mr)) {
         Jmsg(jcr, M_ERROR, 0, _("Unable to get Media record for Volume %s: ERR=%s\n"),
              mr.VolumeName, db_strerror(jcr->db));
         bs->fsend(_("1991 Catalog Request for vol=%s failed: %s"),
            mr.VolumeName, db_strerror(jcr->db));
         goto bail_out;

      }
      /* Set first written time if this is first job */
      if (mr.FirstWritten == 0) {
         if (VolFirstWritten == 0) {
            mr.FirstWritten = jcr->start_time;   /* use Job start time as first write */
         } else {
            mr.FirstWritten = VolFirstWritten;
         }
         mr.set_first_written = true;
      }
      /* If we just labeled the tape set time */
      if (label || mr.LabelDate == 0) {
         mr.LabelDate = jcr->start_time;
         mr.set_label_date = true;
         if (mr.InitialWrite == 0) {
            mr.InitialWrite = jcr->start_time;
         }
         Dmsg2(400, "label=%d labeldate=%d\n", label, mr.LabelDate);
      } else {
         /*
          * Insanity check for VolFiles get set to a smaller value
          */
         if (sdmr.VolFiles < mr.VolFiles) {
            Jmsg(jcr, M_FATAL, 0, _("Volume Files at %u being set to %u"
                 " for Volume \"%s\". This is incorrect.\n"),
               mr.VolFiles, sdmr.VolFiles, mr.VolumeName);
            bs->fsend(_("1992 Update Media error. VolFiles=%u, CatFiles=%u\n"),
               sdmr.VolFiles, mr.VolFiles);
            goto bail_out;

         }
      }
      Dmsg2(400, "Update media: BefVolJobs=%u After=%u\n", mr.VolJobs, sdmr.VolJobs);

      /*
       * Check if the volume has been written by the job,
       * and update the LastWritten field if needed.
       */
      if (mr.VolBlocks != sdmr.VolBlocks && VolLastWritten != 0) {
         mr.LastWritten = VolLastWritten;
      }

      /*
       * Update to point to the last device used to write the Volume.
       *   However, do so only if we are writing the tape, i.e.
       *   the number of VolWrites has increased.
       */
      if (jcr->res.wstore && sdmr.VolWrites > mr.VolWrites) {
         Dmsg2(050, "Update StorageId old=%d new=%d\n",
               mr.StorageId, jcr->res.wstore->StorageId);
         /* Update StorageId after write */
         set_storageid_in_mr(jcr->res.wstore, &mr);
      } else {
         /* Nothing written, reset same StorageId */
         set_storageid_in_mr(NULL, &mr);
      }

      /* Copy updated values to original media record */
      mr.VolJobs      = sdmr.VolJobs;
      mr.VolFiles     = sdmr.VolFiles;
      mr.VolBlocks    = sdmr.VolBlocks;
      mr.VolBytes     = sdmr.VolBytes;
      mr.VolMounts    = sdmr.VolMounts;
      mr.VolErrors    = sdmr.VolErrors;
      mr.VolWrites    = sdmr.VolWrites;
      mr.Slot         = sdmr.Slot;
      mr.InChanger    = sdmr.InChanger;
      bstrncpy(mr.VolStatus, sdmr.VolStatus, sizeof(mr.VolStatus));
      mr.VolReadTime  = sdmr.VolReadTime;
      mr.VolWriteTime = sdmr.VolWriteTime;

      Dmsg2(400, "db_update_media_record. Stat=%s Vol=%s\n", mr.VolStatus, mr.VolumeName);
      /*
       * Update the database, then before sending the response to the
       *  SD, check if the Volume has expired.
       */
      if (!db_update_media_record(jcr, jcr->db, &mr)) {
         Jmsg(jcr, M_FATAL, 0, _("Catalog error updating Media record. %s"),
            db_strerror(jcr->db));
         bs->fsend(_("1993 Update Media error\n"));
         Dmsg0(400, "send error\n");
      } else {
         (void)has_volume_expired(jcr, &mr);
         send_volume_info_to_storage_daemon(jcr, bs, &mr);
      }

bail_out:
      db_unlock(jcr->db);

      Dmsg1(400, ">CatReq response: %s", bs->msg);
      Dmsg1(400, "Leave catreq jcr 0x%x\n", jcr);
      return;
   /*
    * Request to create a JobMedia record
    */
   } else if (sscanf(bs->msg, Create_job_media, &Job,
      &jm.FirstIndex, &jm.LastIndex, &jm.StartFile, &jm.EndFile,
      &jm.StartBlock, &jm.EndBlock, &Copy, &Stripe, &MediaId) == 10) {

      if (jcr->mig_jcr) {
         jm.JobId = jcr->mig_jcr->JobId;
      } else {
         jm.JobId = jcr->JobId;
      }
      jm.MediaId = MediaId;
      Dmsg6(400, "create_jobmedia JobId=%d MediaId=%d SF=%d EF=%d FI=%d LI=%d\n",
         jm.JobId, jm.MediaId, jm.StartFile, jm.EndFile, jm.FirstIndex, jm.LastIndex);
      if (!db_create_jobmedia_record(jcr, jcr->db, &jm)) {
         Jmsg(jcr, M_FATAL, 0, _("Catalog error creating JobMedia record. %s"),
            db_strerror(jcr->db));
         bs->fsend(_("1992 Create JobMedia error\n"));
      } else {
         Dmsg0(400, "JobMedia record created\n");
         bs->fsend(OK_create);
      }

   } else {
      omsg = get_memory(bs->msglen+1);
      pm_strcpy(omsg, bs->msg);
      bs->fsend(_("1990 Invalid Catalog Request: %s"), omsg);
      Jmsg1(jcr, M_FATAL, 0, _("Invalid Catalog request: %s"), omsg);
      free_memory(omsg);
   }

   Dmsg1(400, ">CatReq response: %s", bs->msg);
   Dmsg1(400, "Leave catreq jcr 0x%x\n", jcr);
   return;
}
コード例 #4
0
ファイル: record_read.c プロジェクト: rkorzeniewski/bacula
/*
 * Read the header record
 */
static bool read_header(DCR *dcr, DEV_BLOCK *block, DEV_RECORD *rec)
{
    ser_declare;
    uint32_t VolSessionId;
    uint32_t VolSessionTime;
    int32_t  FileIndex;
    int32_t  Stream;
    uint32_t rhl;
    char buf1[100], buf2[100];

    Dmsg0(dbgep, "=== rpath 1 read_header\n");
    /* Clear state flags */
    rec->state_bits = 0;
    if (block->dev->is_tape()) {
        rec->state_bits |= REC_ISTAPE;
    }
    rec->Block = ((DEVICE *)block->dev)->EndBlock;
    rec->File = ((DEVICE *)block->dev)->EndFile;

    /*
     * Get the header. There is always a full header,
     * otherwise we find it in the next block.
     */
    Dmsg3(read_dbglvl, "Block=%d Ver=%d block_len=%u\n",
          block->BlockNumber, block->BlockVer, block->block_len);
    if (block->BlockVer == 1) {
        rhl = RECHDR1_LENGTH;
    } else {
        rhl = RECHDR2_LENGTH;
    }
    if (rec->remlen >= rhl) {
        Dmsg0(dbgep, "=== rpath 2 begin unserial header\n");
        Dmsg4(read_dbglvl, "read_header: remlen=%d data_len=%d rem=%d blkver=%d\n",
              rec->remlen, rec->data_len, rec->remainder, block->BlockVer);

        unser_begin(block->bufp, WRITE_RECHDR_LENGTH);
        if (block->BlockVer == 1) {
            unser_uint32(VolSessionId);
            unser_uint32(VolSessionTime);
        } else {
            VolSessionId = block->VolSessionId;
            VolSessionTime = block->VolSessionTime;
        }
        unser_int32(FileIndex);
        unser_int32(Stream);
        unser_uint32(rec->data_bytes);

        block->bufp += rhl;
        block->binbuf -= rhl;
        rec->remlen -= rhl;

        /* If we are looking for more (remainder!=0), we reject anything
         *  where the VolSessionId and VolSessionTime don't agree
         */
        if (rec->remainder && (rec->VolSessionId != VolSessionId ||
                               rec->VolSessionTime != VolSessionTime)) {
            rec->state_bits |= REC_NO_MATCH;
            Dmsg0(read_dbglvl, "remainder and VolSession doesn't match\n");
            Dmsg0(dbgep, "=== rpath 4 VolSession no match\n");
            return false;             /* This is from some other Session */
        }

        /* if Stream is negative, it means that this is a continuation
         * of a previous partially written record.
         */
        if (Stream < 0) {               /* continuation record? */
            Dmsg0(dbgep, "=== rpath 5 negative stream\n");
            Dmsg1(read_dbglvl, "Got negative Stream => continuation. remainder=%d\n",
                  rec->remainder);
            rec->state_bits |= REC_CONTINUATION;
            if (!rec->remainder) {       /* if we didn't read previously */
                Dmsg0(dbgep, "=== rpath 6 no remainder\n");
                rec->data_len = 0;        /* return data as if no continuation */
            } else if (rec->Stream != -Stream) {
                Dmsg0(dbgep, "=== rpath 7 wrong cont stream\n");
                rec->state_bits |= REC_NO_MATCH;
                return false;             /* This is from some other Session */
            }
            rec->Stream = -Stream;       /* set correct Stream */
            rec->maskedStream = rec->Stream & STREAMMASK_TYPE;
        } else {                        /* Regular record */
            Dmsg0(dbgep, "=== rpath 8 normal stream\n");
            rec->Stream = Stream;
            rec->maskedStream = rec->Stream & STREAMMASK_TYPE;
            rec->data_len = 0;           /* transfer to beginning of data */
        }
        rec->VolSessionId = VolSessionId;
        rec->VolSessionTime = VolSessionTime;
        rec->FileIndex = FileIndex;
        if (FileIndex > 0) {
            Dmsg0(dbgep, "=== rpath 9 FileIndex>0\n");
            if (block->FirstIndex == 0) {
                Dmsg0(dbgep, "=== rpath 10 FirstIndex\n");
                block->FirstIndex = FileIndex;
            }
            block->LastIndex = rec->FileIndex;
        }

        Dmsg6(read_dbglvl, "read_header: FI=%s SessId=%d Strm=%s len=%u rec->remlen=%d data_len=%d\n",
              FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId,
              stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_bytes, rec->remlen,
              rec->data_len);
    } else {
        Dmsg0(dbgep, "=== rpath 11a block out of records\n");
        /*
         * No more records in this block because the number
         * of remaining bytes are less than a record header
         * length, so return empty handed, but indicate that
         * he must read again. By returning, we allow the
         * higher level routine to fetch the next block and
         * then reread.
         */
        Dmsg0(read_dbglvl, "read_header: End of block\n");
        rec->state_bits |= (REC_NO_HEADER | REC_BLOCK_EMPTY);
        empty_block(block);                      /* mark block empty */
        return false;
    }

    /* Sanity check */
    if (rec->data_bytes >= MAX_BLOCK_LENGTH) {
        Dmsg0(dbgep, "=== rpath 11b maxlen too big\n");
        /*
         * Something is wrong, force read of next block, abort
         *   continuing with this block.
         */
        rec->state_bits |= (REC_NO_HEADER | REC_BLOCK_EMPTY);
        empty_block(block);
        Jmsg2(dcr->jcr, M_WARNING, 0, _("Sanity check failed. maxlen=%d datalen=%d. Block discarded.\n"),
              MAX_BLOCK_LENGTH, rec->data_bytes);
        return false;
    }

    rec->data = check_pool_memory_size(rec->data, rec->data_len+rec->data_bytes);
    rec->rstate = st_data;
    return true;
}
コード例 #5
0
ファイル: vtape.c プロジェクト: AlD/bareos
/*
 * BSR + EOF => begin of EOF + EIO
 * BSR + BSR + EOF => last block
 * current_block = -1
 */
int vtape::bsr(int count)
{
   ASSERT(online);
   ASSERT(current_file >= 0);
   ASSERT(count == 1);
   ASSERT(fd >= 0);

   check_eof();

   if (!count) {
      return 0;
   }

   int ret=0;
   int last_f=0;
   int last_b=0;

   boffset_t last=-1, last2=-1;
   boffset_t orig = lseek(fd, 0, SEEK_CUR);
   int orig_f = current_file;
   int orig_b = current_block;

   Dmsg4(dbglevel, "bsr(%i) cur_blk=%i orig=%lli cur_FM=%lli\n",
         count, current_block, orig, cur_FM);

   /* begin of tape, do nothing */
   if (atBOT) {
      errno = EIO;
      return -1;
   }

   /* at EOF 0:-1 BOT=0 EOD=0 EOF=0 ERR: Input/output error  */
   if (atEOF) {
      lseek(fd, cur_FM, SEEK_SET);
      atEOF = false;
      if (current_file > 0) {
         current_file--;
      }
      current_block=-1;
      errno = EIO;
      return -1;
   }

   /*
    * First, go to cur/last_FM and read all blocks to find the good one
    */
   if (cur_FM == orig) {        /* already just before  EOF */
      lseek(fd, last_FM, SEEK_SET);

   } else {
      lseek(fd, cur_FM, SEEK_SET);
   }

   ret = read_fm(VT_READ_EOF);

   do {
      if (!atEOF) {
         last2 = last;          /* keep track of the 2 last blocs position */
         last = lseek(fd, 0, SEEK_CUR);
         last_f = current_file;
         last_b = current_block;
         Dmsg6(dbglevel, "EOF=%i last2=%lli last=%lli < orig=%lli %i:%i\n",
               atEOF, last2, last, orig, current_file, current_block);
      }
      ret = fsr(1);
   } while ((lseek(fd, 0, SEEK_CUR) < orig) && (ret == 0));

   if (last2 > 0 && atEOF) {    /* we take the previous position */
      lseek(fd, last2, SEEK_SET);
      current_file = last_f;
      current_block = last_b - 1;
      Dmsg3(dbglevel, "1 set offset2=%lli %i:%i\n",
            last, current_file, current_block);

   } else if (last > 0) {
      lseek(fd, last, SEEK_SET);
      current_file = last_f;
      current_block = last_b;
      Dmsg3(dbglevel, "2 set offset=%lli %i:%i\n",
            last, current_file, current_block);
   } else {
      lseek(fd, orig, SEEK_SET);
      current_file = orig_f;
      current_block = orig_b;
      return -1;
   }

   Dmsg2(dbglevel, "bsr %i:%i\n", current_file, current_block);
   errno=0;
   atEOT = atEOF = atEOD = false;
   atBOT = (lseek(fd, 0, SEEK_CUR) - (sizeof(uint32_t)+2*sizeof(boffset_t))) == 0;

   if (orig_b == -1) {
      current_block = orig_b;
   }

   return 0;
}
コード例 #6
0
ファイル: record.c プロジェクト: wisre/bareos
/*
 * Read a Record from the block
 *
 * Returns: false if nothing read or if the continuation record does not match.
 *                In both of these cases, a block read must be done.
 *          true  if at least the record header was read, this
 *                routine may have to be called again with a new
 *                block if the entire record was not read.
 */
bool read_record_from_block(DCR *dcr, DEV_RECORD *rec)
{
   ser_declare;
   uint32_t remlen;
   uint32_t VolSessionId;
   uint32_t VolSessionTime;
   int32_t  FileIndex;
   int32_t  Stream;
   uint32_t data_bytes;
   uint32_t rhl;
   char buf1[100], buf2[100];

   remlen = dcr->block->binbuf;

   /*
    * Clear state flags
    */
   clear_all_bits(REC_STATE_MAX, rec->state_bits);
   if (dcr->block->dev->is_tape()) {
      set_bit(REC_ISTAPE, rec->state_bits);
   }
   rec->Block = ((DEVICE *)(dcr->block->dev))->EndBlock;
   rec->File = ((DEVICE *)(dcr->block->dev))->EndFile;

   /*
    * Get the header. There is always a full header, otherwise we find it in the next block.
    */
   Dmsg3(450, "Block=%d Ver=%d size=%u\n", dcr->block->BlockNumber, dcr->block->BlockVer,
         dcr->block->block_len);
   if (dcr->block->BlockVer == 1) {
      rhl = RECHDR1_LENGTH;
   } else {
      rhl = RECHDR2_LENGTH;
   }
   if (remlen >= rhl) {
      Dmsg4(450, "Enter read_record_block: remlen=%d data_len=%d rem=%d blkver=%d\n",
            remlen, rec->data_len, rec->remainder, dcr->block->BlockVer);

      unser_begin(dcr->block->bufp, WRITE_RECHDR_LENGTH);
      if (dcr->block->BlockVer == 1) {
         unser_uint32(VolSessionId);
         unser_uint32(VolSessionTime);
      } else {
         VolSessionId = dcr->block->VolSessionId;
         VolSessionTime = dcr->block->VolSessionTime;
      }
      unser_int32(FileIndex);
      unser_int32(Stream);
      unser_uint32(data_bytes);

      dcr->block->bufp += rhl;
      dcr->block->binbuf -= rhl;
      remlen -= rhl;

      /*
       * If we are looking for more (remainder!=0), we reject anything
       * where the VolSessionId and VolSessionTime don't agree
       */
      if (rec->remainder && (rec->VolSessionId != VolSessionId ||
                             rec->VolSessionTime != VolSessionTime)) {
         set_bit(REC_NO_MATCH, rec->state_bits);
         Dmsg0(450, "remainder and VolSession doesn't match\n");
         return false;             /* This is from some other Session */
      }

      /*
       * If Stream is negative, it means that this is a continuation
       * of a previous partially written record.
       */
      if (Stream < 0) {               /* continuation record? */
         Dmsg1(500, "Got negative Stream => continuation. remainder=%d\n", rec->remainder);
         set_bit(REC_CONTINUATION, rec->state_bits);
         if (!rec->remainder) {       /* if we didn't read previously */
            rec->data_len = 0;        /* return data as if no continuation */
         } else if (rec->Stream != -Stream) {
            set_bit(REC_NO_MATCH, rec->state_bits);
            return false;             /* This is from some other Session */
         }
         rec->Stream = -Stream;       /* set correct Stream */
         rec->maskedStream = rec->Stream & STREAMMASK_TYPE;
      } else {                        /* Regular record */
         rec->Stream = Stream;
         rec->maskedStream = rec->Stream & STREAMMASK_TYPE;
         rec->data_len = 0;           /* transfer to beginning of data */
      }
      rec->VolSessionId = VolSessionId;
      rec->VolSessionTime = VolSessionTime;
      rec->FileIndex = FileIndex;
      if (FileIndex > 0) {
         if (dcr->block->FirstIndex == 0) {
            dcr->block->FirstIndex = FileIndex;
         }
         dcr->block->LastIndex = FileIndex;
      }

      Dmsg6(450, "rd_rec_blk() got FI=%s SessId=%d Strm=%s len=%u\n"
                 "remlen=%d data_len=%d\n",
         FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId,
         stream_to_ascii(buf2, rec->Stream, rec->FileIndex), data_bytes, remlen,
         rec->data_len);
   } else {
      /*
       * No more records in this block because the number
       * of remaining bytes are less than a record header
       * length, so return empty handed, but indicate that
       * he must read again. By returning, we allow the
       * higher level routine to fetch the next block and
       * then reread.
       */
      Dmsg0(450, "read_record_block: nothing\n");
      set_bit(REC_NO_HEADER, rec->state_bits);
      set_bit(REC_BLOCK_EMPTY, rec->state_bits);
      empty_block(dcr->block);                 /* mark block empty */
      return false;
   }

   /* Sanity check */
   if (data_bytes >= MAX_BLOCK_LENGTH) {
      /*
       * Something is wrong, force read of next block, abort
       *   continuing with this block.
       */
      set_bit(REC_NO_HEADER, rec->state_bits);
      set_bit(REC_BLOCK_EMPTY, rec->state_bits);
      empty_block(dcr->block);
      Jmsg2(dcr->jcr, M_WARNING, 0, _("Sanity check failed. maxlen=%d datalen=%d. Block discarded.\n"),
         MAX_BLOCK_LENGTH, data_bytes);
      return false;
   }

   rec->data = check_pool_memory_size(rec->data, rec->data_len + data_bytes);

   /*
    * At this point, we have read the header, now we
    * must transfer as much of the data record as
    * possible taking into account: 1. A partial
    * data record may have previously been transferred,
    * 2. The current block may not contain the whole data
    * record.
    */
   if (remlen >= data_bytes) {
      /*
       * Got whole record
       */
      memcpy(rec->data+rec->data_len, dcr->block->bufp, data_bytes);
      dcr->block->bufp += data_bytes;
      dcr->block->binbuf -= data_bytes;
      rec->data_len += data_bytes;
   } else {
      /*
       * Partial record
       */
      memcpy(rec->data+rec->data_len, dcr->block->bufp, remlen);
      dcr->block->bufp += remlen;
      dcr->block->binbuf -= remlen;
      rec->data_len += remlen;
      rec->remainder = 1;             /* partial record transferred */
      Dmsg1(450, "read_record_block: partial xfered=%d\n", rec->data_len);
      set_bit(REC_PARTIAL_RECORD, rec->state_bits);
      set_bit(REC_BLOCK_EMPTY, rec->state_bits);
      return true;
   }
   rec->remainder = 0;

   Dmsg4(450, "Rtn full rd_rec_blk FI=%s SessId=%d Strm=%s len=%d\n",
         FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId,
         stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len);

   return true;                       /* transferred full record */
}
コード例 #7
0
ファイル: sd_cmds.c プロジェクト: engeenity/bareos
/*
 * We get the slot list from the Storage daemon.
 *  If listall is set we run an 'autochanger listall' cmd
 *  otherwise an 'autochanger list' cmd
 *  If scan is set and listall is not, we return all slots found,
 *  otherwise, we return only slots with valid barcodes (Volume names)
 *
 * Input (output of mxt-changer list):
 *
 * 0:vol2                Slot num:Volume Name
 *
 * Input (output of mxt-changer listall):
 *
 * Drive content:         D:Drive num:F:Slot loaded:Volume Name
 * D:0:F:2:vol2        or D:Drive num:E
 * D:1:F:42:vol42
 * D:3:E
 *
 * Slot content:
 * S:1:F:vol1             S:Slot num:F:Volume Name
 * S:2:E               or S:Slot num:E
 * S:3:F:vol4
 *
 * Import/Export tray slots:
 * I:10:F:vol10           I:Slot num:F:Volume Name
 * I:11:E              or I:Slot num:E
 * I:12:F:vol40
 *
 * If a drive is loaded, the slot *should* be empty
 */
dlist *get_vol_list_from_SD(UAContext *ua, STORERES *store, bool listall, bool scan)
{
   int nr_fields;
   char *bp;
   char dev_name[MAX_NAME_LENGTH];
   char *field1, *field2, *field3, *field4, *field5;
   vol_list_t *vl = NULL;
   dlist *vol_list;
   BSOCK *sd = NULL;

   if (!(sd = open_sd_bsock(ua))) {
      return NULL;
   }

   bstrncpy(dev_name, store->dev_name(), sizeof(dev_name));
   bash_spaces(dev_name);

   /*
    * Ask for autochanger list of volumes
    */
   if (listall) {
      sd->fsend(changerlistallcmd , dev_name);
   } else {
      sd->fsend(changerlistcmd, dev_name);
   }

   vol_list = New(dlist(vl, &vl->link));

   /*
    * Read and organize list of Volumes
    */
   while (bnet_recv(sd) >= 0) {
      strip_trailing_junk(sd->msg);

      /*
       * Check for returned SD messages
       */
      if (sd->msg[0] == '3' && B_ISDIGIT(sd->msg[1]) &&
          B_ISDIGIT(sd->msg[2]) && B_ISDIGIT(sd->msg[3]) &&
          sd->msg[4] == ' ') {
         ua->send_msg("%s\n", sd->msg);   /* pass them on to user */
         continue;
      }

      /*
       * Parse the message. list gives max 2 fields listall max 5.
       * We always make sure all fields are initialized to either
       * a value or NULL.
       *
       * For autochanger list the following mapping is used:
       * - field1 == slotnr
       * - field2 == volumename
       *
       * For autochanger listall the following mapping is used:
       * - field1 == type
       * - field2 == slotnr
       * - field3 == content (E for Empty, F for Full)
       * - field4 == loaded (loaded slot if type == D)
       * - field4 == volumename (if type == S or I)
       * - field5 == volumename (if type == D)
       */
      field1 = sd->msg;
      field2 = strchr(sd->msg, ':');
      if (field2) {
         *field2++ = '\0';
         if (listall) {
            field3 = strchr(field2, ':');
            if (field3) {
               *field3++ = '\0';
               field4 = strchr(field3, ':');
               if (field4) {
                  *field4++ = '\0';
                  field5 = strchr(field4, ':');
                  if (field5) {
                     *field5++ = '\0';
                     nr_fields = 5;
                  } else {
                     nr_fields = 4;
                  }
               } else {
                  nr_fields = 3;
                  field5 = NULL;
               }
            } else {
               nr_fields = 2;
               field4 = NULL;
               field5 = NULL;
            }
         } else {
            nr_fields = 2;
            field3 = NULL;
            field4 = NULL;
            field5 = NULL;
         }
      } else {
         nr_fields = 1;
         field3 = NULL;
         field4 = NULL;
         field5 = NULL;
      }

      /*
       * See if this is a parsable string from either list or listall
       * e.g. at least f1:f2
       */
      if (!field1 && !field2) {
         goto parse_error;
      }

      vl = (vol_list_t *)malloc(sizeof(vol_list_t));
      memset(vl, 0, sizeof(vol_list_t));

      if (scan && !listall) {
         /*
          * Scanning -- require only valid slot
          */
         vl->Slot = atoi(field1);
         if (vl->Slot <= 0) {
            ua->error_msg(_("Invalid Slot number: %s\n"), sd->msg);
            free(vl);
            continue;
         }

         vl->Type = slot_type_normal;
         if (strlen(field2) > 0) {
            vl->Content = slot_content_full;
            vl->VolName = bstrdup(field2);
         } else {
            vl->Content = slot_content_empty;
         }
         vl->Index = INDEX_SLOT_OFFSET + vl->Slot;
      } else if (!listall) {
         /*
          * Not scanning and not listall.
          */
         if (strlen(field2) == 0) {
            free(vl);
            continue;
         }

         if (!is_an_integer(field1) || (vl->Slot = atoi(field1)) <= 0) {
            ua->error_msg(_("Invalid Slot number: %s\n"), field1);
            free(vl);
            continue;
         }

         if (!is_volume_name_legal(ua, field2)) {
            ua->error_msg(_("Invalid Volume name: %s\n"), field2);
            free(vl);
            continue;
         }

         vl->Type = slot_type_normal;
         vl->Content = slot_content_full;
         vl->VolName = bstrdup(field2);
         vl->Index = INDEX_SLOT_OFFSET + vl->Slot;
      } else {
         /*
          * Listall.
          */
         if (!field3) {
            goto parse_error;
         }

         switch (*field1) {
         case 'D':
            vl->Type = slot_type_drive;
            break;
         case 'S':
            vl->Type = slot_type_normal;
            break;
         case 'I':
            vl->Type = slot_type_import;
            break;
         default:
            vl->Type = slot_type_unknown;
            break;
         }

         /*
          * For drives the Slot is the actual drive number.
          * For any other type its the actual slot number.
          */
         switch (vl->Type) {
         case slot_type_drive:
            if (!is_an_integer(field2) || (vl->Slot = atoi(field2)) < 0) {
               ua->error_msg(_("Invalid Drive number: %s\n"), field2);
               free(vl);
               continue;
            }
            vl->Index = INDEX_DRIVE_OFFSET + vl->Slot;
            if (vl->Index >= INDEX_MAX_DRIVES) {
               ua->error_msg(_("Drive number %d greater then INDEX_MAX_DRIVES(%d) please increase define\n"),
                             vl->Slot, INDEX_MAX_DRIVES);
               free(vl);
               continue;
            }
            break;
         default:
            if (!is_an_integer(field2) || (vl->Slot = atoi(field2)) <= 0) {
               ua->error_msg(_("Invalid Slot number: %s\n"), field2);
               free(vl);
               continue;
            }
            vl->Index = INDEX_SLOT_OFFSET + vl->Slot;
            break;
         }

         switch (*field3) {
         case 'E':
            vl->Content = slot_content_empty;
            break;
         case 'F':
            vl->Content = slot_content_full;
            switch (vl->Type) {
            case slot_type_normal:
            case slot_type_import:
               if (field4) {
                  vl->VolName = bstrdup(field4);
               }
               break;
            case slot_type_drive:
               if (field4) {
                  vl->Loaded = atoi(field4);
               }
               if (field5) {
                  vl->VolName = bstrdup(field5);
               }
               break;
            default:
               break;
            }
            break;
         default:
            vl->Content = slot_content_unknown;
            break;
         }
      }

      if (vl->VolName) {
         Dmsg6(100, "Add index = %d slot=%d loaded=%d type=%d content=%d Vol=%s to SD list.\n",
               vl->Index, vl->Slot, vl->Loaded, vl->Type, vl->Content, NPRT(vl->VolName));
      } else {
         Dmsg5(100, "Add index = %d slot=%d loaded=%d type=%d content=%d Vol=NULL to SD list.\n",
               vl->Index, vl->Slot, vl->Loaded, vl->Type, vl->Content);
      }

      vol_list->binary_insert(vl, compare_vol_list_entry);
      continue;

parse_error:
      /*
       * We encountered a parse error, see how many replacements
       * we done of ':' with '\0' by looking at the nr_fields
       * variable and undo those. Number of undo's are nr_fields - 1
       */
      while (nr_fields > 1 && (bp = strchr(sd->msg, '\0')) != NULL) {
         *bp = ':';
         nr_fields--;
      }
      ua->error_msg(_("Illegal output from autochanger %s: %s\n"),
                   (listall) ? _("listall") : _("list"), sd->msg);
      free(vl);
      continue;
   }

   close_sd_bsock(ua);

   if (vol_list->size() == 0) {
      delete vol_list;
      vol_list = NULL;
   }

   return vol_list;
}
コード例 #8
0
ファイル: dvd.c プロジェクト: anarexia/bacula
/*
 * Open the next part file.
 *  - Close the fd
 *  - Increment part number 
 *  - Reopen the device
 */
int dvd_open_next_part(DCR *dcr)
{
   DEVICE *dev = dcr->dev;

   Dmsg6(29, "Enter: == open_next_part part=%d npart=%d dev=%s vol=%s mode=%d file_addr=%d\n", 
      dev->part, dev->num_dvd_parts, dev->print_name(),
         dev->getVolCatName(), dev->openmode, dev->file_addr);
   if (!dev->is_dvd()) {
      Dmsg1(100, "Device %s is not dvd!!!!\n", dev->print_name()); 
      return -1;
   }
   
   /* When appending, do not open a new part if the current is empty */
   if (dev->can_append() && (dev->part > dev->num_dvd_parts) && 
       (dev->part_size == 0)) {
      Dmsg0(29, "open_next_part exited immediately (dev->part_size == 0).\n");
      return dev->fd();
   }

   dev->close_part(dcr);               /* close current part */
   
   /*
    * If we have a spooled part open, write it to the
    *  DVD before opening the next part.
    */
   if (dev->is_part_spooled()) {
      Dmsg2(100, "Before open next write previous. part=%d num_parts=%d\n",
         dev->part, dev->num_dvd_parts);
      if (!dvd_write_part(dcr)) {
         Dmsg0(29, "Error in dvd_write part.\n");
         return -1;
      }
   }
     
   dev->part_start += dev->part_size;
   dev->part++;
   Dmsg2(29, "Inc part=%d num_dvd_parts=%d\n", dev->part, dev->num_dvd_parts);

   /* Are we working on a part past what is written in the DVD? */
   if (dev->num_dvd_parts < dev->part) {
      POOL_MEM archive_name(PM_FNAME);
      struct stat buf;
      /* 
       * First check what is on DVD.  If our part is there, we
       *   are in trouble, so bail out.
       * NB: This is however not a problem if we are writing the first part.
       * It simply means that we are over writing an existing volume...
       */
      if (dev->num_dvd_parts > 0) {
         make_mounted_dvd_filename(dev, archive_name);   /* makes dvd name */
         Dmsg1(100, "Check if part on DVD: %s\n", archive_name.c_str());
         if (stat(archive_name.c_str(), &buf) == 0) {
            /* bad news bail out */
            dev->set_part_spooled(false);
            Mmsg1(&dev->errmsg, _("Next Volume part already exists on DVD. Cannot continue: %s\n"),
               archive_name.c_str());
            return -1;
         }
      }

#ifdef neeeded
      Dmsg2(400, "num_dvd_parts=%d part=%d\n", dev->num_dvd_parts, dev->part);
      make_spooled_dvd_filename(dev, archive_name);   /* makes spool name */
      
      /* Check if the next part exists in spool directory . */
      Dmsg1(100, "Check if part on spool: %s\n", archive_name.c_str());
      if ((stat(archive_name.c_str(), &buf) == 0) || (errno != ENOENT)) {
         Dmsg1(29, "======= Part %s is in the way, deleting it...\n", archive_name.c_str());
         /* Then try to unlink it */
         if (unlink(archive_name.c_str()) < 0) {
            berrno be;
            dev->set_part_spooled(false);
            dev->dev_errno = errno;
            Mmsg2(dev->errmsg, _("open_next_part can't unlink existing part %s, ERR=%s\n"), 
                   archive_name.c_str(), be.bstrerror());
            return -1;
         }
      }
#endif
   }

   Dmsg2(400, "Call dev->open(vol=%s, mode=%d)\n", dcr->getVolCatName(), 
         dev->openmode);

   /* Open next part.  Note, this sets part_size for part opened. */
   if (dev->open(dcr, OPEN_READ_ONLY) < 0) {
      return -1;
   } 
   dev->set_labeled();                   /* all next parts are "labeled" */
   
   return dev->fd();
}
コード例 #9
0
ファイル: ua_label.c プロジェクト: s-seitz/bareos
/*
 * NOTE! This routine opens the SD socket but leaves it open
 */
static bool send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr,
                               POOL_DBR *pr, bool relabel, bool media_record_exists,
                               int drive)
{
   BSOCK *sd;
   char dev_name[MAX_NAME_LENGTH];
   bool ok = false;
   uint64_t VolBytes = 0;

   if (!(sd=open_sd_bsock(ua))) {
      return false;
   }

   bstrncpy(dev_name, ua->jcr->res.wstore->dev_name(), sizeof(dev_name));
   bash_spaces(dev_name);
   bash_spaces(mr->VolumeName);
   bash_spaces(mr->MediaType);
   bash_spaces(pr->Name);
   if (relabel) {
      bash_spaces(omr->VolumeName);
      sd->fsend("relabel %s OldName=%s NewName=%s PoolName=%s "
                     "MediaType=%s Slot=%d drive=%d",
                 dev_name, omr->VolumeName, mr->VolumeName, pr->Name,
                 mr->MediaType, mr->Slot, drive);
      ua->send_msg(_("Sending relabel command from \"%s\" to \"%s\" ...\n"),
         omr->VolumeName, mr->VolumeName);
   } else {
      sd->fsend("label %s VolumeName=%s PoolName=%s MediaType=%s "
                     "Slot=%d drive=%d",
                 dev_name, mr->VolumeName, pr->Name, mr->MediaType,
                 mr->Slot, drive);
      ua->send_msg(_("Sending label command for Volume \"%s\" Slot %d ...\n"),
         mr->VolumeName, mr->Slot);
      Dmsg6(100, "label %s VolumeName=%s PoolName=%s MediaType=%s Slot=%d drive=%d\n",
         dev_name, mr->VolumeName, pr->Name, mr->MediaType, mr->Slot, drive);
   }

   /*
    * We use bget_dirmsg here and not bnet_recv because as part of
    * the label request the stored can request catalog information for
    * any plugin who listens to the bsdEventLabelVerified event.
    * As we don't want to loose any non protocol data e.g. errors
    * without a 3xxx prefix we set the allow_any_message of
    * bget_dirmsg to true and as such is behaves like a normal
    * bnet_recv for any non protocol messages.
    */
   while (bget_dirmsg(sd, true) >= 0) {
      ua->send_msg("%s", sd->msg);
      if (sscanf(sd->msg, "3000 OK label. VolBytes=%llu ", &VolBytes) == 1) {
         ok = true;
      }
   }

   unbash_spaces(mr->VolumeName);
   unbash_spaces(mr->MediaType);
   unbash_spaces(pr->Name);
   mr->LabelDate = time(NULL);
   mr->set_label_date = true;

   if (ok) {
      if (media_record_exists) {      /* we update it */
         mr->VolBytes = VolBytes;
         mr->InChanger = mr->Slot > 0;  /* if slot give assume in changer */
         set_storageid_in_mr(ua->jcr->res.wstore, mr);
         if (!db_update_media_record(ua->jcr, ua->db, mr)) {
             ua->error_msg("%s", db_strerror(ua->db));
             ok = false;
         }
      } else {                        /* create the media record */
         set_pool_dbr_defaults_in_media_dbr(mr, pr);
         mr->VolBytes = VolBytes;
         mr->InChanger = mr->Slot > 0;  /* if slot give assume in changer */
         mr->Enabled = 1;
         set_storageid_in_mr(ua->jcr->res.wstore, mr);
         if (db_create_media_record(ua->jcr, ua->db, mr)) {
            ua->info_msg(_("Catalog record for Volume \"%s\", Slot %d  successfully created.\n"),
            mr->VolumeName, mr->Slot);
            /*
             * Update number of volumes in pool
             */
            pr->NumVols++;
            if (!db_update_pool_record(ua->jcr, ua->db, pr)) {
               ua->error_msg("%s", db_strerror(ua->db));
            }
         } else {
            ua->error_msg("%s", db_strerror(ua->db));
            ok = false;
         }
      }
   } else {
      ua->error_msg(_("Label command failed for Volume %s.\n"), mr->VolumeName);
   }

   return ok;
}
コード例 #10
0
ファイル: label.c プロジェクト: janstadler/bareos
/* Write session label
 *  Returns: false on failure
 *           true  on success
 */
bool write_session_label(DCR *dcr, int label)
{
   JCR *jcr = dcr->jcr;
   DEVICE *dev = dcr->dev;
   DEV_RECORD *rec;
   DEV_BLOCK *block = dcr->block;
   char buf1[100], buf2[100];

   rec = new_record();
   Dmsg1(130, "session_label record=%x\n", rec);
   switch (label) {
   case SOS_LABEL:
      set_start_vol_position(dcr);
      break;
   case EOS_LABEL:
      if (dev->is_tape()) {
         dcr->EndBlock = dev->EndBlock;
         dcr->EndFile  = dev->EndFile;
      } else {
         dcr->EndBlock = (uint32_t)dev->file_addr;
         dcr->EndFile = (uint32_t)(dev->file_addr >> 32);
      }
      break;
   default:
      Jmsg1(jcr, M_ABORT, 0, _("Bad Volume session label = %d\n"), label);
      break;
   }
   create_session_label(dcr, rec, label);
   rec->FileIndex = label;

   /*
    * We guarantee that the session record can totally fit
    *  into a block. If not, write the block, and put it in
    *  the next block. Having the sesssion record totally in
    *  one block makes reading them much easier (no need to
    *  read the next block).
    */
   if (!can_write_record_to_block(block, rec)) {
      Dmsg0(150, "Cannot write session label to block.\n");
      if (!dcr->write_block_to_device()) {
         Dmsg0(130, "Got session label write_block_to_dev error.\n");
         free_record(rec);
         return false;
      }
   }
   if (!write_record_to_block(dcr, rec)) {
      free_record(rec);
      return false;
   }

   Dmsg6(150, "Write sesson_label record JobId=%d FI=%s SessId=%d Strm=%s len=%d "
             "remainder=%d\n", jcr->JobId,
      FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId,
      stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len,
      rec->remainder);

   free_record(rec);
   Dmsg2(150, "Leave write_session_label Block=%ud File=%ud\n",
      dev->get_block_num(), dev->get_file());
   return true;
}
コード例 #11
0
ファイル: ua_label.c プロジェクト: halgandd/bacula
/*
 * NOTE! This routine opens the SD socket but leaves it open
 */
static bool send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr,
                               POOL_DBR *pr, int relabel, bool media_record_exists,
                               int drive)
{
   BSOCK *sd;
   char dev_name[MAX_NAME_LENGTH];
   bool ok = false;
   bool is_dvd = false;
   uint64_t VolBytes = 0;

   if (!(sd=open_sd_bsock(ua))) {
      return false;
   }
   bstrncpy(dev_name, ua->jcr->wstore->dev_name(), sizeof(dev_name));
   bash_spaces(dev_name);
   bash_spaces(mr->VolumeName);
   bash_spaces(mr->MediaType);
   bash_spaces(pr->Name);
   if (relabel) {
      bash_spaces(omr->VolumeName);
      sd->fsend("relabel %s OldName=%s NewName=%s PoolName=%s "
                     "MediaType=%s Slot=%d drive=%d",
                 dev_name, omr->VolumeName, mr->VolumeName, pr->Name, 
                 mr->MediaType, mr->Slot, drive);
      ua->send_msg(_("Sending relabel command from \"%s\" to \"%s\" ...\n"),
         omr->VolumeName, mr->VolumeName);
   } else {
      sd->fsend("label %s VolumeName=%s PoolName=%s MediaType=%s "
                     "Slot=%d drive=%d",
                 dev_name, mr->VolumeName, pr->Name, mr->MediaType, 
                 mr->Slot, drive);
      ua->send_msg(_("Sending label command for Volume \"%s\" Slot %d ...\n"),
         mr->VolumeName, mr->Slot);
      Dmsg6(100, "label %s VolumeName=%s PoolName=%s MediaType=%s Slot=%d drive=%d\n",
         dev_name, mr->VolumeName, pr->Name, mr->MediaType, mr->Slot, drive);
   }

   while (sd->recv() >= 0) {
      int dvd;
      ua->send_msg("%s", sd->msg);
      if (sscanf(sd->msg, "3000 OK label. VolBytes=%llu DVD=%d ", &VolBytes,
                 &dvd) == 2) {
         is_dvd = dvd;
         ok = true;
      }
   }
   unbash_spaces(mr->VolumeName);
   unbash_spaces(mr->MediaType);
   unbash_spaces(pr->Name);
   mr->LabelDate = time(NULL);
   mr->set_label_date = true;
   if (is_dvd) {
      /* We know that a freshly labelled DVD has 1 VolParts */
      /* This does not apply to auto-labelled DVDs. */
      mr->VolParts = 1;
   }
   if (ok) {
      if (media_record_exists) {      /* we update it */
         mr->VolBytes = VolBytes;
         mr->InChanger = mr->Slot > 0;  /* if slot give assume in changer */
         mr->StorageId = ua->jcr->wstore->StorageId;
         if (!db_update_media_record(ua->jcr, ua->db, mr)) {
             ua->error_msg("%s", db_strerror(ua->db));
             ok = false;
         }
      } else {                        /* create the media record */
         set_pool_dbr_defaults_in_media_dbr(mr, pr);
         mr->VolBytes = VolBytes;
         mr->InChanger = mr->Slot > 0;  /* if slot give assume in changer */
         mr->StorageId = ua->jcr->wstore->StorageId;
         mr->Enabled = 1;
         if (db_create_media_record(ua->jcr, ua->db, mr)) {
            ua->info_msg(_("Catalog record for Volume \"%s\", Slot %d  successfully created.\n"),
            mr->VolumeName, mr->Slot);
            /* Update number of volumes in pool */
            pr->NumVols++;
            if (!db_update_pool_record(ua->jcr, ua->db, pr)) {
               ua->error_msg("%s", db_strerror(ua->db));
            }
         } else {
            ua->error_msg("%s", db_strerror(ua->db));
            ok = false;
         }
      }
   } else {
      ua->error_msg(_("Label command failed for Volume %s.\n"), mr->VolumeName);
   }
   return ok;
}
コード例 #12
0
ファイル: record.c プロジェクト: aussendorf/bareos
/*
 * Write a Record to the block
 *
 *  Returns: false on failure (none or partially written)
 *           true  on success (all bytes written)
 *
 *  and remainder returned in packet.
 *
 *  We require enough room for the header, and we deal with
 *  two special cases. 1. Only part of the record may have
 *  been transferred the last time (when remainder is
 *  non-zero), and 2. The remaining bytes to write may not
 *  all fit into the block.
 */
bool write_record_to_block(DCR *dcr, DEV_RECORD *rec)
{
   bool retval = false;
   char buf1[100], buf2[100];
   DEV_BLOCK *block = dcr->block;

   /*
    * After this point the record is in nrec not rec e.g. its either converted
    * or is just a pointer to the same as the rec pointer being passed in.
    */

   while (1) {
      ASSERT(block->binbuf == (uint32_t)(block->bufp - block->buf));
      ASSERT(block->buf_len >= block->binbuf);

      Dmsg6(890, "write_record_to_block() FI=%s SessId=%d Strm=%s len=%d\n"
            "rem=%d remainder=%d\n",
            FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId,
            stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len,
            rec->remlen, rec->remainder);

      switch (rec->state) {
      case st_none:
         /*
          * Figure out what to do
          */
         rec->state = st_header;
         continue;              /* go to next state */

      case st_header:
         /*
          * Write header
          *
          * If rec->remainder is non-zero, we have been called a
          * second (or subsequent) time to finish writing a record
          * that did not previously fit into the block.
          */
          if (!write_header_to_block(block, rec)) {
             goto bail_out;      /* write block then come back here */
          }
          rec->state = st_data;  /* after header, now write data */
          continue;

      /*
       * Write continuation header
       */
      case st_header_cont:
         write_continue_header_to_block(block, rec);
         rec->state = st_data;
         if (rec->remlen == 0) {
            goto bail_out;       /* Partial transfer */
         }
         continue;

      /*
       * Write normal data
       */
      case st_data:
         /*
          * Write data
          *
          * Part of it may have already been transferred, and we
          * may not have enough room to transfer the whole this time.
          */
         if (rec->remainder > 0) {
            if (!write_data_to_block(block, rec)) {
               rec->state = st_header_cont;
               goto bail_out;
            }
         }
         rec->remainder = 0;               /* did whole transfer */
         rec->state = st_none;
         retval = true;
         goto bail_out;

      default:
         Dmsg0(000, "Something went wrong. Default state.\n");
         rec->state = st_none;
         retval = true;
         goto bail_out;
      }
   }

bail_out:
   return retval;
}