Example #1
0
static char *find_msg_start(char *msg)
{
   char *p = msg;

   skip_nonspaces(&p);                /* skip message type */
   skip_spaces(&p);
   skip_nonspaces(&p);                /* skip Job */
   skip_spaces(&p);                   /* after spaces come the message */
   return p;
}
Example #2
0
/*
 * Note, we receive the whole attribute record, but we select out only the stat
 * packet, VolSessionId, VolSessionTime, FileIndex, file type, and file name to
 * store in the catalog.
 */
static void update_attribute(JCR *jcr, char *msg, int32_t msglen)
{
   unser_declare;
   uint32_t VolSessionId, VolSessionTime;
   int32_t Stream;
   uint32_t FileIndex;
   char *p;
   int len;
   char *fname, *attr;
   ATTR_DBR *ar = NULL;
   uint32_t reclen;

   /*
    * Start transaction allocates jcr->attr and jcr->ar if needed
    */
   db_start_transaction(jcr, jcr->db);     /* start transaction if not already open */
   ar = jcr->ar;

   /*
    * Start by scanning directly in the message buffer to get Stream
    * there may be a cached attr so we cannot yet write into
    * jcr->attr or jcr->ar
    */
   p = msg;
   skip_nonspaces(&p);                /* UpdCat */
   skip_spaces(&p);
   skip_nonspaces(&p);                /* Job=nnn */
   skip_spaces(&p);
   skip_nonspaces(&p);                /* "FileAttributes" */
   p += 1;

   /*
    * The following "SD header" fields are serialized
    */
   unser_begin(p, 0);
   unser_uint32(VolSessionId);        /* VolSessionId */
   unser_uint32(VolSessionTime);      /* VolSessionTime */
   unser_int32(FileIndex);            /* FileIndex */
   unser_int32(Stream);               /* Stream */
   unser_uint32(reclen);              /* Record length */
   p += unser_length(p);              /* Raw record follows */

   /**
    * At this point p points to the raw record, which varies according
    *  to what kind of a record (Stream) was sent.  Note, the integer
    *  fields at the beginning of these "raw" records are in ASCII with
    *  spaces between them so one can use scanf or manual scanning to
    *  extract the fields.
    *
    * File Attributes
    *   File_index
    *   File type
    *   Filename (full path)
    *   Encoded attributes
    *   Link name (if type==FT_LNK or FT_LNKSAVED)
    *   Encoded extended-attributes (for Win32)
    *   Delta sequence number (32 bit int)
    *
    * Restore Object
    *   File_index
    *   File_type
    *   Object_index
    *   Object_len (possibly compressed)
    *   Object_full_len (not compressed)
    *   Object_compression
    *   Plugin_name
    *   Object_name
    *   Binary Object data
    */

   Dmsg1(400, "UpdCat msg=%s\n", msg);
   Dmsg5(400, "UpdCat VolSessId=%d VolSessT=%d FI=%d Strm=%d reclen=%d\n",
         VolSessionId, VolSessionTime, FileIndex, Stream, reclen);

   jcr->SDJobBytes += reclen; /* update number of bytes transferred for quotas */

   /*
    * Depending on the stream we are handling dispatch.
    */
   switch (Stream) {
   case STREAM_UNIX_ATTRIBUTES:
   case STREAM_UNIX_ATTRIBUTES_EX:
      if (jcr->cached_attribute) {
         Dmsg2(400, "Cached attr. Stream=%d fname=%s\n", ar->Stream, ar->fname);
         if (!db_create_attributes_record(jcr, jcr->db, ar)) {
            Jmsg1(jcr, M_FATAL, 0, _("Attribute create error: ERR=%s"), db_strerror(jcr->db));
         }
         jcr->cached_attribute = false;
      }

      /*
       * Any cached attr is flushed so we can reuse jcr->attr and jcr->ar
       */
      jcr->attr = check_pool_memory_size(jcr->attr, msglen);
      memcpy(jcr->attr, msg, msglen);
      p = jcr->attr - msg + p;         /* point p into jcr->attr */
      skip_nonspaces(&p);              /* skip FileIndex */
      skip_spaces(&p);
      ar->FileType = str_to_int32(p);
      skip_nonspaces(&p);              /* skip FileType */
      skip_spaces(&p);
      fname = p;
      len = strlen(fname);             /* length before attributes */
      attr = &fname[len+1];
      ar->DeltaSeq = 0;
      if (ar->FileType == FT_REG) {
         p = attr + strlen(attr) + 1;  /* point to link */
         p = p + strlen(p) + 1;        /* point to extended attributes */
         p = p + strlen(p) + 1;        /* point to delta sequence */
         /*
          * Older FDs don't have a delta sequence, so check if it is there
          */
         if (p - jcr->attr < msglen) {
            ar->DeltaSeq = str_to_int32(p); /* delta_seq */
         }
      }

      Dmsg2(400, "dird<stored: stream=%d %s\n", Stream, fname);
      Dmsg1(400, "dird<stored: attr=%s\n", attr);

      ar->attr = attr;
      ar->fname = fname;
      if (ar->FileType == FT_DELETED) {
         ar->FileIndex = 0;     /* special value */
      } else {
         ar->FileIndex = FileIndex;
      }
      ar->Stream = Stream;
      ar->link = NULL;
      if (jcr->mig_jcr) {
         ar->JobId = jcr->mig_jcr->JobId;
      } else {
         ar->JobId = jcr->JobId;
      }
      ar->Digest = NULL;
      ar->DigestType = CRYPTO_DIGEST_NONE;
      jcr->cached_attribute = true;

      Dmsg2(400, "dird<filed: stream=%d %s\n", Stream, fname);
      Dmsg1(400, "dird<filed: attr=%s\n", attr);
      break;
   case STREAM_RESTORE_OBJECT: {
      ROBJECT_DBR ro;

      memset(&ro, 0, sizeof(ro));
      ro.Stream = Stream;
      ro.FileIndex = FileIndex;
      if (jcr->mig_jcr) {
         ro.JobId = jcr->mig_jcr->JobId;
      } else {
         ro.JobId = jcr->JobId;
      }

      Dmsg1(100, "Robj=%s\n", p);

      skip_nonspaces(&p);                  /* skip FileIndex */
      skip_spaces(&p);
      ro.FileType = str_to_int32(p);        /* FileType */
      skip_nonspaces(&p);
      skip_spaces(&p);
      ro.object_index = str_to_int32(p);    /* Object Index */
      skip_nonspaces(&p);
      skip_spaces(&p);
      ro.object_len = str_to_int32(p);      /* object length possibly compressed */
      skip_nonspaces(&p);
      skip_spaces(&p);
      ro.object_full_len = str_to_int32(p); /* uncompressed object length */
      skip_nonspaces(&p);
      skip_spaces(&p);
      ro.object_compression = str_to_int32(p); /* compression */
      skip_nonspaces(&p);
      skip_spaces(&p);

      ro.plugin_name = p;                      /* point to plugin name */
      len = strlen(ro.plugin_name);
      ro.object_name = &ro.plugin_name[len+1]; /* point to object name */
      len = strlen(ro.object_name);
      ro.object = &ro.object_name[len+1];      /* point to object */
      ro.object[ro.object_len] = 0;            /* add zero for those who attempt printing */

      Dmsg7(100, "oname=%s stream=%d FT=%d FI=%d JobId=%d, obj_len=%d\nobj=\"%s\"\n",
            ro.object_name, ro.Stream, ro.FileType, ro.FileIndex, ro.JobId,
            ro.object_len, ro.object);

      /*
       * Store it.
       */
      if (!db_create_restore_object_record(jcr, jcr->db, &ro)) {
         Jmsg1(jcr, M_FATAL, 0, _("Restore object create error. %s"), db_strerror(jcr->db));
      }
      break;
   }
   default:
      if (crypto_digest_stream_type(Stream) != CRYPTO_DIGEST_NONE) {
         fname = p;
         if (ar->FileIndex != FileIndex) {
            Jmsg3(jcr, M_WARNING, 0, _("%s not same File=%d as attributes=%d\n"),
               stream_to_ascii(Stream), FileIndex, ar->FileIndex);
         } else {
            /*
             * Update digest in catalog
             */
            char digestbuf[BASE64_SIZE(CRYPTO_DIGEST_MAX_SIZE)];
            int len = 0;
            int type = CRYPTO_DIGEST_NONE;

            switch(Stream) {
            case STREAM_MD5_DIGEST:
               len = CRYPTO_DIGEST_MD5_SIZE;
               type = CRYPTO_DIGEST_MD5;
               break;
            case STREAM_SHA1_DIGEST:
               len = CRYPTO_DIGEST_SHA1_SIZE;
               type = CRYPTO_DIGEST_SHA1;
               break;
            case STREAM_SHA256_DIGEST:
               len = CRYPTO_DIGEST_SHA256_SIZE;
               type = CRYPTO_DIGEST_SHA256;
               break;
            case STREAM_SHA512_DIGEST:
               len = CRYPTO_DIGEST_SHA512_SIZE;
               type = CRYPTO_DIGEST_SHA512;
               break;
            default:
               /*
                * Never reached ...
                */
               Jmsg(jcr, M_ERROR, 0, _("Catalog error updating file digest. Unsupported digest stream type: %d"), Stream);
            }

            bin_to_base64(digestbuf, sizeof(digestbuf), fname, len, true);

            Dmsg3(400, "DigestLen=%d Digest=%s type=%d\n", strlen(digestbuf),
                  digestbuf, Stream);

            if (jcr->cached_attribute) {
               ar->Digest = digestbuf;
               ar->DigestType = type;

               Dmsg2(400, "Cached attr with digest. Stream=%d fname=%s\n", ar->Stream, ar->fname);

               /*
                * Update BaseFile table
                */
               if (!db_create_attributes_record(jcr, jcr->db, ar)) {
                  Jmsg1(jcr, M_FATAL, 0, _("attribute create error. %s"), db_strerror(jcr->db));
               }
               jcr->cached_attribute = false;
            } else {
               if (!db_add_digest_to_file_record(jcr, jcr->db, ar->FileId, digestbuf, type)) {
                  Jmsg(jcr, M_ERROR, 0, _("Catalog error updating file digest. %s"), db_strerror(jcr->db));
               }
            }
         }
      }
      break;
   }
}
Example #3
0
/** Decode a LinkFI field of encoded stat packet */
int32_t decode_LinkFI(char *buf, struct stat *statp, int stat_size)
{
   char *p = buf;
   int64_t val;
   /*
    * We store into the stat packet so make sure the caller's conception
    *  is the same as ours.  They can be different if LARGEFILE is not
    *  the same when compiling this library and the calling program.
    */
   ASSERT(stat_size == (int)sizeof(struct stat));

   skip_nonspaces(&p);                /* st_dev */
   p++;                               /* skip space */
   skip_nonspaces(&p);                /* st_ino */
   p++;
   p += from_base64(&val, p);
   plug(statp->st_mode, val);         /* st_mode */
   p++;
   skip_nonspaces(&p);                /* st_nlink */
   p++;
   skip_nonspaces(&p);                /* st_uid */
   p++;
   skip_nonspaces(&p);                /* st_gid */
   p++;
   skip_nonspaces(&p);                /* st_rdev */
   p++;
   skip_nonspaces(&p);                /* st_size */
   p++;
   skip_nonspaces(&p);                /* st_blksize */
   p++;
   skip_nonspaces(&p);                /* st_blocks */
   p++;
   skip_nonspaces(&p);                /* st_atime */
   p++;
   skip_nonspaces(&p);                /* st_mtime */
   p++;
   skip_nonspaces(&p);                /* st_ctime */

   /* Optional FileIndex of hard linked file data */
   if (*p == ' ' || (*p != 0 && *(p+1) == ' ')) {
      p++;
      p += from_base64(&val, p);
      return (int32_t)val;
   }
   return 0;
}
Example #4
0
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Read and parse syslinux config file.
//
// return:
//   0: ok, 1: error
//
int read_config_file(void)
{
  FILE *f;
  char *s, *t, buf[MAX_CONFIG_LINE_LEN];
  unsigned u, menu_idx = 0, label_size = 0, append_size = 0;
  menu_t *menu_ptr = NULL, **menu_next = &menu;

  menu_default = calloc(1, sizeof *menu_default);

  if(!(f = fopen(syslinux_config_file(), "r"))) return 1;

  while((s = fgets(buf, sizeof buf, f))) {
    chop_line(s);
    s = skip_spaces(s);
    if(!*s || *s == '#') continue;
    t = skip_nonspaces(s);
    if(*t) *t++ = 0;
    t = skip_spaces(t);

    if(!strcasecmp(s, "timeout")) {
      timeout = atoi(t);
      continue;
    }

    if(!strcasecmp(s, "default")) {
      menu_default->label = strdup(t);
      u = strlen(t);
      if(u > label_size) label_size = u;
      continue;
    }

    if(!strcasecmp(s, "label")) {
      menu_ptr = *menu_next = calloc(1, sizeof **menu_next);
      menu_next = &menu_ptr->next;
      menu_idx++;
      menu_ptr->label = menu_ptr->menu_label = strdup(t);
      u = strlen(t);
      if(u > label_size) label_size = u;
      continue;
    }

    if(!strcasecmp(s, "kernel") && menu_ptr) {
      menu_ptr->kernel = strdup(t);
      continue;
    }

    if(!strcasecmp(s, "linux") && menu_ptr) {
      menu_ptr->linux = strdup(t);
      continue;
    }

    if(!strcasecmp(s, "localboot") && menu_ptr) {
      menu_ptr->localboot = strdup(t);
      continue;
    }

    if(!strcasecmp(s, "initrd") && menu_ptr) {
      menu_ptr->initrd = strdup(t);
      continue;
    }

    if(!strcasecmp(s, "append")) {
      (menu_ptr ?: menu_default)->append = strdup(t);
      u = strlen(t);
      if(u > append_size) append_size = u;
      continue;
    }

    if(!strcasecmp(s, "ipappend")) {
      (menu_ptr ?: menu_default)->ipappend = strdup(t);
      continue;
    }
Example #5
0
/*
 * Fill the fileWidget box with the contents of the current directory
 */
void restorePage::fillDirectory()
{
   mainWin->waitEnter();
   char modes[20], user[20], group[20], size[20], date[30];
   char marked[10];
   int pnl, fnl;
   POOLMEM *file = get_pool_memory(PM_FNAME);
   POOLMEM *path = get_pool_memory(PM_FNAME);

   fileWidget->clear();
   m_console->write_dir(m_conn, "dir", false);
   QList<QTreeWidgetItem *> treeItemList;
   QStringList item;
   m_rx.setPattern("has no children\\.$");
   bool first = true;
   while (m_console->read(m_conn) > 0) {
      char *p = m_console->msg(m_conn);
      char *l;
      strip_trailing_newline(p);
      if (*p == '$' || !*p) { continue; }
      if (first) {
         if (m_rx.indexIn(QString(p)) != -1) { continue; }
         first = false;
      }
      l = p;
      skip_nonspaces(&p);             /* permissions */
      *p++ = 0;
      bstrncpy(modes, l, sizeof(modes));
      skip_spaces(&p);
      skip_nonspaces(&p);             /* link count */
      *p++ = 0;
      skip_spaces(&p);
      l = p;
      skip_nonspaces(&p);             /* user */
      *p++ = 0;
      skip_spaces(&p);
      bstrncpy(user, l, sizeof(user));
      l = p;
      skip_nonspaces(&p);             /* group */
      *p++ = 0;
      bstrncpy(group, l, sizeof(group));
      skip_spaces(&p);
      l = p;
      skip_nonspaces(&p);             /* size */
      *p++ = 0;
      bstrncpy(size, l, sizeof(size));
      skip_spaces(&p);
      l = p;
      skip_nonspaces(&p);             /* date/time */
      skip_spaces(&p);
      skip_nonspaces(&p);
      *p++ = 0;
      bstrncpy(date, l, sizeof(date));
      skip_spaces(&p);
      if (*p == '*') {
         bstrncpy(marked, "*", sizeof(marked));
         p++;
      } else {
         bstrncpy(marked, " ", sizeof(marked));
      }
      split_path_and_filename(p, path, &pnl, file, &fnl);
      item.clear();
      item << "" << file << modes << user << group << size << date;
      if (item[1].endsWith("/")) {
         addDirectory(item[1]);
      }
      QTreeWidgetItem *ti = new QTreeWidgetItem((QTreeWidget *)0, item);
      ti->setTextAlignment(5, Qt::AlignRight); /* right align size */
      if (strcmp(marked, "*") == 0) {
         ti->setIcon(0, QIcon(QString::fromUtf8(":images/check.png")));
         ti->setData(0, Qt::UserRole, true);
      } else {
         ti->setIcon(0, QIcon(QString::fromUtf8(":images/unchecked.png")));
         ti->setData(0, Qt::UserRole, false);
      }
      treeItemList.append(ti);
   }
   fileWidget->clear();
   fileWidget->insertTopLevelItems(0, treeItemList);
   for (int i=0; i<7; i++) {
      fileWidget->resizeColumnToContents(i);
   }

   free_pool_memory(file);
   free_pool_memory(path);
   mainWin->waitExit();
}
Example #6
0
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Read and parse syslinux config file.
//
// return:
//   0: ok, 1: error
//
int read_config_file(const char *filename)
{
  FILE *f;
  char *s, *t, buf[MAX_CONFIG_LINE_LEN];
  unsigned u, top_level = 0, text = 0;

  if(!strcmp(filename, "~")) {
    top_level = 1;
    filename = syslinux_config_file();
    gfx_menu.entries = 0;
    gfx_menu.label_size = 0;
    gfx_menu.arg_size = 0;
    menu_ptr = NULL;
    menu_next = &menu;
    menu_default = calloc(1, sizeof *menu_default);
  }

  if(!(f = fopen(filename, "r"))) return 1;

  while((s = fgets(buf, sizeof buf, f))) {
    chop_line(s);
    s = skipspace(s);
    if(!*s || *s == '#') continue;
    t = skip_nonspaces(s);
    if(*t) *t++ = 0;
    t = skipspace(t);

    if(!strcasecmp(s, "endtext")) {
      text = 0;
      continue;
    }

    if (text)
      continue;

    if(!strcasecmp(s, "timeout")) {
      timeout = atoi(t);
      continue;
    }

    if(!strcasecmp(s, "default")) {
      menu_default->label = strdup(t);
      u = strlen(t);
      if(u > gfx_menu.label_size) gfx_menu.label_size = u;
      continue;
    }

    if(!strcasecmp(s, "label")) {
      menu_ptr = *menu_next = calloc(1, sizeof **menu_next);
      menu_next = &menu_ptr->next;
      gfx_menu.entries++;
      menu_ptr->label = menu_ptr->menu_label = strdup(t);
      u = strlen(t);
      if(u > gfx_menu.label_size) gfx_menu.label_size = u;
      continue;
    }

    if(!strcasecmp(s, "kernel") && menu_ptr) {
      menu_ptr->kernel = strdup(t);
      continue;
    }

    if(!strcasecmp(s, "linux") && menu_ptr) {
      menu_ptr->linux = strdup(t);
      continue;
    }

    if(!strcasecmp(s, "localboot") && menu_ptr) {
      menu_ptr->localboot = strdup(t);
      continue;
    }

    if(!strcasecmp(s, "initrd") && menu_ptr) {
      menu_ptr->initrd = strdup(t);
      continue;
    }

    if(!strcasecmp(s, "append")) {
      (menu_ptr ?: menu_default)->append = strdup(t);
      u = strlen(t);
      if(u > gfx_menu.arg_size) gfx_menu.arg_size = u;
      continue;
    }

    if(!strcasecmp(s, "ipappend")) {
      (menu_ptr ?: menu_default)->ipappend = strdup(t);
      continue;
    }
Example #7
0
/*
 * Get a message
 *  Call appropriate processing routine
 *  If it is not a Jmsg or a ReqCat message,
 *   return it to the caller.
 *
 *  This routine is called to get the next message from
 *  another daemon. If the message is in canonical message
 *  format and the type is known, it will be dispatched
 *  to the appropriate handler.  If the message is
 *  in any other format, it will be returned.
 *
 *  E.g. any message beginning with a digit will be passed
 *       through to the caller.
 *  All other messages are expected begin with some identifier
 *    -- for the moment only the first character is checked, but
 *    at a later time, the whole identifier (e.g. Jmsg, CatReq, ...)
 *    could be checked. This is followed by Job=Jobname <user-defined>
 *    info. The identifier is used to dispatch the message to the right
 *    place (Job message, catalog request, ...). The Job is used to lookup
 *    the JCR so that the action is performed on the correct jcr, and
 *    the rest of the message is up to the user.  Note, DevUpd uses
 *    *System* for the Job name, and hence no JCR is obtained. This
 *    is a *rare* case where a jcr is not really needed.
 *
 */
int bget_dirmsg(BSOCK *bs, bool allow_any_message)
{
   int32_t n = BNET_TERMINATE;
   char Job[MAX_NAME_LENGTH];
   char MsgType[20];
   int type;
   utime_t mtime;                     /* message time */
   JCR *jcr = bs->jcr();
   char *msg;

   for ( ; !bs->is_stop() && !bs->is_timed_out(); ) {
      n = bs->recv();
      Dmsg2(200, "bget_dirmsg %d: %s\n", n, bs->msg);

      if (bs->is_stop() || bs->is_timed_out()) {
         return n;                    /* error or terminate */
      }
      if (n == BNET_SIGNAL) {          /* handle signal */
         /* BNET_SIGNAL (-1) return from bnet_recv() => network signal */
         switch (bs->msglen) {
         case BNET_EOD:            /* end of data */
            return n;
         case BNET_EOD_POLL:
            bs->fsend(OK_msg);/* send response */
            return n;              /* end of data */
         case BNET_TERMINATE:
            bs->set_terminated();
            return n;
         case BNET_POLL:
            bs->fsend(OK_msg); /* send response */
            break;
         case BNET_HEARTBEAT:
//          encode_time(time(NULL), Job);
//          Dmsg1(100, "%s got heartbeat.\n", Job);
            break;
         case BNET_HB_RESPONSE:
            break;
         case BNET_STATUS:
            /* *****FIXME***** Implement more completely */
            bs->fsend("Status OK\n");
            bs->signal(BNET_EOD);
            break;
         case BNET_BTIME:             /* send BAREOS time */
            char ed1[50];
            bs->fsend("btime %s\n", edit_uint64(get_current_btime(),ed1));
            break;
         default:
            Jmsg1(jcr, M_WARNING, 0, _("bget_dirmsg: unknown bnet signal %d\n"), bs->msglen);
            return n;
         }
         continue;
      }

      /*
       * Handle normal data
       */
      if (n > 0 && B_ISDIGIT(bs->msg[0])) {      /* response? */
         return n;                    /* yes, return it */
      }

      /*
       * If we get here, it must be a request.  Either
       *  a message to dispatch, or a catalog request.
       *  Try to fulfill it.
       */
      if (sscanf(bs->msg, "%020s Job=%127s ", MsgType, Job) != 2) {
         /*
          * If the special flag allow_any_message is given ignore
          * the error and just return it as normal data.
          */
         if (allow_any_message) {
            return n;
         } else {
            Jmsg1(jcr, M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
            continue;
         }
      }

      /*
       * Skip past "Jmsg Job=nnn"
       */
      if (!(msg=find_msg_start(bs->msg))) {
         Jmsg1(jcr, M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
         continue;
      }

      /*
       * Here we are expecting a message of the following format:
       *   Jmsg Job=nnn type=nnn level=nnn Message-string
       * Note, level should really be mtime, but that changes
       *   the protocol.
       */
      if (bs->msg[0] == 'J') {           /* Job message */
         if (sscanf(bs->msg, "Jmsg Job=%127s type=%d level=%lld",
                    Job, &type, &mtime) != 3) {
            Jmsg1(jcr, M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
            continue;
         }
         Dmsg1(900, "Got msg: %s\n", bs->msg);
         skip_spaces(&msg);
         skip_nonspaces(&msg);        /* skip type=nnn */
         skip_spaces(&msg);
         skip_nonspaces(&msg);        /* skip level=nnn */
         if (*msg == ' ') {
            msg++;                    /* skip leading space */
         }
         Dmsg1(900, "Dispatch msg: %s", msg);
         dispatch_message(jcr, type, mtime, msg);
         continue;
      }
      /*
       * Here we expact a CatReq message
       *   CatReq Job=nn Catalog-Request-Message
       */
      if (bs->msg[0] == 'C') {        /* Catalog request */
         Dmsg2(900, "Catalog req jcr 0x%x: %s", jcr, bs->msg);
         catalog_request(jcr, bs);
         continue;
      }
      if (bs->msg[0] == 'U') {        /* SD sending attributes */
         Dmsg2(900, "Catalog upd jcr 0x%x: %s", jcr, bs->msg);
         catalog_update(jcr, bs);
         continue;
      }
      if (bs->msg[0] == 'B') {        /* SD sending file spool attributes */
         Dmsg2(100, "Blast attributes jcr 0x%x: %s", jcr, bs->msg);
         char filename[256];
         if (sscanf(bs->msg, "BlastAttr Job=%127s File=%255s",
                    Job, filename) != 2) {
            Jmsg1(jcr, M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
            continue;
         }
         unbash_spaces(filename);
         if (despool_attributes_from_file(jcr, filename)) {
            bs->fsend("1000 OK BlastAttr\n");
         } else {
            bs->fsend("1990 ERROR BlastAttr\n");
         }
         continue;
      }
      if (bs->msg[0] == 'M') {        /* Mount request */
         Dmsg1(900, "Mount req: %s", bs->msg);
         mount_request(jcr, bs, msg);
         continue;
      }
      if (bs->msg[0] == 'S') {       /* Status change */
         int JobStatus;
         char Job[MAX_NAME_LENGTH];
         if (sscanf(bs->msg, Job_status, &Job, &JobStatus) == 2) {
            set_jcr_sd_job_status(jcr, JobStatus); /* current status */
         } else {
            Jmsg1(jcr, M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
         }
         continue;
      }
#ifdef needed
      /* No JCR for Device Updates! */
      if (bs->msg[0] = 'D') {         /* Device update */
         DEVICE *dev;
         POOL_MEM dev_name, changer_name, media_type, volume_name;
         int dev_open, dev_append, dev_read, dev_labeled;
         int dev_offline, dev_autochanger, dev_autoselect;
         int dev_num_writers, dev_max_writers, dev_reserved;
         uint64_t dev_read_time, dev_write_time, dev_write_bytes, dev_read_bytes;
         uint64_t dev_PoolId;
         Dmsg1(100, "<stored: %s", bs->msg);
         if (sscanf(bs->msg, Device_update,
             &Job, dev_name.c_str(),
             &dev_append, &dev_read,
             &dev_num_writers, &dev_open,
             &dev_labeled, &dev_offline, &dev_reserved,
             &dev_max_writers, &dev_autoselect,
             &dev_autochanger,
             changer_name.c_str(), media_type.c_str(),
             volume_name.c_str(),
             &dev_read_time, &dev_write_time, &dev_read_bytes,
             &dev_write_bytes) != 19) {
            Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
         } else {
            unbash_spaces(dev_name);
            dev = (DEVICE *)GetResWithName(R_DEVICE, dev_name.c_str());
            if (!dev) {
               continue;
            }
            unbash_spaces(changer_name);
            unbash_spaces(media_type);
            unbash_spaces(volume_name);
            bstrncpy(dev->ChangerName, changer_name.c_str(), sizeof(dev->ChangerName));
            bstrncpy(dev->MediaType, media_type.c_str(), sizeof(dev->MediaType));
            bstrncpy(dev->VolumeName, volume_name.c_str(), sizeof(dev->VolumeName));
            /* Note, these are copied because they are boolean rather than
             *  integer.
             */
            dev->open = dev_open;
            dev->append = dev_append;
            dev->read = dev_read;
            dev->labeled = dev_labeled;
            dev->offline = dev_offline;
            dev->autoselect = dev_autoselect;
            dev->autochanger = dev_autochanger > 0;
            dev->num_drives = dev_autochanger;    /* does double duty */
            dev->PoolId = dev_PoolId;
            dev->num_writers = dev_num_writers;
            dev->max_writers = dev_max_writers;
            dev->reserved = dev_reserved;
            dev->found = true;
            dev->DevReadTime = dev_read_time; /* TODO : have to update database */
            dev->DevWriteTime = dev_write_time;
            dev->DevReadBytes = dev_read_bytes;
            dev->DevWriteBytes = dev_write_bytes;
         }
         continue;
      }
#endif
      return n;
   }
   return n;
}
Example #8
0
/*
 * This routine is called only during a Verify
 */
void get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId)
{
   BSOCK   *fd;
   int n, len;
   FILE_DBR fdbr;
   struct stat statf;                 /* file stat */
   struct stat statc;                 /* catalog stat */
   char buf[MAXSTRING];
   POOLMEM *fname = get_pool_memory(PM_MESSAGE);
   int do_Digest = CRYPTO_DIGEST_NONE;
   int32_t file_index = 0;

   memset(&fdbr, 0, sizeof(FILE_DBR));
   fd = jcr->file_bsock;
   fdbr.JobId = JobId;
   jcr->FileIndex = 0;

   Dmsg0(20, "bdird: waiting to receive file attributes\n");
   /*
    * Get Attributes and Signature from File daemon
    * We expect:
    *   FileIndex
    *   Stream
    *   Options or Digest (MD5/SHA1)
    *   Filename
    *   Attributes
    *   Link name  ???
    */
   while ((n=bget_dirmsg(fd)) >= 0 && !job_canceled(jcr)) {
      int32_t stream, full_stream;
      char *attr, *p, *fn;
      char Opts_Digest[MAXSTRING];        /* Verify Opts or MD5/SHA1 digest */

      if (job_canceled(jcr)) {
         free_pool_memory(fname);
         return;
      }
      fname = check_pool_memory_size(fname, fd->msglen);
      jcr->fname = check_pool_memory_size(jcr->fname, fd->msglen);
      Dmsg1(200, "Atts+Digest=%s\n", fd->msg);
      if ((len = sscanf(fd->msg, "%ld %d %100s", &file_index, &full_stream,
            fname)) != 3) {
         Jmsg3(jcr, M_FATAL, 0, _("bird<filed: bad attributes, expected 3 fields got %d\n"
" mslen=%d msg=%s\n"), len, fd->msglen, fd->msg);
         free_pool_memory(fname);
         return;
      }
      stream = full_stream & STREAMMASK_TYPE;
      Dmsg4(30, "Got hdr: FilInx=%d FullStream=%d Stream=%d fname=%s.\n", file_index, full_stream, stream, fname);

      /*
       * We read the Options or Signature into fname
       *  to prevent overrun, now copy it to proper location.
       */
      bstrncpy(Opts_Digest, fname, sizeof(Opts_Digest));
      p = fd->msg;
      skip_nonspaces(&p);             /* skip FileIndex */
      skip_spaces(&p);
      skip_nonspaces(&p);             /* skip Stream */
      skip_spaces(&p);
      skip_nonspaces(&p);             /* skip Opts_Digest */
      p++;                            /* skip space */
      fn = fname;
      while (*p != 0) {
         *fn++ = *p++;                /* copy filename */
      }
      *fn = *p++;                     /* term filename and point to attribs */
      attr = p;
      /*
       * Got attributes stream, decode it
       */
      if (stream == STREAM_UNIX_ATTRIBUTES || stream == STREAM_UNIX_ATTRIBUTES_EX) {
         int32_t LinkFIf, LinkFIc;
         Dmsg2(400, "file_index=%d attr=%s\n", file_index, attr);
         jcr->JobFiles++;
         jcr->FileIndex = file_index;    /* remember attribute file_index */
         jcr->previous_jr.FileIndex = file_index;
         decode_stat(attr, &statf, sizeof(statf), &LinkFIf);  /* decode file stat packet */
         do_Digest = CRYPTO_DIGEST_NONE;
         jcr->fn_printed = false;
         pm_strcpy(jcr->fname, fname);  /* move filename into JCR */

         Dmsg2(040, "dird<filed: stream=%d %s\n", stream, jcr->fname);
         Dmsg1(020, "dird<filed: attr=%s\n", attr);

         /*
          * Find equivalent record in the database
          */
         fdbr.FileId = 0;
         if (!db_get_file_attributes_record(jcr, jcr->db, jcr->fname,
              &jcr->previous_jr, &fdbr)) {
            Jmsg(jcr, M_INFO, 0, _("New file: %s\n"), jcr->fname);
            Dmsg1(020, _("File not in catalog: %s\n"), jcr->fname);
            jcr->setJobStatus(JS_Differences);
            continue;
         } else {
            /*
             * mark file record as visited by stuffing the
             * current JobId, which is unique, into the MarkId field.
             */
            db_mark_file_record(jcr, jcr->db, fdbr.FileId, jcr->JobId);
         }

         Dmsg3(400, "Found %s in catalog. inx=%d Opts=%s\n", jcr->fname,
            file_index, Opts_Digest);
         decode_stat(fdbr.LStat, &statc, sizeof(statc), &LinkFIc); /* decode catalog stat */
         /*
          * Loop over options supplied by user and verify the
          * fields he requests.
          */
         for (p=Opts_Digest; *p; p++) {
            char ed1[30], ed2[30];
            switch (*p) {
            case 'i':                /* compare INODEs */
               if (statc.st_ino != statf.st_ino) {
                  prt_fname(jcr);
                  Jmsg(jcr, M_INFO, 0, _("      st_ino   differ. Cat: %s File: %s\n"),
                     edit_uint64((uint64_t)statc.st_ino, ed1),
                     edit_uint64((uint64_t)statf.st_ino, ed2));
                  jcr->setJobStatus(JS_Differences);
               }
               break;
            case 'p':                /* permissions bits */
               if (statc.st_mode != statf.st_mode) {
                  prt_fname(jcr);
                  Jmsg(jcr, M_INFO, 0, _("      st_mode  differ. Cat: %x File: %x\n"),
                     (uint32_t)statc.st_mode, (uint32_t)statf.st_mode);
                  jcr->setJobStatus(JS_Differences);
               }
               break;
            case 'n':                /* number of links */
               if (statc.st_nlink != statf.st_nlink) {
                  prt_fname(jcr);
                  Jmsg(jcr, M_INFO, 0, _("      st_nlink differ. Cat: %d File: %d\n"),
                     (uint32_t)statc.st_nlink, (uint32_t)statf.st_nlink);
                  jcr->setJobStatus(JS_Differences);
               }
               break;
            case 'u':                /* user id */
               if (statc.st_uid != statf.st_uid) {
                  prt_fname(jcr);
                  Jmsg(jcr, M_INFO, 0, _("      st_uid   differ. Cat: %u File: %u\n"),
                     (uint32_t)statc.st_uid, (uint32_t)statf.st_uid);
                  jcr->setJobStatus(JS_Differences);
               }
               break;
            case 'g':                /* group id */
               if (statc.st_gid != statf.st_gid) {
                  prt_fname(jcr);
                  Jmsg(jcr, M_INFO, 0, _("      st_gid   differ. Cat: %u File: %u\n"),
                     (uint32_t)statc.st_gid, (uint32_t)statf.st_gid);
                  jcr->setJobStatus(JS_Differences);
               }
               break;
            case 's':                /* size */
               if (statc.st_size != statf.st_size) {
                  prt_fname(jcr);
                  Jmsg(jcr, M_INFO, 0, _("      st_size  differ. Cat: %s File: %s\n"),
                     edit_uint64((uint64_t)statc.st_size, ed1),
                     edit_uint64((uint64_t)statf.st_size, ed2));
                  jcr->setJobStatus(JS_Differences);
               }
               break;
            case 'a':                /* access time */
               if (statc.st_atime != statf.st_atime) {
                  prt_fname(jcr);
                  Jmsg(jcr, M_INFO, 0, _("      st_atime differs\n"));
                  jcr->setJobStatus(JS_Differences);
               }
               break;
            case 'm':
               if (statc.st_mtime != statf.st_mtime) {
                  prt_fname(jcr);
                  Jmsg(jcr, M_INFO, 0, _("      st_mtime differs\n"));
                  jcr->setJobStatus(JS_Differences);
               }
               break;
            case 'c':                /* ctime */
               if (statc.st_ctime != statf.st_ctime) {
                  prt_fname(jcr);
                  Jmsg(jcr, M_INFO, 0, _("      st_ctime differs\n"));
                  jcr->setJobStatus(JS_Differences);
               }
               break;
            case 'd':                /* file size decrease */
               if (statc.st_size > statf.st_size) {
                  prt_fname(jcr);
                  Jmsg(jcr, M_INFO, 0, _("      st_size  decrease. Cat: %s File: %s\n"),
                     edit_uint64((uint64_t)statc.st_size, ed1),
                     edit_uint64((uint64_t)statf.st_size, ed2));
                  jcr->setJobStatus(JS_Differences);
               }
               break;
            case '5':                /* compare MD5 */
               Dmsg1(500, "set Do_MD5 for %s\n", jcr->fname);
               do_Digest = CRYPTO_DIGEST_MD5;
               break;
            case '1':                 /* compare SHA1 */
               do_Digest = CRYPTO_DIGEST_SHA1;
               break;
            case ':':
            case 'V':
            default:
               break;
            }
         }
      /*
       * Got Digest Signature from Storage daemon
       *  It came across in the Opts_Digest field.
       */
      } else if (crypto_digest_stream_type(stream) != CRYPTO_DIGEST_NONE) {
         Dmsg2(400, "stream=Digest inx=%d Digest=%s\n", file_index, Opts_Digest);
         /*
          * When ever we get a digest it MUST have been
          * preceded by an attributes record, which sets attr_file_index
          */
         if (jcr->FileIndex != (uint32_t)file_index) {
            Jmsg2(jcr, M_FATAL, 0, _("MD5/SHA1 index %d not same as attributes %d\n"),
               file_index, jcr->FileIndex);
            free_pool_memory(fname);
            return;
         }
         if (do_Digest != CRYPTO_DIGEST_NONE) {
            db_escape_string(jcr, jcr->db, buf, Opts_Digest, strlen(Opts_Digest));
            if (strcmp(buf, fdbr.Digest) != 0) {
               prt_fname(jcr);
               Jmsg(jcr, M_INFO, 0, _("      %s differs. File=%s Cat=%s\n"),
                    stream_to_ascii(stream), buf, fdbr.Digest);
               jcr->setJobStatus(JS_Differences);
            }
            do_Digest = CRYPTO_DIGEST_NONE;
         }
      }
      jcr->JobFiles = file_index;
   }
   if (fd->is_error()) {
      berrno be;
      Jmsg2(jcr, M_FATAL, 0, _("bdird<filed: bad attributes from filed n=%d : %s\n"),
                        n, be.bstrerror());
      free_pool_memory(fname);
      return;
   }

   /* Now find all the files that are missing -- i.e. all files in
    *  the database where the MarkId != current JobId
    */
   jcr->fn_printed = false;
   bsnprintf(buf, sizeof(buf),
      "SELECT Path.Path,Filename.Name FROM File,Path,Filename "
      "WHERE File.JobId=%d AND File.FileIndex > 0 "
      "AND File.MarkId!=%d AND File.PathId=Path.PathId "
      "AND File.FilenameId=Filename.FilenameId",
         JobId, jcr->JobId);
   /* missing_handler is called for each file found */
   db_sql_query(jcr->db, buf, missing_handler, (void *)jcr);
   if (jcr->fn_printed) {
      jcr->setJobStatus(JS_Differences);
   }
   free_pool_memory(fname);
}
Example #9
0
/* Update the free space on the device */
bool DEVICE::update_freespace()
{
   POOL_MEM ocmd(PM_FNAME);
   POOLMEM* results;
   char* icmd;
   char* p;
   uint64_t free, total;
   char ed1[50];
   bool ok = false;
   int status;
   berrno be;

   if (!is_file()) {
      Mmsg(errmsg, "");
      return true;
   }

   /* The device must be mounted in order for freespace to work */
   if (requires_mount()) {
      mount(1);
   }

   if (get_os_device_freespace()) {
      Dmsg4(20, "get_os_device_freespace: free_space=%s freespace_ok=%d free_space_errno=%d have_media=%d\n",
         edit_uint64(free_space, ed1), !!is_freespace_ok(), free_space_errno, !!have_media());
      return true;
   }

   icmd = device->free_space_command;

   if (!icmd) {
      set_freespace(0, 0, 0, false);
      Dmsg2(20, "ERROR: update_free_space_dev: free_space=%s, free_space_errno=%d (!icmd)\n",
            edit_uint64(free_space, ed1), free_space_errno);
      Mmsg(errmsg, _("No FreeSpace command defined.\n"));
      return false;
   }

   edit_mount_codes(ocmd, icmd);

   Dmsg1(20, "update_freespace: cmd=%s\n", ocmd.c_str());

   results = get_pool_memory(PM_MESSAGE);

   Dmsg1(20, "Run freespace prog=%s\n", ocmd.c_str());
   status = run_program_full_output(ocmd.c_str(), max_open_wait/2, results);
   Dmsg2(20, "Freespace status=%d result=%s\n", status, results);
   /* Should report "1223232 12323232\n"  "free  total\n" */
   if (status == 0) {
      free = str_to_int64(results) * 1024;
      p = results;

      if (skip_nonspaces(&p)) {
         total = str_to_int64(p) * 1024;

      } else {
         total = 0;
      }

      Dmsg1(400, "Free space program run: Freespace=%s\n", results);
      if (free >= 0) {
         set_freespace(free, total, 0, true); /* have valid freespace */
         Mmsg(errmsg, "");
         ok = true;
      }
   } else {
      set_freespace(0, 0, EPIPE, false); /* no valid freespace */
      Mmsg2(errmsg, _("Cannot run free space command. Results=%s ERR=%s\n"),
            results, be.bstrerror(status));

      dev_errno = free_space_errno;
      Dmsg4(20, "Cannot get free space on device %s. free_space=%s, "
         "free_space_errno=%d ERR=%s\n",
            print_name(), edit_uint64(free_space, ed1),
            free_space_errno, errmsg);
   }
   free_pool_memory(results);
   Dmsg4(20, "leave update_freespace: free_space=%s freespace_ok=%d free_space_errno=%d have_media=%d\n",
      edit_uint64(free_space, ed1), !!is_freespace_ok(), free_space_errno, !!have_media());
   return ok;
}
Example #10
0
/*
 * Fill the CList box with files at path
 */
void FillDirectory(const char *path, Window *restore)
{
   char pathbuf[MAXSTRING];
   char modes[20], user[20], group[20], size[20], date[30];
   char file[1000];
   char marked[10];
   gchar *text[NUM_COLUMNS] = {marked, file, modes, user, group, size, date};
   GtkCList *list = restore->list;
   int row = 0;

   stop_director_reader(NULL);
   pm_strcpy(&restore->fname, path);
   gtk_entry_set_text(GTK_ENTRY(restore_dir), restore->fname);
   gtk_clist_freeze(list);
   gtk_clist_clear(list);

   bsnprintf(pathbuf, sizeof(pathbuf), "cd %s", path);
   Dmsg1(100, "%s\n", pathbuf);
   write_director(pathbuf);
   discard_to_prompt();

   write_director("dir");
   while (bnet_recv(UA_sock) > 0) {
      char *p = UA_sock->msg;
      char *l;
      strip_trailing_junk(UA_sock->msg);
      if (*p == '$') {
         break;
      }
      Dmsg1(200, "Got: %s\n", p);
      if (!*p) {
         continue;
      }
      l = p;
      skip_nonspaces(&p);             /* permissions */
      *p++ = 0;
      bstrncpy(modes, l, sizeof(modes));
      skip_spaces(&p);
      skip_nonspaces(&p);             /* link count */
      *p++ = 0;
      skip_spaces(&p);
      l = p;
      skip_nonspaces(&p);             /* user */
      *p++ = 0;
      skip_spaces(&p);
      bstrncpy(user, l, sizeof(user));
      l = p;
      skip_nonspaces(&p);             /* group */
      *p++ = 0;
      bstrncpy(group, l, sizeof(group));
      skip_spaces(&p);
      l = p;
      skip_nonspaces(&p);             /* size */
      *p++ = 0;
      bstrncpy(size, l, sizeof(size));
      skip_spaces(&p);
      l = p;
      skip_nonspaces(&p);             /* date/time */
      skip_spaces(&p);
      skip_nonspaces(&p);
      *p++ = 0;
      bstrncpy(date, l, sizeof(date));
      skip_spaces(&p);
      if (*p == '*') {
         bstrncpy(marked, "x", sizeof(marked));
         p++;
      } else {
         bstrncpy(marked, " ", sizeof(marked));
      }
      split_path_and_filename(p, &restore->path, &restore->pnl,
                              &restore->file, &restore->fnl);

//    Dmsg1(000, "restore->fname=%s\n", restore->fname);
      bstrncpy(file, restore->file, sizeof(file));
//    printf("modes=%s user=%s group=%s size=%s date=%s file=%s\n",
//       modes, user, group, size, date, file);

      gtk_clist_append(list, text);

      row++;
   }

   /* Fix up length of file column */
   gtk_clist_set_column_width(list, FILE_COLUMN, gtk_clist_optimal_column_width(list, FILE_COLUMN));
   gtk_clist_set_column_width(list, MODES_COLUMN, gtk_clist_optimal_column_width(list, MODES_COLUMN));
   gtk_clist_thaw(list);
   start_director_reader(NULL);
}