Imported Upstream version 3.1.0
[debian/amanda] / ndmp-src / smc_parse.c
diff --git a/ndmp-src/smc_parse.c b/ndmp-src/smc_parse.c
new file mode 100644 (file)
index 0000000..29bc504
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 1998,1999,2000
+ *     Traakan, Inc., Los Altos, CA
+ *     All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice unmodified, this list of conditions, and the following
+ *    disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Project:  NDMJOB
+ * Ident:    $Id: $
+ *
+ * Description:
+ *
+ */
+
+
+#include "smc_priv.h"
+
+
+#define WITH(P,V,T)    { T * V = (T *) P;
+#define ENDWITH                }
+
+int
+smc_parse_volume_tag (
+  struct smc_raw_volume_tag *raw,
+  struct smc_volume_tag *vtag)
+{
+       int             i;
+
+       bzero (vtag, sizeof *vtag);
+
+       for (i = 31; i >= 0 && raw->volume_id[i] == ' '; i--)
+               continue;
+
+       for (; i >= 0; i--)
+               vtag->volume_id[i] = raw->volume_id[i];
+
+       vtag->volume_seq = SMC_GET2(raw->volume_seq);
+
+       return 0;
+}
+
+
+
+int
+smc_parse_element_status_data (
+  char *       raw,
+  unsigned     raw_len,
+  struct smc_element_descriptor elem_desc[],
+  unsigned     max_elem_desc)
+{
+       unsigned char *                 p = (unsigned char *)raw;
+       unsigned char *                 raw_end = p + raw_len;
+       unsigned int                    n_elem = 0;
+
+       bzero (elem_desc, sizeof elem_desc[0] * max_elem_desc);
+
+       WITH(p, esdh, struct smc_raw_element_status_data_header)
+               unsigned        byte_count = SMC_GET3(esdh->byte_count);
+
+               if (raw_len > byte_count+8) {
+                       /* probably an error, but press on */
+                       raw_len = byte_count+8;
+               }
+               raw_end = p + raw_len;
+       ENDWITH
+
+       p += 8;
+
+       while (p+8 < raw_end) {         /* +8 for sizeof *esph */
+           WITH(p, esph, struct smc_raw_element_status_page_header)
+               unsigned        desc_size = SMC_GET2(esph->elem_desc_len);
+               unsigned        byte_count = SMC_GET3(esph->byte_count);
+               unsigned        elem_type = esph->element_type;
+               unsigned char * pgend = p + byte_count + 8;
+               int             PVolTag = 0;
+               int             AVolTag = 0;
+
+               if (pgend > raw_end) {
+                       /* malformed, really, but punt */
+                       pgend = raw_end;
+               }
+
+               if (esph->flag1 & SMC_RAW_ESP_F1_PVolTag)
+                       PVolTag = 1;
+               if (esph->flag1 & SMC_RAW_ESP_F1_AVolTag)
+                       AVolTag = 1;
+
+               p += 8;
+
+               for (;p + desc_size <= pgend; p += desc_size) {
+                   struct smc_element_descriptor *edp;
+
+                   if (n_elem >= max_elem_desc) {
+                       /* bust out */
+                       goto done;
+                   }
+                   edp = &elem_desc[n_elem++];
+                   WITH (p, red, struct smc_raw_element_descriptor)
+                       unsigned char *p2;
+
+                       edp->element_type_code = elem_type;
+                       edp->element_address = SMC_GET2(red->element_address);
+                       edp->PVolTag = PVolTag;
+                       edp->AVolTag = AVolTag;
+#define FLAG(RAWMEM,BIT,MEM) if (red->RAWMEM & BIT) edp->MEM = 1;
+                       FLAG(flags2, SMC_RAW_ED_F2_Full, Full);
+                       FLAG(flags2, SMC_RAW_ED_F2_ImpExp, ImpExp);
+                       FLAG(flags2, SMC_RAW_ED_F2_Except, Except);
+                       FLAG(flags2, SMC_RAW_ED_F2_Access, Access);
+                       FLAG(flags2, SMC_RAW_ED_F2_ExEnab, ExEnab);
+                       FLAG(flags2, SMC_RAW_ED_F2_InEnab, InEnab);
+
+                       edp->asc = red->asc;
+                       edp->ascq = red->ascq;
+
+                       edp->scsi_lun = red->flags6 & 7;
+                       FLAG(flags6, SMC_RAW_ED_F6_LU_valid, LU_valid);
+                       FLAG(flags6, SMC_RAW_ED_F6_ID_valid, ID_valid);
+                       FLAG(flags6, SMC_RAW_ED_F6_Not_bus, Not_bus);
+
+                       edp->scsi_sid = red->scsi_sid;
+
+                       FLAG(flags9, SMC_RAW_ED_F9_Invert, Invert);
+                       FLAG(flags9, SMC_RAW_ED_F9_SValid, SValid);
+#undef FLAG
+
+                       edp->src_se_addr = SMC_GET2(red->src_se_addr);
+
+                       p2 = (unsigned char *) &red->primary_vol_tag;
+                       if (edp->PVolTag) {
+                               smc_parse_volume_tag ((void*)p2,
+                                               &edp->primary_vol_tag);
+                               p2 += SMC_VOL_TAG_LEN;
+                       }
+                       if (edp->AVolTag) {
+                               smc_parse_volume_tag ((void*)p2,
+                                               &edp->alternate_vol_tag);
+                               p2 += SMC_VOL_TAG_LEN;
+                       }
+                       p2 += 4;        /* resv84 */
+                       /* p2 ready for vendor_specific */
+                   ENDWITH
+               }
+               p = pgend;
+           ENDWITH
+       }
+
+  done:
+       return n_elem;
+}
+
+
+
+int
+smc_parse_element_address_assignment (
+  struct smc_raw_element_address_assignment_page *raw,
+  struct smc_element_address_assignment *eaa)
+{
+       eaa->mte_addr  = SMC_GET2(raw->mte_addr);
+       eaa->mte_count = SMC_GET2(raw->mte_count);
+       eaa->se_addr   = SMC_GET2(raw->se_addr);
+       eaa->se_count  = SMC_GET2(raw->se_count);
+       eaa->iee_addr  = SMC_GET2(raw->iee_addr);
+       eaa->iee_count = SMC_GET2(raw->iee_count);
+       eaa->dte_addr  = SMC_GET2(raw->dte_addr);
+       eaa->dte_count = SMC_GET2(raw->dte_count);
+
+       return 0;
+}
+