Logo Search packages:      
Sourcecode: makefs version File versions  Download package

iso9660_rrip.c

/**   $MirOS: src/usr.sbin/makefs/cd9660/iso9660_rrip.c,v 1.21 2009/06/29 18:58:55 tg Exp $ */
/*    $NetBSD: iso9660_rrip.c,v 1.4 2006/12/18 21:03:29 christos Exp $  */

/*
 * Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan
 * Perez-Rathke and Ram Vedam.  All rights reserved.
 *
 * This code was written by Daniel Watt, Walter Deignan, Ryan Gabrys,
 * Alan Perez-Rathke and Ram Vedam.
 *
 * 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, 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 DANIEL WATT, WALTER DEIGNAN, RYAN
 * GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM ``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 DANIEL WATT, WALTER DEIGNAN, RYAN
 * GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM 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.
 */
/* This will hold all the function definitions
 * defined in iso9660_rrip.h
 */

#include "makefs.h"
#include "cd9660.h"
#include "iso9660_rrip.h"
#include <sys/queue.h>
#include <stdio.h>

#include <sys/cdefs.h>
#if defined(__RCSID) && !defined(__lint)
__RCSID("$NetBSD: iso9660_rrip.c,v 1.4 2006/12/18 21:03:29 christos Exp $");
__IDSTRING(mbsdid, "$MirOS: src/usr.sbin/makefs/cd9660/iso9660_rrip.c,v 1.21 2009/06/29 18:58:55 tg Exp $");
#endif  /* !__lint */

static void cd9660_rrip_initialize_inode(cd9660node *);
static int cd9660_susp_handle_continuation(cd9660node *);
static int cd9660_susp_handle_continuation_common(cd9660node *, int);

int
cd9660_susp_initialize(cd9660node *node, cd9660node *parent,
    cd9660node *grandparent, int shortcut)
{
      cd9660node *cn;
      int r;

      /* Make sure the node is not NULL. If it is, there are major problems */
      assert(node != NULL);

      if (shortcut == 2) {
            shortcut = 0;
            goto cd9660_susp_initialize_shortcut;
      }

      if (!(node->type & CD9660_TYPE_DOT) &&
          !(node->type & CD9660_TYPE_DOTDOT))
            TAILQ_INIT(&(node->head));
      if (node->dot_record != 0)
            TAILQ_INIT(&(node->dot_record->head));
      if (node->dot_dot_record != 0)
            TAILQ_INIT(&(node->dot_dot_record->head));

       /* SUSP specific entries here */
      if ((r = cd9660_susp_initialize_node(node)) < 0)
            return r;

      /* currently called cd9660node_rrip_init_links */
      r = cd9660_rrip_initialize_node(node, parent, grandparent);
      if (r < 0)
            return r;

      /*
       * If we are the root node, we need to initialise the entries for
       * our dot node now (out of the below loop) with shortcut set to
       * 1, then move all of its entries (save PX to prevent duplicates)
       * into it, then finalise the dot node out of bounds but after us
       * again. The “shortcut” variable is unused after the label, thus
       * it can be used as temporary to speed up the loop.
       */

      if (shortcut == 1)
            return 1;
 cd9660_susp_initialize_shortcut:
      /* assert: shortcut == 0 here */

      if (node == diskStructure.rootNode) {
            /* We are the root node. */
            struct ISO_SUSP_ATTRIBUTES *temp;

            /* Initialise our dot record. */
            if ((r = cd9660_susp_initialize(node->dot_record, node,
                parent, 1)) < 0)
                  return r;

            /* Move SUSP entries. */
            while ((temp = TAILQ_FIRST(&node->head))) {
                  TAILQ_REMOVE(&node->head, temp, rr_ll);
                  if (temp->attr.su_entry.SP.h.type[0] != 'P' ||
                      temp->attr.su_entry.SP.h.type[1] != 'X')
                        TAILQ_INSERT_TAIL(&node->dot_record->head,
                            temp, rr_ll);
            }

            /* Note that we are the root node. */
            shortcut = 1;

            /* Now go on process ourselves normally. */
      }

      /*
       * See if we need a CE record, and set all of the
       * associated counters.
       *
       * This should be called after all extensions. After
       * this is called, no new records should be added.
       */
      if ((r = cd9660_susp_handle_continuation(node)) < 0)
            return r;

      /* Recurse on children. */
      TAILQ_FOREACH(cn, &node->cn_children, cn_next_child) {
            if ((r = cd9660_susp_initialize(cn, node, parent,
                /* root node? */ shortcut && cn == node->dot_record ?
                /* finish only */ 2 : /* full operation */ 0)) < 0)
                  return 0;
      }
      return 1;
}

int
cd9660_susp_finalize(cd9660node *node)
{
      cd9660node *temp;
      int r;

      assert(node != NULL);

      if (node == diskStructure.rootNode)
            diskStructure.susp_continuation_area_current_free = 0;

      if ((r = cd9660_susp_finalize_node(node)) < 0)
            return r;
      if ((r = cd9660_rrip_finalize_node(node)) < 0)
            return r;

      TAILQ_FOREACH(temp, &node->cn_children, cn_next_child) {
            if ((r = cd9660_susp_finalize(temp)) < 0)
                  return r;
      }
      return 1;
}

/*
 * If we really wanted to speed things up, we could have some sort of
 * lookup table on the SUSP entry type that calls a functor. Or, we could
 * combine the functions. These functions are kept separate to allow
 * easier addition of other extensions.

 * For the sake of simplicity and clarity, we won't be doing that for now.
 */

/*
 * SUSP needs to update the following types:
 * CE (continuation area)
 */
int
cd9660_susp_finalize_node(cd9660node *node)
{
      struct ISO_SUSP_ATTRIBUTES *t;

      /* Handle CE counters */
      if (node->susp_entry_ce_length > 0) {
            node->susp_entry_ce_start =
                diskStructure.susp_continuation_area_current_free;
            diskStructure.susp_continuation_area_current_free +=
                node->susp_entry_ce_length;
      }

      TAILQ_FOREACH(t, &node->head, rr_ll) {
            if (t->susp_type != SUSP_TYPE_SUSP ||
                t->entry_type != SUSP_ENTRY_SUSP_CE)
                  continue;
            cd9660_bothendian_dword(
                  diskStructure.
                    susp_continuation_area_start_sector,
                  t->attr.su_entry.CE.ca_sector);

            cd9660_bothendian_dword(
                  diskStructure.
                    susp_continuation_area_start_sector,
                  t->attr.su_entry.CE.ca_sector);
            cd9660_bothendian_dword(node->susp_entry_ce_start,
                  t->attr.su_entry.CE.offset);
            cd9660_bothendian_dword(node->susp_entry_ce_length,
                  t->attr.su_entry.CE.length);
      }
      return 0;
}

int
cd9660_rrip_finalize_node(cd9660node *node)
{
      struct ISO_SUSP_ATTRIBUTES *t;

      TAILQ_FOREACH(t, &node->head, rr_ll) {
            if (t->susp_type != SUSP_TYPE_RRIP)
                  continue;
            switch (t->entry_type) {
            case SUSP_ENTRY_RRIP_CL:
                  /* Look at rr_relocated*/
                  if (node->rr_relocated == NULL)
                        return -1;
                  cd9660_bothendian_dword(
                      node->rr_relocated->fileDataSector,
                      t->attr.rr_entry.CL.dir_loc);
                  break;
            case SUSP_ENTRY_RRIP_PL:
                  /* Look at rr_real_parent */
                  if (node->parent->rr_real_parent == NULL)
                        return -1;
                  cd9660_bothendian_dword(
                      node->parent->rr_real_parent->fileDataSector,
                      t->attr.rr_entry.PL.dir_loc);
                  break;
            }
      }
      return 0;
}

static int
cd9660_susp_handle_continuation_common(cd9660node *node, int space)
{
      int ca_used, susp_used, working;
      struct ISO_SUSP_ATTRIBUTES *temp, *last = NULL, *CE;

      working = 254 - space;
#ifdef DEBUG
      printf("There are %i bytes to work with\n", working);
#endif

      susp_used = 0;
      ca_used = 0;
      TAILQ_FOREACH(temp, &node->head, rr_ll) {
#ifdef DEBUG
            printf("SUSP entry %c%c found, length %d\n",
                temp->attr.su_entry.SP.h.type[0],
                temp->attr.su_entry.SP.h.type[1],
                temp->attr.su_entry.SP.h.length[0]);
#endif
            working -= CD9660_SUSP_ENTRY_SIZE(temp);
            if (working >= 28) {
                  last = temp;
                  susp_used += CD9660_SUSP_ENTRY_SIZE(temp);
            } else if (working < 0)
                  break;
      }

      /* A CE entry is needed */
      if (working <= 0) {
            CE = cd9660node_susp_create_node(SUSP_TYPE_SUSP,
                  SUSP_ENTRY_SUSP_CE, "CE", SUSP_LOC_ENTRY);
            cd9660_susp_ce(CE, node);
            TAILQ_INSERT_BEFORE(temp, CE, rr_ll);
            susp_used += 28;

            /* Count how much CA data is necessary */
            for (temp = TAILQ_NEXT(CE, rr_ll); temp != NULL;
                 temp = TAILQ_NEXT(temp, rr_ll)) {
                  ca_used += CD9660_SUSP_ENTRY_SIZE(temp);
            }
      }

      /* align to even size */
      node->susp_entry_size = ((susp_used + 1) >> 1) << 1;
      node->susp_entry_ce_length = ca_used;

      diskStructure.susp_continuation_area_size += ca_used;
      return 1;
}

/* See if a continuation entry is needed for each of the different types */
static int
cd9660_susp_handle_continuation(cd9660node *node)
{
      assert (node != NULL);

      /* Entry */
      if (cd9660_susp_handle_continuation_common(
            node,(int)(node->isoDirRecord->length[0])) < 0)
            return 0;

      return 1;
}

int
cd9660_susp_initialize_node(cd9660node *node)
{
      struct ISO_SUSP_ATTRIBUTES *temp;

      /*
       * Requirements/notes:
       * CE: is added for us where needed
       * ST: not sure if it is even required, but if so, should be
       *     handled by the CE code
       * PD: isnt needed (though might be added for testing)
       * SP: is stored ONLY on the . record of the root directory
       * ES: not sure
       */

      /* Check for root directory, add SP and ER if needed. */
      if (node->type & CD9660_TYPE_DOT) {
            if (node->parent == diskStructure.rootNode) {
                  temp = cd9660node_susp_create_node(SUSP_TYPE_SUSP,
                        SUSP_ENTRY_SUSP_SP, "SP", SUSP_LOC_DOT);
                  cd9660_susp_sp(temp, node);

                  /* Should be first entry. */
                  TAILQ_INSERT_HEAD(&node->head, temp, rr_ll);
            }
      }
      return 1;
}

static void
cd9660_rrip_initialize_inode(cd9660node *node)
{
      struct ISO_SUSP_ATTRIBUTES *attr;

      /*
       * Inode dependent values - this may change,
       * but for now virtual files and directories do
       * not have an inode structure
       */

      if ((node->node != NULL) && (node->node->inode != NULL)) {
            /* PX - POSIX attributes */
            attr = cd9660node_susp_create_node(SUSP_TYPE_RRIP,
                  SUSP_ENTRY_RRIP_PX, "PX", SUSP_LOC_ENTRY);
            cd9660node_rrip_px(attr, node->node);

            TAILQ_INSERT_TAIL(&node->head, attr, rr_ll);

            /* TF - timestamp */
            attr = cd9660node_susp_create_node(SUSP_TYPE_RRIP,
                  SUSP_ENTRY_RRIP_TF, "TF", SUSP_LOC_ENTRY);
            cd9660node_rrip_tf(attr, node->node);
            TAILQ_INSERT_TAIL(&node->head, attr, rr_ll);

            /* SL - Symbolic link */
            /* ?????????? Dan - why is this here? */
            if (TAILQ_EMPTY(&node->cn_children) &&
                node->node->inode != NULL &&
                S_ISLNK(node->node->inode->st.st_mode))
                  cd9660_createSL(node);

            /* PN - device number */
            if (node->node->inode != NULL &&
                ((S_ISCHR(node->node->inode->st.st_mode) ||
                 S_ISBLK(node->node->inode->st.st_mode)))) {
                  attr =
                      cd9660node_susp_create_node(SUSP_TYPE_RRIP,
                        SUSP_ENTRY_RRIP_PN, "PN",
                        SUSP_LOC_ENTRY);
                  cd9660node_rrip_pn(attr, node->node);
                  TAILQ_INSERT_TAIL(&node->head, attr, rr_ll);
            }
      }
}

int
cd9660_rrip_initialize_node(cd9660node *node, cd9660node *parent,
    cd9660node *grandparent)
{
      struct ISO_SUSP_ATTRIBUTES *current = NULL;

      assert(node != NULL);

      if (node->type & CD9660_TYPE_DOT) {
            /*
             * Handle ER - should be the only entry to appear on
             * a "." record
             */
            if (node->parent == diskStructure.rootNode) {
                  cd9660_susp_ER(node, 1, SUSP_RRIP_ER_EXT_ID,
                        SUSP_RRIP_ER_EXT_DES, SUSP_RRIP_ER_EXT_SRC);
            }
            if (parent != NULL && parent->node != NULL &&
                parent->node->inode != NULL) {
                  /* PX - POSIX attributes */
                  current = cd9660node_susp_create_node(SUSP_TYPE_RRIP,
                        SUSP_ENTRY_RRIP_PX, "PX", SUSP_LOC_ENTRY);
                  cd9660node_rrip_px(current, parent->node);
                  TAILQ_INSERT_TAIL(&node->head, current, rr_ll);
            }
      } else if (node->type & CD9660_TYPE_DOTDOT) {
            if (grandparent != NULL && grandparent->node != NULL &&
                grandparent->node->inode != NULL) {
                  /* PX - POSIX attributes */
                  current = cd9660node_susp_create_node(SUSP_TYPE_RRIP,
                        SUSP_ENTRY_RRIP_PX, "PX", SUSP_LOC_ENTRY);
                  cd9660node_rrip_px(current, grandparent->node);
                  TAILQ_INSERT_TAIL(&node->head, current, rr_ll);
            }
      } else {
            cd9660_rrip_initialize_inode(node);

            /*
             * Not every node needs a NM set - only if the name is
             * actually different. IE: If a file is TEST -> TEST,
             * no NM. test -> TEST, need a NM
             *
             * The rr_moved_dir needs to be assigned a NM record as well.
             */
            if (node == diskStructure.rr_moved_dir) {
                  cd9660_rrip_add_NM(node, RRIP_DEFAULT_MOVE_DIR_NAME);
            }
            else if ((node->node != NULL) &&
                  ((strlen(node->node->name) !=
                      (int)node->isoDirRecord->name_len[0]) ||
                  (memcmp(node->node->name,node->isoDirRecord->name,
                        (int) node->isoDirRecord->name_len[0]) != 0))) {
                  cd9660_rrip_NM(node);
            }



            /* Rock ridge directory relocation code here. */

            /* First handle the CL for the placeholder file. */
            if (node->rr_relocated != NULL) {
                  current = cd9660node_susp_create_node(SUSP_TYPE_RRIP,
                        SUSP_ENTRY_RRIP_CL, "CL", SUSP_LOC_ENTRY);
                  cd9660_rrip_CL(current, node);
                  TAILQ_INSERT_TAIL(&node->head, current, rr_ll);
            }

            /* Handle RE*/
            if (node->rr_real_parent != NULL) {
                  current = cd9660node_susp_create_node(SUSP_TYPE_RRIP,
                        SUSP_ENTRY_RRIP_RE, "RE", SUSP_LOC_ENTRY);
                  cd9660_rrip_RE(current,node);
                  TAILQ_INSERT_TAIL(&node->head, current, rr_ll);

                  /* Handle PL */
                  current = cd9660node_susp_create_node(SUSP_TYPE_RRIP,
                        SUSP_ENTRY_RRIP_PL, "PL", SUSP_LOC_DOTDOT);
                  cd9660_rrip_PL(current,node->dot_dot_record);
                  TAILQ_INSERT_TAIL(&node->dot_dot_record->head, current,
                      rr_ll);
            }
      }
      return 1;
}

struct ISO_SUSP_ATTRIBUTES*
cd9660node_susp_create_node(int susp_type, int entry_type, const char *type_id,
                      int write_loc)
{
      struct ISO_SUSP_ATTRIBUTES* temp;

      if ((temp = calloc(1, sizeof (struct ISO_SUSP_ATTRIBUTES))) == NULL) {
            CD9660_MEM_ALLOC_ERROR("cd9660node_susp_create_node");
            exit(1);
      }

      temp->susp_type = susp_type;
      temp->entry_type = entry_type;
      /* Phase this out */
      temp->type_of[0] = type_id[0];
      temp->type_of[1] = type_id[1];
      temp->write_location = write_loc;

      /*
       * Since the first four bytes is common, lets go ahead and
       * set the type identifier, since we are passing that to this
       * function anyhow.
       */
      temp->attr.su_entry.SP.h.type[0] = type_id[0];
      temp->attr.su_entry.SP.h.type[1] = type_id[1];
      return temp;
}

int
cd9660_rrip_PL(struct ISO_SUSP_ATTRIBUTES* p, cd9660node *node __unused)
{
      p->attr.rr_entry.PL.h.length[0] = 12;
      p->attr.rr_entry.PL.h.version[0] = 1;
      return 1;
}

int
cd9660_rrip_CL(struct ISO_SUSP_ATTRIBUTES *p, cd9660node *node __unused)
{
      p->attr.rr_entry.CL.h.length[0] = 12;
      p->attr.rr_entry.CL.h.version[0] = 1;
      return 1;
}

int
cd9660_rrip_RE(struct ISO_SUSP_ATTRIBUTES *p, cd9660node *node __unused)
{
      p->attr.rr_entry.RE.h.length[0] = 0;
      p->attr.rr_entry.RE.h.version[0] = 1;
      return 1;
}

void
cd9660_createSL(cd9660node *node)
{
      struct ISO_SUSP_ATTRIBUTES* current;
      int path_count, dir_count, done, i, j, dir_copied;
      char temp_cr[255];
      char temp_sl[255]; /* used in copying continuation entry*/
      char* sl_ptr;

      sl_ptr = node->node->symlink;

      done = 0;
      path_count = 0;
      dir_count = 0;
      dir_copied = 0;
      current = cd9660node_susp_create_node(SUSP_TYPE_RRIP,
          SUSP_ENTRY_RRIP_SL, "SL", SUSP_LOC_ENTRY);

      current->attr.rr_entry.SL.h.version[0] = 1;
      current->attr.rr_entry.SL.flags[0] = SL_FLAGS_NONE;

      if (*sl_ptr == '/') {
            temp_cr[0] = SL_FLAGS_ROOT;
            temp_cr[1] = 0;
            memcpy(current->attr.rr_entry.SL.component + path_count,
                temp_cr, 2);
            path_count += 2;
            sl_ptr++;
      }

      for (i = 0; i < (dir_count + 2); i++)
            temp_cr[i] = '\0';

      while (!done) {
            while ((*sl_ptr != '/') && (*sl_ptr != '\0')) {
                  dir_copied = 1;
                  if (*sl_ptr == '.') {
                        if ((*(sl_ptr + 1) == '/') || (*(sl_ptr + 1)
                             == '\0')) {
                              temp_cr[0] = SL_FLAGS_CURRENT;
                              sl_ptr++;
                        } else if(*(sl_ptr + 1) == '.') {
                              if ((*(sl_ptr + 2) == '/') ||
                                  (*(sl_ptr + 2) == '\0')) {
                                    temp_cr[0] = SL_FLAGS_PARENT;
                                    sl_ptr += 2;
                              }
                        } else {
                              temp_cr[dir_count+2] = *sl_ptr;
                              sl_ptr++;
                              dir_count++;
                        }
                  } else {
                        temp_cr[dir_count + 2] = *sl_ptr;
                        sl_ptr++;
                        dir_count++;
                  }
            }

            if ((path_count + dir_count) >= 249) {
                  current->attr.rr_entry.SL.flags[0] |= SL_FLAGS_CONTINUE;

                  j = 0;

                  if (path_count <= 249) {
                        while(j != (249 - path_count)) {
                              temp_sl[j] = temp_cr[j];
                              j++;
                        }
                        temp_sl[0] = SL_FLAGS_CONTINUE;
                        temp_sl[1] = j - 2;
                        memcpy(
                            current->attr.rr_entry.SL.component +
                              path_count,
                            temp_sl, j);
                  }

                  path_count += j;
                  current->attr.rr_entry.SL.h.length[0] = path_count + 5;
                  TAILQ_INSERT_TAIL(&node->head, current, rr_ll);
                  current= cd9660node_susp_create_node(SUSP_TYPE_RRIP,
                         SUSP_ENTRY_RRIP_SL, "SL", SUSP_LOC_ENTRY);
                  current->attr.rr_entry.SL.h.version[0] = 1;
                  current->attr.rr_entry.SL.flags[0] = SL_FLAGS_NONE;

                  path_count = 0;

                  if (dir_count > 2) {
                        while (j != dir_count + 2) {
                              current->attr.rr_entry.SL.component[
                                  path_count + 2] = temp_cr[j];
                              j++;
                              path_count++;
                        }
                        current->attr.rr_entry.SL.component[1]
                            = path_count;
                        path_count+= 2;
                  } else {
                        while(j != dir_count) {
                              current->attr.rr_entry.SL.component[
                                  path_count+2] = temp_cr[j];
                              j++;
                              path_count++;
                        }
                  }
            } else {
                  if (dir_copied == 1) {
                        temp_cr[1] = dir_count;
                        memcpy(current->attr.rr_entry.SL.component +
                              path_count,
                            temp_cr, dir_count + 2);
                        path_count += dir_count + 2;
                  }
            }

            if (*sl_ptr == '\0') {
                  done = 1;
                  current->attr.rr_entry.SL.h.length[0] = path_count + 5;
                  TAILQ_INSERT_TAIL(&node->head, current, rr_ll);
            } else {
                  sl_ptr++;
                  dir_count = 0;
                  dir_copied = 0;
                  for(i = 0; i < 255; i++) {
                        temp_cr[i] = '\0';
                  }
            }
      }
}

int
cd9660node_rrip_px(struct ISO_SUSP_ATTRIBUTES *v, fsnode *pxinfo)
{
      v->attr.rr_entry.PX.h.length[0] = 44;
      v->attr.rr_entry.PX.h.version[0] = 1;
      cd9660_bothendian_dword(rrip_squash ?
          /* turn on all R bits, and all X bits if one X bit is set */
          (((pxinfo->inode->st.st_mode & 0111) ? 0555 : 0444) |
          /* preserve original mode bits, except W, setugid, sticky */
          pxinfo->inode->st.st_mode) & ~07222 : pxinfo->inode->st.st_mode,
          v->attr.rr_entry.PX.mode);
      cd9660_bothendian_dword(pxinfo->inode->st.st_nlink,
          v->attr.rr_entry.PX.links);
      cd9660_bothendian_dword(rrip_squash ? 0 : pxinfo->inode->st.st_uid,
          v->attr.rr_entry.PX.uid);
      cd9660_bothendian_dword(rrip_squash ? 0 : pxinfo->inode->st.st_gid,
          v->attr.rr_entry.PX.gid);
      cd9660_bothendian_dword(pxinfo->inode->serno,
          v->attr.rr_entry.PX.serial);

      return 1;
}

int
cd9660node_rrip_pn(struct ISO_SUSP_ATTRIBUTES *pn_field, fsnode *fnode)
{
      pn_field->attr.rr_entry.PN.h.length[0] = 20;
      pn_field->attr.rr_entry.PN.h.version[0] = 1;

      if (sizeof (fnode->inode->st.st_rdev) > 32)
            cd9660_bothendian_dword((uint64_t)fnode->inode->st.st_rdev >> 32,
                pn_field->attr.rr_entry.PN.high);
      else
            cd9660_bothendian_dword(0, pn_field->attr.rr_entry.PN.high);

      cd9660_bothendian_dword(fnode->inode->st.st_rdev & 0xffffffff,
            pn_field->attr.rr_entry.PN.low);
      return 1;
}

#if 0
int
cd9660node_rrip_nm(struct ISO_SUSP_ATTRIBUTES *p, cd9660node *file_node)
{
      int nm_length = strlen(file_node->isoDirRecord->name) + 5;
        p->attr.rr_entry.NM.h.type[0] = 'N';
      p->attr.rr_entry.NM.h.type[1] = 'M';
      snprintf(p->attr.rr_entry.NM.altname,
          sizeof (p->attr.rr_entry.NM.altname),
          "%s", file_node->isoDirRecord->name);
      p->attr.rr_entry.NM.h.length[0] = (unsigned char)nm_length;
      p->attr.rr_entry.NM.h.version[0] = (unsigned char)1;
      p->attr.rr_entry.NM.flags[0] = (unsigned char) NM_PARENT;
      return 1;
}
#endif

int
cd9660node_rrip_tf(struct ISO_SUSP_ATTRIBUTES *p, fsnode *_node)
{
      struct cd9660node_rrip_tf_data {
            ISO_SUSP_HEADER          h;
            u_char flags             [ISODCL ( 4, 4)];
#if 0
            u_char timestamp   [ISODCL ( 5, 256)];
#else
            /* using short form */
            u_char ts_mtime          [ISODCL ( 5, 11)];
            u_char ts_atime          [ISODCL (12, 18)];
            u_char ts_ctime          [ISODCL (19, 25)];
            u_char _ts_rest          [ISODCL (26, 256)];
#endif
      } *tfp;

      /* memory alias */
      tfp = (struct cd9660node_rrip_tf_data *)(&(p->attr.rr_entry.TF));

      tfp->flags[0] = TF_MODIFY | TF_ACCESS | TF_ATTRIBUTES;
      tfp->h.length[0] = 4;
      tfp->h.version[0] = 1;

      /*
       * Need to add creation time, backup time,
       * expiration time, and effective time.
       */

      cd9660_time_915(_node->inode->st.st_mtime, tfp->ts_mtime);
      tfp->h.length[0] += 7;

      cd9660_time_915(_node->inode->st.st_atime, tfp->ts_atime);
      tfp->h.length[0] += 7;

      cd9660_time_915(_node->inode->st.st_ctime, tfp->ts_ctime);
      tfp->h.length[0] += 7;
      return 1;
}

int
cd9660_susp_sp(struct ISO_SUSP_ATTRIBUTES *p, cd9660node *spinfo __unused)
{
      p->attr.su_entry.SP.h.length[0] = 7;
      p->attr.su_entry.SP.h.version[0] = 1;
      p->attr.su_entry.SP.check[0] = 0xBE;
      p->attr.su_entry.SP.check[1] = 0xEF;
      p->attr.su_entry.SP.len_skp[0] = 0;
      return 1;
}

int
cd9660_susp_st(struct ISO_SUSP_ATTRIBUTES *p, cd9660node *stinfo __unused)
{
      p->attr.su_entry.ST.h.type[0] = 'S';
      p->attr.su_entry.ST.h.type[1] = 'T';
      p->attr.su_entry.ST.h.length[0] = 4;
      p->attr.su_entry.ST.h.version[0] = 1;
      return 1;
}

int
cd9660_susp_ce(struct ISO_SUSP_ATTRIBUTES *p, cd9660node *spinfo __unused)
{
      p->attr.su_entry.CE.h.length[0] = 28;
      p->attr.su_entry.CE.h.version[0] = 1;
      /* Other attributes dont matter right now, will be updated later */
      return 1;
}

int
cd9660_susp_pd(struct ISO_SUSP_ATTRIBUTES *p __unused, int length __unused)
{
      return 1;
}

void
cd9660_rrip_add_NM(cd9660node *node, const char *name)
{
      int working,len;
      const char *p;
      struct ISO_SUSP_ATTRIBUTES *r;

      /*
       * Each NM record has 254 byes to work with. This means that
       * the name data itself only has 249 bytes to work with. So, a
       * name with 251 characters would require two nm records.
       */
      p = name;
      working = 1;
      while (working) {
            r = cd9660node_susp_create_node(SUSP_TYPE_RRIP,
                SUSP_ENTRY_RRIP_NM, "NM", SUSP_LOC_ENTRY);
            r->attr.rr_entry.NM.h.version[0] = 1;
            r->attr.rr_entry.NM.flags[0] = RRIP_NM_FLAGS_NONE;
            len = strlen(p);

            if (len > 249) {
                  len = 249;
                  r->attr.rr_entry.NM.flags[0] = RRIP_NM_FLAGS_CONTINUE;
            } else {
                  working = 0;
            }
            memcpy(r->attr.rr_entry.NM.altname, p, len);
            r->attr.rr_entry.NM.h.length[0] = 5 + len;

            TAILQ_INSERT_TAIL(&node->head, r, rr_ll);

            p += len;
      }
}

void
cd9660_rrip_NM(cd9660node *node)
{
      cd9660_rrip_add_NM(node, node->node->name);
}

struct ISO_SUSP_ATTRIBUTES*
cd9660_susp_ER(cd9660node *node,
             u_char ext_version, const char* ext_id, const char* ext_des,
             const char* ext_src)
{
      int l;
      struct ISO_SUSP_ATTRIBUTES *r;

      r = cd9660node_susp_create_node(SUSP_TYPE_SUSP,
                  SUSP_ENTRY_SUSP_ER, "ER", SUSP_LOC_DOT);

      /* Fixed data is 8 bytes */
      r->attr.su_entry.ER.h.length[0] = 8;
      r->attr.su_entry.ER.h.version[0] = 1;

      r->attr.su_entry.ER.len_id[0] = (u_char)strlen(ext_id);
      r->attr.su_entry.ER.len_des[0] = (u_char)strlen(ext_des);
      r->attr.su_entry.ER.len_src[0] = (u_char)strlen(ext_src);

      l = r->attr.su_entry.ER.len_id[0] +
            r->attr.su_entry.ER.len_src[0] +
            r->attr.su_entry.ER.len_des[0];

      /* Everything must fit. */
      assert(l + r->attr.su_entry.ER.h.length[0] <= 254);

      r->attr.su_entry.ER.h.length[0] += (u_char)l;


      r->attr.su_entry.ER.ext_ver[0] = ext_version;
      memcpy(r->attr.su_entry.ER.ext_data, ext_id,
            (int)r->attr.su_entry.ER.len_id[0]);
      l = (int) r->attr.su_entry.ER.len_id[0];
      memcpy(r->attr.su_entry.ER.ext_data + l,ext_des,
            (int)r->attr.su_entry.ER.len_des[0]);

      l += (int)r->attr.su_entry.ER.len_des[0];
      memcpy(r->attr.su_entry.ER.ext_data + l,ext_src,
            (int)r->attr.su_entry.ER.len_src[0]);

      TAILQ_INSERT_TAIL(&node->head, r, rr_ll);
      return r;
}

struct ISO_SUSP_ATTRIBUTES*
cd9660_susp_ES(struct ISO_SUSP_ATTRIBUTES *last __unused, cd9660node *node __unused)
{
      return NULL;
}

Generated by  Doxygen 1.6.0   Back to index