/* Free a memory buffer */ void sm_free_pool_memory(const char *fname, int lineno, POOLMEM *obuf) { struct abufhead *buf; int pool; ASSERT(obuf); P(mutex); buf = (struct abufhead *)((char *)obuf - HEAD_SIZE); pool = buf->pool; pool_ctl[pool].in_use--; if (pool == 0) { free((char *)buf); /* free nonpooled memory */ } else { /* otherwise link it to the free pool chain */ /* Disabled because it hangs in #5507 */ #ifdef xDEBUG struct abufhead *next; /* Don't let him free the same buffer twice */ for (next=pool_ctl[pool].free_buf; next; next=next->next) { if (next == buf) { Dmsg4(dbglvl, "free_pool_memory %p pool=%d from %s:%d\n", buf, pool, fname, lineno); Dmsg4(dbglvl, "bad free_pool_memory %p pool=%d from %s:%d\n", buf, pool, fname, lineno); V(mutex); /* unblock the pool */ ASSERT(next != buf); /* attempt to free twice */ } } #endif buf->next = pool_ctl[pool].free_buf; pool_ctl[pool].free_buf = buf; } Dmsg4(dbglvl, "free_pool_memory %p pool=%d from %s:%d\n", buf, pool, fname, lineno); V(mutex); }
/* * Set the inchanger flag to zero for each slot marked in * the given slot_list. * * The vol_list passed here needs to be from an "autochanger listall" cmd. */ void update_inchanger_for_export(UAContext *ua, STORERES *store, dlist *vol_list, char *slot_list) { vol_list_t *vl; MEDIA_DBR mr; if (!open_client_db(ua)) { return; } /* * Walk through the list updating the media records */ foreach_dlist(vl, vol_list) { /* * We are only interested in normal slots. */ switch (vl->Type) { case slot_type_normal: break; default: continue; } /* * Only update entries of slots marked in the slot_list. */ if (!bit_is_set(vl->Slot - 1, slot_list)) { continue; } /* * Set InChanger to zero for this Slot */ memset(&mr, 0, sizeof(mr)); mr.Slot = vl->Slot; mr.InChanger = 1; mr.MediaId = 0; /* Get by VolumeName */ if (vl->VolName) { bstrncpy(mr.VolumeName, vl->VolName, sizeof(mr.VolumeName)); } else { mr.VolumeName[0] = 0; } set_storageid_in_mr(store, &mr); Dmsg4(100, "Before make unique: Vol=%s slot=%d inchanger=%d sid=%d\n", mr.VolumeName, mr.Slot, mr.InChanger, mr.StorageId); db_lock(ua->db); /* * Set InChanger to zero for this Slot */ db_make_inchanger_unique(ua->jcr, ua->db, &mr); db_unlock(ua->db); Dmsg4(100, "After make unique: Vol=%s slot=%d inchanger=%d sid=%d\n", mr.VolumeName, mr.Slot, mr.InChanger, mr.StorageId); } return; }
void *sm_realloc(const char *fname, int lineno, void *ptr, unsigned int size) { unsigned osize; void *buf; char *cp = (char *) ptr; Dmsg4(DT_MEMORY|50, "sm_realloc %s:%d %p %d\n", get_basename(fname), (uint32_t)lineno, ptr, size); if (size <= 0) { e_msg(fname, lineno, M_ABORT, 0, _("sm_realloc size: %d\n"), size); } /* If the old block pointer is NULL, treat realloc() as a malloc(). SVID is silent on this, but many C libraries permit this. */ if (ptr == NULL) { return sm_malloc(fname, lineno, size); } /* If the old and new sizes are the same, be a nice guy and just return the buffer passed in. */ cp -= HEAD_SIZE; struct abufhead *head = (struct abufhead *)cp; osize = head->ablen - (HEAD_SIZE + 1); if (size == osize) { return ptr; } /* Sizes differ. Allocate a new buffer of the requested size. If we can't obtain such a buffer, act as defined in SVID: return NULL from realloc() and leave the buffer in PTR intact. */ // sm_buffers--; // sm_bytes -= head->ablen; if ((buf = smalloc(fname, lineno, size)) != NULL) { memcpy(buf, ptr, (int)sm_min(size, osize)); /* If the new buffer is larger than the old, fill the balance of it with "designer garbage". */ if (size > osize) { memset(((char *) buf) + osize, 0x55, (int) (size - osize)); } /* All done. Free and dechain the original buffer. */ sm_free(fname, lineno, ptr); } Dmsg4(DT_MEMORY|60, _("sm_realloc %d at %p from %s:%d\n"), size, buf, get_basename(fname), (uint32_t)lineno); return buf; }
/* * TODO: Check fsr with EOF */ int vtape::fsr(int count) { ASSERT(online); ASSERT(current_file >= 0); ASSERT(fd >= 0); int i,nb, ret=0; // boffset_t where=0; uint32_t s; Dmsg4(dbglevel, "fsr %i:%i EOF=%i c=%i\n", current_file,current_block,atEOF,count); check_eof(); if (atEOT) { errno = EIO; current_block = -1; return -1; } if (atEOD) { errno = EIO; return -1; } atBOT = atEOF = false; /* check all block record */ for(i=0; (i < count) && !atEOF ; i++) { nb = ::read(fd, &s, sizeof(uint32_t)); /* get size of next block */ if (nb == sizeof(uint32_t) && s) { current_block++; lseek(fd, s, SEEK_CUR); /* seek after this block */ } else { Dmsg4(dbglevel, "read EOF %i:%i nb=%i s=%i\n", current_file, current_block, nb,s); errno = EIO; ret = -1; if (next_FM) { current_file++; read_fm(VT_SKIP_EOF); } atEOF = true; /* stop the loop */ } } return ret; }
static inline int ndmp_wait_for_job_termination(JCR *jcr) { jcr->setJobStatus(JS_Running); /* * Force cancel in SD if failing, but not for Incomplete jobs * so that we let the SD despool. */ Dmsg4(100, "cancel=%d FDJS=%d JS=%d SDJS=%d\n", jcr->is_canceled(), jcr->FDJobStatus, jcr->JobStatus, jcr->SDJobStatus); if (jcr->is_canceled() || (!jcr->res.job->RescheduleIncompleteJobs)) { Dmsg3(100, "FDJS=%d JS=%d SDJS=%d\n", jcr->FDJobStatus, jcr->JobStatus, jcr->SDJobStatus); cancel_storage_daemon_job(jcr); } /* * Note, the SD stores in jcr->JobFiles/ReadBytes/JobBytes/JobErrors */ wait_for_storage_daemon_termination(jcr); jcr->FDJobStatus = JS_Terminated; if (jcr->JobStatus != JS_Terminated) { return jcr->JobStatus; } if (jcr->FDJobStatus != JS_Terminated) { return jcr->FDJobStatus; } return jcr->SDJobStatus; }
/* * Compare a files chksum against a stored chksum. * * Returns: true if chksum matches. * false if chksum is different. */ bool calculate_and_compare_file_chksum(JCR *jcr, FF_PKT *ff_pkt, const char *fname, const char *chksum) { DIGEST *digest = NULL; int digest_stream = STREAM_NONE; char *digest_buf = NULL; const char *digest_name; bool retval = false; if (calculate_file_chksum(jcr, ff_pkt, &digest, &digest_stream, &digest_buf, &digest_name)) { if (digest_stream != STREAM_NONE && digest == NULL) { Jmsg(jcr, M_WARNING, 0, _("%s digest initialization failed\n"), stream_to_ascii(digest_stream)); } else if (digest && digest_buf) { if (!bstrcmp(digest_buf, chksum)) { Dmsg4(100, "%s %s chksum diff. Cat: %s File: %s\n", fname, digest_name, chksum, digest_buf); } else { retval = true; } } if (digest_buf) { free(digest_buf); } if (digest) { crypto_digest_free(digest); } } return retval; }
/* * Do in place strip of path */ static bool do_strip(int count, char *in) { char *out = in; int stripped; int numsep = 0; /* Copy to first path separator -- Win32 might have c: ... */ while (*in && !IsPathSeparator(*in)) { out++; in++; } out++; in++; numsep++; /* one separator seen */ for (stripped=0; stripped<count && *in; stripped++) { while (*in && !IsPathSeparator(*in)) { in++; /* skip chars */ } if (*in) { numsep++; /* count separators seen */ in++; /* skip separator */ } } /* Copy to end */ while (*in) { /* copy to end */ if (IsPathSeparator(*in)) { numsep++; } *out++ = *in++; } *out = 0; Dmsg4(500, "stripped=%d count=%d numsep=%d sep>count=%d\n", stripped, count, numsep, numsep>count); return stripped==count && numsep>count; }
/* * Start a timer on a BSOCK. kill it after wait seconds. * * Returns: btimer_t *(pointer to btimer_t struct) on success * NULL on failure */ btimer_t *start_bsock_timer(BSOCK *bsock, uint32_t wait) { btimer_t *wid; if (wait <= 0) { /* wait should be > 0 */ return NULL; } wid = btimer_start_common(wait); if (wid == NULL) { return NULL; } wid->type = TYPE_BSOCK; wid->tid = pthread_self(); wid->bsock = bsock; wid->jcr = bsock->jcr(); wid->wd->callback = callback_thread_timer; wid->wd->one_shot = true; wid->wd->interval = wait; register_watchdog(wid->wd); Dmsg4(dbglvl, "Start bsock timer %p tid=%p for %d secs at %d\n", wid, wid->tid, wait, time(NULL)); return wid; }
/* * Check if this is a cleaning tape by comparing the Volume name * with the Cleaning Prefix. If they match, this is a cleaning * tape. */ static inline bool is_cleaning_tape(UAContext *ua, MEDIA_DBR *mr, POOL_DBR *pr) { bool retval; /* * Find Pool resource */ ua->jcr->res.pool = (POOLRES *)GetResWithName(R_POOL, pr->Name); if (!ua->jcr->res.pool) { ua->error_msg(_("Pool \"%s\" resource not found for volume \"%s\"!\n"), pr->Name, mr->VolumeName); return false; } retval = bstrncmp(mr->VolumeName, ua->jcr->res.pool->cleaning_prefix, strlen(ua->jcr->res.pool->cleaning_prefix)); Dmsg4(100, "CLNprefix=%s: Vol=%s: len=%d bstrncmp=%s\n", ua->jcr->res.pool->cleaning_prefix, mr->VolumeName, strlen(ua->jcr->res.pool->cleaning_prefix), retval ? "true" : "false"); return retval; }
/* * Note!! Do not enter with dev->Lock() since unreserve_device() * is going to lock it too. */ void DEVICE::detach_dcr_from_dev(DCR *dcr) { Dmsg0(500, "Enter detach_dcr_from_dev\n"); /* jcr is NULL in some cases */ Lock(); Lock_dcrs(); /* Detach this dcr only if attached */ if (dcr->attached_to_dev) { dcr->unreserve_device(true); Dmsg4(200, "Detach Jid=%d dcr=%p size=%d to dev=%s\n", (uint32_t)dcr->jcr->JobId, dcr, attached_dcrs->size(), print_name()); dcr->attached_to_dev = false; if (attached_dcrs->size()) { attached_dcrs->remove(dcr); /* detach dcr from device */ } } /* Check if someone accidentally left a drive reserved, and clear it */ if (attached_dcrs->size() == 0 && num_reserved() > 0) { Pmsg2(000, "Warning!!! dcrs=0 reserved=%d setting reserved==0. dev=%s\n", num_reserved(), print_name()); m_num_reserved = 0; } dcr->attached_to_dev = false; Unlock_dcrs(); Unlock(); }
static bool ini_store_alist_str(LEX *lc, ConfigFile *inifile, ini_items *item) { alist *list; if (!lc) { /* * TODO, write back the alist to edit buffer */ return true; } if (lex_get_token(lc, T_STRING) == T_ERROR) { return false; } if (item->val.alistval == NULL) { list = New(alist(10, owned_by_alist)); } else { list = item->val.alistval; } Dmsg4(900, "Append %s to alist %p size=%d %s\n", lc->str, list, list->size(), item->name); list->append(bstrdup(lc->str)); item->val.alistval = list; scan_to_eol(lc); return true; }
/* * Open the device with the operating system and * initialize buffer pointers. * * Returns: true on success * false on error * * Note, for a tape, the VolName is the name we give to the * volume (not really used here), but for a file, the * VolName represents the name of the file to be created/opened. * In the case of a file, the full name is the device name * (archive_name) with the VolName concatenated. */ bool DEVICE::open(DCR *dcr, int omode) { char preserve[ST_BYTES]; clear_all_bits(ST_MAX, preserve); if (is_open()) { if (open_mode == omode) { return true; } else { d_close(m_fd); clear_opened(); Dmsg0(100, "Close fd for mode change.\n"); if (bit_is_set(ST_LABEL, state)) set_bit(ST_LABEL, preserve); if (bit_is_set(ST_APPENDREADY, state)) set_bit(ST_APPENDREADY, preserve); if (bit_is_set(ST_READREADY, state)) set_bit(ST_READREADY, preserve); } } if (dcr) { dcr->setVolCatName(dcr->VolumeName); VolCatInfo = dcr->VolCatInfo; /* structure assign */ } Dmsg4(100, "open dev: type=%d dev_name=%s vol=%s mode=%s\n", dev_type, print_name(), getVolCatName(), mode_to_str(omode)); clear_bit(ST_LABEL, state); clear_bit(ST_APPENDREADY, state); clear_bit(ST_READREADY, state); clear_bit(ST_EOT, state); clear_bit(ST_WEOT, state); clear_bit(ST_EOF, state); label_type = B_BAREOS_LABEL; /* * We are about to open the device so let any plugin know we are. */ if (dcr && generate_plugin_event(dcr->jcr, bsdEventDeviceOpen, dcr) != bRC_OK) { Dmsg0(100, "open_dev: bsdEventDeviceOpen failed\n"); return false; } Dmsg1(100, "call open_device mode=%s\n", mode_to_str(omode)); open_device(dcr, omode); /* * Reset any important state info */ clone_bits(ST_MAX, preserve, state); Dmsg2(100, "preserve=0x%x fd=%d\n", preserve, m_fd); return m_fd >= 0; }
/* * Write a Record to the block * * Returns: false means the block could not be written to tape/disk. * true on success (all bytes written to the block). */ bool DCR::write_record() { bool retval = false; bool translated_record = false; char buf1[100], buf2[100]; /* * Perform record translations. */ before_rec = rec; after_rec = NULL; if (generate_plugin_event(jcr, bsdEventWriteRecordTranslation, this) != bRC_OK) { goto bail_out; } /* * The record got translated when we got an after_rec pointer after calling the * bsdEventWriteRecordTranslation plugin event. If no translation has taken place * we just point the after_rec pointer to same DEV_RECORD as in the before_rec pointer. */ if (!after_rec) { after_rec = before_rec; } else { translated_record = true; } while (!write_record_to_block(this, after_rec)) { Dmsg2(850, "!write_record_to_block data_len=%d rem=%d\n", after_rec->data_len, after_rec->remainder); if (!write_block_to_device()) { Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n", dev->print_name(), dev->bstrerror()); goto bail_out; } } jcr->JobBytes += after_rec->data_len; /* increment bytes this job */ if (jcr->RemainingQuota && jcr->JobBytes > jcr->RemainingQuota) { Jmsg0(jcr, M_FATAL, 0, _("Quota Exceeded. Job Terminated.\n")); goto bail_out; } Dmsg4(850, "write_record FI=%s SessId=%d Strm=%s len=%d\n", FI_to_ascii(buf1, after_rec->FileIndex), after_rec->VolSessionId, stream_to_ascii(buf2, after_rec->Stream, after_rec->FileIndex), after_rec->data_len); retval = true; bail_out: if (translated_record) { copy_record_state(before_rec, after_rec); free_record(after_rec); after_rec = NULL; } return retval; }
void vtape::dump() { Dmsg0(dbglevel+1, "===================\n"); Dmsg2(dbglevel, "file:block = %i:%i\n", current_file, current_block); Dmsg1(dbglevel+1, "last_file=%i\n", last_file); Dmsg1(dbglevel+1, "file_block=%i\n", file_block); Dmsg4(dbglevel+1, "EOF=%i EOT=%i EOD=%i BOT=%i\n", atEOF, atEOT, atEOD, atBOT); }
/* * Close the device */ bool DEVICE::close() { bool ok = true; Dmsg4(40, "close_dev vol=%s fd=%d dev=%p dev=%s\n", VolHdr.VolumeName, m_fd, this, print_name()); offline_or_rewind(); if (!is_open()) { Dmsg2(200, "device %s already closed vol=%s\n", print_name(), VolHdr.VolumeName); return true; /* already closed */ } switch (dev_type) { case B_VTL_DEV: case B_VTAPE_DEV: case B_TAPE_DEV: unlock_door(); /* Fall through wanted */ default: if (d_close(m_fd) != 0) { berrno be; dev_errno = errno; Mmsg2(errmsg, _("Error closing device %s. ERR=%s.\n"), print_name(), be.bstrerror()); ok = false; } break; } unmount(1); /* do unmount if required */ /* Clean up device packet so it can be reused */ clear_opened(); /* * Be careful not to clear items needed by the DVD driver * when it is closing a single part. */ state &= ~(ST_LABEL|ST_READ|ST_APPEND|ST_EOT|ST_WEOT|ST_EOF| ST_NOSPACE|ST_MOUNTED|ST_MEDIA|ST_SHORT); label_type = B_BACULA_LABEL; file = block_num = 0; file_size = 0; file_addr = 0; EndFile = EndBlock = 0; openmode = 0; clear_volhdr(); memset(&VolCatInfo, 0, sizeof(VolCatInfo)); if (tid) { stop_thread_timer(tid); tid = 0; } return ok; }
/* * This function returns the total number of bytes difference remaining before going over quota. * Returns: unsigned long long containing remaining bytes before going over quota. * 0 if over quota */ uint64_t quota_fetch_remaining_quota(JCR *jcr) { uint64_t remaining = 0; uint64_t now = (uint64_t)time(NULL); /* * Quotas not being used ? */ if (!jcr->HasQuota) { return 0; } Dmsg2(dbglvl, "JobSumTotalBytes for JobId %d is %llu\n", jcr->JobId, jcr->jr.JobSumTotalBytes); Dmsg1(dbglvl, "Fetching remaining quotas for JobId %d\n", jcr->JobId); /* * If strict quotas on and grace exceeded, enforce the softquota */ if (jcr->res.client->StrictQuotas && jcr->res.client->SoftQuota && jcr->res.client->GraceTime > 0 && (now - (uint64_t)jcr->res.client->GraceTime) > (uint64_t)jcr->res.client->SoftQuotaGracePeriod && jcr->res.client->SoftQuotaGracePeriod > 0) { remaining = jcr->res.client->SoftQuota - jcr->jr.JobSumTotalBytes; } else if (!jcr->res.client->StrictQuotas && jcr->res.client->SoftQuota && jcr->res.client->GraceTime > 0 && jcr->res.client->SoftQuotaGracePeriod > 0 && (now - (uint64_t)jcr->res.client->GraceTime) > (uint64_t)jcr->res.client->SoftQuotaGracePeriod) { /* * If strict quotas turned off and grace exceeded use the last known limit */ if (jcr->res.client->QuotaLimit > jcr->res.client->SoftQuota) { remaining = jcr->res.client->QuotaLimit - jcr->jr.JobSumTotalBytes; } else { remaining = jcr->res.client->SoftQuota - jcr->jr.JobSumTotalBytes; } } else if (jcr->jr.JobSumTotalBytes < jcr->res.client->HardQuota) { /* * If within the hardquota. */ remaining = jcr->res.client->HardQuota - jcr->jr.JobSumTotalBytes; } else { /* * If just over quota return 0. This shouldnt happen because quotas * are checked properly prior to this code. */ remaining = 0; } Dmsg4(dbglvl, "Quota for %s is %llu. Remainder is %llu, QuotaLimit: %llu\n", jcr->jr.Name, jcr->jr.JobSumTotalBytes, remaining, jcr->res.client->QuotaLimit); return remaining; }
int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode, dev_t rdev) { Dmsg4(100, "bopen: fname %s, flags %d, mode %d, rdev %u\n", fname, flags, mode, rdev); if (bfd->cmd_plugin && plugin_bopen) { Dmsg1(400, "call plugin_bopen fname=%s\n", fname); bfd->fid = plugin_bopen(bfd, fname, flags, mode); Dmsg1(400, "Plugin bopen stat=%d\n", bfd->fid); return bfd->fid; } /* Normal file open */ Dmsg1(dbglvl, "open file %s\n", fname); /* We use fnctl to set O_NOATIME if requested to avoid open error */ bfd->fid = open(fname, flags & ~O_NOATIME, mode); /* Set O_NOATIME if possible */ if (bfd->fid != -1 && flags & O_NOATIME) { int oldflags = fcntl(bfd->fid, F_GETFL, 0); if (oldflags == -1) { bfd->berrno = errno; close(bfd->fid); bfd->fid = -1; } else { int ret = fcntl(bfd->fid, F_SETFL, oldflags | O_NOATIME); /* EPERM means setting O_NOATIME was not allowed */ if (ret == -1 && errno != EPERM) { bfd->berrno = errno; close(bfd->fid); bfd->fid = -1; } } } bfd->berrno = errno; bfd->m_flags = flags; Dmsg1(400, "Open file %d\n", bfd->fid); errno = bfd->berrno; bfd->win32DecompContext.bIsInData = false; bfd->win32DecompContext.liNextHeader = 0; #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED) if (bfd->fid != -1 && flags & O_RDONLY) { int status = posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_WILLNEED); Dmsg2(400, "Did posix_fadvise on %s status=%d\n", fname, status); } #endif return bfd->fid; }
/* * Read Open session command * * We need to scan for the parameters of the job * to be restored. */ static bool read_open_session(JCR *jcr) { BSOCK *fd = jcr->file_bsock; Dmsg1(120, "%s\n", fd->msg); if (jcr->session_opened) { pm_strcpy(jcr->errmsg, _("Attempt to open read on non-open session.\n")); fd->fsend(NO_open); return false; } if (sscanf(fd->msg, read_open, jcr->read_dcr->VolumeName, &jcr->read_VolSessionId, &jcr->read_VolSessionTime, &jcr->read_StartFile, &jcr->read_EndFile, &jcr->read_StartBlock, &jcr->read_EndBlock) == 7) { if (jcr->session_opened) { pm_strcpy(jcr->errmsg, _("Attempt to open read on non-open session.\n")); fd->fsend(NOT_opened); return false; } Dmsg4(100, "read_open_session got: JobId=%d Vol=%s VolSessId=%ld VolSessT=%ld\n", jcr->JobId, jcr->read_dcr->VolumeName, jcr->read_VolSessionId, jcr->read_VolSessionTime); Dmsg4(100, " StartF=%ld EndF=%ld StartB=%ld EndB=%ld\n", jcr->read_StartFile, jcr->read_EndFile, jcr->read_StartBlock, jcr->read_EndBlock); } jcr->session_opened = true; jcr->set_JobType(JT_RESTORE); /* Send "Ticket" to File Daemon */ fd->fsend(OK_open, jcr->VolSessionId); Dmsg1(110, ">filed: %s", fd->msg); return true; }
static void callback_thread_timer(watchdog_t *self) { btimer_t *wid = (btimer_t *)self->data; Dmsg4(dbglvl, "thread timer %p kill %s tid=%p at %d.\n", self, wid->type == TYPE_BSOCK ? "bsock" : "thread", wid->tid, time(NULL)); if (wid->jcr) { Dmsg2(dbglvl, "killed jid=%u Job=%s\n", wid->jcr->JobId, wid->jcr->Job); } if (wid->type == TYPE_BSOCK && wid->bsock) { wid->bsock->set_timed_out(); } pthread_kill(wid->tid, TIMEOUT_SIGNAL); }
/* * Foward space num records * * Returns: false on failure * true on success */ bool generic_tape_device::fsr(int num) { struct mtop mt_com; int status; if (!is_open()) { dev_errno = EBADF; Mmsg0(errmsg, _("Bad call to fsr. Device not open\n")); Emsg0(M_FATAL, 0, errmsg); return false; } if (!has_cap(CAP_FSR)) { Mmsg1(errmsg, _("ioctl MTFSR not permitted on %s.\n"), prt_name); return false; } Dmsg1(100, "fsr %d\n", num); mt_com.mt_op = MTFSR; mt_com.mt_count = num; status = d_ioctl(m_fd, MTIOCTOP, (char *)&mt_com); if (status == 0) { clear_eof(); block_num += num; } else { berrno be; struct mtget mt_stat; clrerror(mt_com.mt_op); Dmsg1(100, "FSF fail: ERR=%s\n", be.bstrerror()); if (dev_get_os_pos(this, &mt_stat)) { Dmsg4(100, "Adjust from %d:%d to %d:%d\n", file, block_num, mt_stat.mt_fileno, mt_stat.mt_blkno); file = mt_stat.mt_fileno; block_num = mt_stat.mt_blkno; } else { if (at_eof()) { set_eot(); } else { set_ateof(); } } Mmsg3(errmsg, _("ioctl MTFSR %d error on %s. ERR=%s.\n"), num, prt_name, be.bstrerror()); } return status == 0; }
/* * Reposition the device to file, block * * Returns: false on failure * true on success */ bool generic_tape_device::reposition(DCR *dcr, uint32_t rfile, uint32_t rblock) { Dmsg4(100, "reposition from %u:%u to %u:%u\n", file, block_num, rfile, rblock); if (rfile < file) { Dmsg0(100, "Rewind\n"); if (!rewind(NULL)) { return false; } } if (rfile > file) { Dmsg1(100, "fsf %d\n", rfile-file); if (!fsf(rfile-file)) { Dmsg1(100, "fsf failed! ERR=%s\n", bstrerror()); return false; } Dmsg2(100, "wanted_file=%d at_file=%d\n", rfile, file); } if (rblock < block_num) { Dmsg2(100, "wanted_blk=%d at_blk=%d\n", rblock, block_num); Dmsg0(100, "bsf 1\n"); bsf(1); Dmsg0(100, "fsf 1\n"); fsf(1); Dmsg2(100, "wanted_blk=%d at_blk=%d\n", rblock, block_num); } if (has_cap(CAP_POSITIONBLOCKS) && rblock > block_num) { /* * Ignore errors as Bareos can read to the correct block. */ Dmsg1(100, "fsr %d\n", rblock-block_num); return fsr(rblock-block_num); } else { while (rblock > block_num) { if (!dcr->read_block_from_dev(NO_BLOCK_NUMBER_CHECK)) { berrno be; dev_errno = errno; Dmsg2(30, "Failed to find requested block on %s: ERR=%s", prt_name, be.bstrerror()); return false; } Dmsg2(300, "moving forward wanted_blk=%d at_blk=%d\n", rblock, block_num); } } return true; }
/* * Open and read the state file for the daemon */ void read_state_file(char *dir, const char *progname, int port) { int sfd; ssize_t status; bool ok = false; POOLMEM *fname = get_pool_memory(PM_FNAME); struct s_state_hdr hdr; int hdr_size = sizeof(hdr); Mmsg(&fname, "%s/%s.%d.state", dir, progname, port); /* If file exists, see what we have */ // Dmsg1(10, "O_BINARY=%d\n", O_BINARY); if ((sfd = open(fname, O_RDONLY|O_BINARY)) < 0) { berrno be; Dmsg3(010, "Could not open state file. sfd=%d size=%d: ERR=%s\n", sfd, sizeof(hdr), be.bstrerror()); goto bail_out; } if ((status = read(sfd, &hdr, hdr_size)) != hdr_size) { berrno be; Dmsg4(010, "Could not read state file. sfd=%d status=%d size=%d: ERR=%s\n", sfd, (int)status, hdr_size, be.bstrerror()); goto bail_out; } if (hdr.version != state_hdr.version) { Dmsg2(010, "Bad hdr version. Wanted %d got %d\n", state_hdr.version, hdr.version); goto bail_out; } hdr.id[13] = 0; if (!bstrcmp(hdr.id, state_hdr.id)) { Dmsg0(000, "State file header id invalid.\n"); goto bail_out; } // Dmsg1(010, "Read header of %d bytes.\n", sizeof(hdr)); if (!read_last_jobs_list(sfd, hdr.last_jobs_addr)) { goto bail_out; } ok = true; bail_out: if (sfd >= 0) { close(sfd); } if (!ok) { unlink(fname); } free_pool_memory(fname); }
/* * Try to connect to host for max_retry_time at retry_time intervals. * Note, you must have called the constructor prior to calling * this routine. */ bool BSOCK::connect(JCR * jcr, int retry_interval, utime_t max_retry_time, utime_t heart_beat, const char *name, char *host, char *service, int port, int verbose) { bool ok = false; int i; int fatal = 0; time_t begin_time = time(NULL); time_t now; btimer_t *tid = NULL; /* Try to trap out of OS call when time expires */ if (max_retry_time) { tid = start_thread_timer(jcr, pthread_self(), (uint32_t)max_retry_time); } for (i = 0; !open(jcr, name, host, service, port, heart_beat, &fatal); i -= retry_interval) { berrno be; if (fatal || (jcr && job_canceled(jcr))) { goto bail_out; } Dmsg4(100, "Unable to connect to %s on %s:%d. ERR=%s\n", name, host, port, be.bstrerror()); if (i < 0) { i = 60 * 5; /* complain again in 5 minutes */ if (verbose) Qmsg4(jcr, M_WARNING, 0, _( "Could not connect to %s on %s:%d. ERR=%s\n" "Retrying ...\n"), name, host, port, be.bstrerror()); } bmicrosleep(retry_interval, 0); now = time(NULL); if (begin_time + max_retry_time <= now) { Qmsg4(jcr, M_FATAL, 0, _("Unable to connect to %s on %s:%d. ERR=%s\n"), name, host, port, be.bstrerror()); goto bail_out; } } ok = true; bail_out: if (tid) { stop_thread_timer(tid); } return ok; }
void DEVICE::attach_dcr_to_dev(DCR *dcr) { JCR *jcr = dcr->jcr; Lock_dcrs(); jcr = dcr->jcr; if (jcr) Dmsg1(500, "JobId=%u enter attach_dcr_to_dev\n", (uint32_t)jcr->JobId); /* ***FIXME*** return error if dev not initiated */ if (!dcr->attached_to_dev && initiated && jcr && jcr->getJobType() != JT_SYSTEM) { Dmsg4(200, "Attach Jid=%d dcr=%p size=%d dev=%s\n", (uint32_t)jcr->JobId, dcr, attached_dcrs->size(), print_name()); attached_dcrs->append(dcr); /* attach dcr to device */ dcr->attached_to_dev = true; } Unlock_dcrs(); }
/* * +---+---------+---+------------------+---+-------------------+ * |00N| DATA |0LN| DATA |0LC| DATA | * +---+---------+---+------------------+---+-------------------+ * * 0 : zero * L : Last FileMark offset * N : Next FileMark offset * C : Current FileMark Offset */ int vtape::weof() { ASSERT(online); ASSERT(current_file >= 0); #if 0 if (atEOT) { errno = ENOSPC; current_block = -1; return -1; } #endif if (!atEOD) { truncate_file(); /* nothing after this point */ } last_FM = cur_FM; cur_FM = lseek(fd, 0, SEEK_CUR); // current position /* update previous next_FM */ lseek(fd, last_FM + sizeof(uint32_t)+sizeof(boffset_t), SEEK_SET); ::write(fd, &cur_FM, sizeof(boffset_t)); lseek(fd, cur_FM, SEEK_SET); next_FM = 0; uint32_t c=0; ::write(fd, &c, sizeof(uint32_t)); // EOF ::write(fd, &last_FM, sizeof(last_FM)); // F-1 ::write(fd, &next_FM, sizeof(next_FM)); // F (will be updated next time) current_file++; current_block = 0; needEOF = false; atEOD = false; atBOT = false; atEOF = true; last_file = MAX(current_file, last_file); Dmsg4(dbglevel, "Writing EOF %i:%i last=%lli cur=%lli next=0\n", current_file, current_block, last_FM, cur_FM); return 0; }
/* Store regex info */ static void store_regex(LEX *lc, RES_ITEM *item, int index, int pass) { int token, rc; regex_t preg; char prbuf[500]; const char *type; int newsize; token = lex_get_token(lc, T_SKIP_EOL); if (pass == 1) { /* Pickup regex string */ switch (token) { case T_IDENTIFIER: case T_UNQUOTED_STRING: case T_QUOTED_STRING: rc = regcomp(&preg, lc->str, REG_EXTENDED); if (rc != 0) { regerror(rc, &preg, prbuf, sizeof(prbuf)); regfree(&preg); scan_err1(lc, _("Regex compile error. ERR=%s\n"), prbuf); break; } regfree(&preg); if (item->code == 1) { type = "regexdir"; res_incexe.current_opts->regexdir.append(bstrdup(lc->str)); newsize = res_incexe.current_opts->regexdir.size(); } else if (item->code == 2) { type = "regexfile"; res_incexe.current_opts->regexfile.append(bstrdup(lc->str)); newsize = res_incexe.current_opts->regexfile.size(); } else { type = "regex"; res_incexe.current_opts->regex.append(bstrdup(lc->str)); newsize = res_incexe.current_opts->regex.size(); } Dmsg4(900, "set %s %p size=%d %s\n", type, res_incexe.current_opts, newsize, lc->str); break; default: scan_err1(lc, _("Expected a regex string, got: %s\n"), lc->str); } } scan_to_eol(lc); }
static void *smalloc(const char *fname, int lineno, unsigned int nbytes) { char *buf; /* Note: Unix MALLOC actually permits a zero length to be passed and allocates a valid block with zero user bytes. Such a block can later be expanded with realloc(). We disallow this based on the belief that it's better to make a special case and allocate one byte in the rare case this is desired than to miss all the erroneous occurrences where buffer length calculation code results in a zero. */ ASSERT(nbytes > 0); nbytes += HEAD_SIZE + 1; if ((buf = (char *)malloc(nbytes)) != NULL) { struct abufhead *head = (struct abufhead *)buf; P(mutex); /* Enqueue buffer on allocated list */ qinsert(&abqueue, (struct b_queue *) buf); head->ablen = nbytes; head->abfname = bufimode ? NULL : fname; head->ablineno = (uint32_t)lineno; head->abin_use = true; /* Emplace end-clobber detector at end of buffer */ buf[nbytes - 1] = (uint8_t)((((intptr_t) buf) & 0xFF) ^ 0xC5); buf += HEAD_SIZE; /* Increment to user data start */ if (++sm_buffers > sm_max_buffers) { sm_max_buffers = sm_buffers; } sm_bytes += nbytes; if (sm_bytes > sm_max_bytes) { sm_max_bytes = sm_bytes; } V(mutex); } else { Emsg0(M_ABORT, 0, _("Out of memory\n")); } Dmsg4(DT_MEMORY|50, "smalloc %d at %p from %s:%d\n", nbytes, buf, fname, lineno); #if SMALLOC_SANITY_CHECK > 0 if (sm_bytes > SMALLOC_SANITY_CHECK) { Emsg0(M_ABORT, 0, _("Too much memory used.")); } #endif return (void *)buf; }
/* Store Wild-card info */ static void store_wild(LEX *lc, RES_ITEM *item, int index, int pass) { int token; const char *type; int newsize; token = lex_get_token(lc, T_SKIP_EOL); if (pass == 1) { /* * Pickup Wild-card string */ switch (token) { case T_IDENTIFIER: case T_UNQUOTED_STRING: case T_QUOTED_STRING: if (item->code == 1) { type = "wilddir"; res_incexe.current_opts->wilddir.append(bstrdup(lc->str)); newsize = res_incexe.current_opts->wilddir.size(); } else if (item->code == 2) { if (strpbrk(lc->str, "/\\") != NULL) { type = "wildfile"; res_incexe.current_opts->wildfile.append(bstrdup(lc->str)); newsize = res_incexe.current_opts->wildfile.size(); } else { type = "wildbase"; res_incexe.current_opts->wildbase.append(bstrdup(lc->str)); newsize = res_incexe.current_opts->wildbase.size(); } } else { type = "wild"; res_incexe.current_opts->wild.append(bstrdup(lc->str)); newsize = res_incexe.current_opts->wild.size(); } Dmsg4(9, "set %s %p size=%d %s\n", type, res_incexe.current_opts, newsize, lc->str); break; default: scan_err1(lc, _("Expected a wild-card string, got: %s\n"), lc->str); } } scan_to_eol(lc); }
bool B_ACCURATE_HTABLE::add_file(JCR *jcr, char *fname, int fname_length, char *lstat, int lstat_length, char *chksum, int chksum_length, int32_t delta_seq) { CurFile *item; int total_length; bool retval = true; total_length = sizeof(CurFile) + fname_length + lstat_length + chksum_length + 3; item = (CurFile *)m_file_list->hash_malloc(total_length); item->fname = (char *)item + sizeof(CurFile); memcpy(item->fname, fname, fname_length); item->fname[fname_length] = '\0'; item->payload.lstat = item->fname + fname_length + 1; memcpy(item->payload.lstat, lstat, lstat_length); item->payload.lstat[lstat_length] = '\0'; item->payload.chksum = item->payload.lstat + lstat_length + 1; if (chksum_length) { memcpy(item->payload.chksum, chksum, chksum_length); } item->payload.chksum[chksum_length] = '\0'; item->payload.delta_seq = delta_seq; item->payload.filenr = m_filenr++; m_file_list->insert(item->fname, item); if (chksum) { Dmsg4(dbglvl, "add fname=<%s> lstat=%s delta_seq=%i chksum=%s\n", fname, lstat, delta_seq, chksum); } else { Dmsg2(dbglvl, "add fname=<%s> lstat=%s\n", fname, lstat); } return retval; }
/* * Store a string in an alist. */ void store_alist_str(LEX *lc, RES_ITEM *item, int index, int pass) { alist *list; if (pass == 2) { if (*(item->value) == NULL) { list = New(alist(10, owned_by_alist)); } else { list = (alist *)(*(item->value)); } lex_get_token(lc, T_STRING); /* scan next item */ Dmsg4(900, "Append %s to alist %p size=%d %s\n", lc->str, list, list->size(), item->name); list->append(bstrdup(lc->str)); *(item->value) = (char *)list; } scan_to_eol(lc); set_bit(index, res_all.hdr.item_present); }