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

rock.c

/*
 * This file has been modified for the cdrkit suite.
 *
 * The behaviour and appearence of the program code below can differ to a major
 * extent from the version distributed by the original author(s).
 *
 * For details, see Changelog file distributed with the cdrkit package. If you
 * received this file from another source then ask the distributing person for
 * a log of modifications.
 *
 */

/* @(#)rock.c     1.43 05/05/01 joerg */
/*
 * File rock.c - generate RRIP  records for iso9660 filesystems.
 *
 * Written by Eric Youngdale (1993).
 *
 * Copyright 1993 Yggdrasil Computing, Incorporated
 * Copyright (c) 1999,2000-2003 J. Schilling
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <mconfig.h>
#include "genisoimage.h"
#include <device.h>
#include <schily.h>

#define     SU_VERSION 1

#define     SL_ROOT    8
#define     SL_PARENT  4
#define     SL_CURRENT 2
#define     SL_CONTINUE 1

#define     CE_SIZE 28  /* SUSP     Continuation aerea                  */
#define     CL_SIZE 12  /* RR Child Link for deep dir relocation  */
#define     ER_SIZE 8   /* RR Extension record for RR signature   */
#define     NM_SIZE 5   /* RR Real name                     */
#define     PL_SIZE 12  /* RR Paren Link for deep dir relocation  */
#define     PN_SIZE 20  /* RR POSIX device modes (Major/Minor)    */
#define     PX_SIZE 36  /* RR POSIX Extensions (mode/nlink(uid/gid)     */
#define     RE_SIZE 4   /* RR Relocated directory                 */
#define     RR_SIZE 5   /* RR RR Signature in every file          */
#define     SL_SIZE 20  /* RR Symlink                             */
#define     ZF_SIZE 16  /* RR*      Linux compression extension         */
#ifdef APPLE_HYB
#define     AA_SIZE 14  /* size of Apple extension */
#endif      /* APPLE_HYB */
#if defined(__QNX__) && !defined(__QNXNTO__)    /* Not on Neutrino! never OK? */
#define     TF_SIZE (5 + 4 * 7)     /* RR Time field              */
#else
#define     TF_SIZE (5 + 3 * 7)
#endif

static      void  rstrncpy(char *t, char *f, int c,
                                          struct unls_table *inls,
                                          struct unls_table *onls);
static      void  add_CE_entry(char *field, int line);
static      int   gen_xa_attr(mode_t attr);
static      void  gen_xa(struct stat *lstatbuf);
int generate_xa_rr_attributes(char *whole_name, char *name,
                                                            struct directory_entry *s_entry,
                                                            struct stat *statbuf,
                                                            struct stat *lstatbuf,
                                                            int deep_opt);
char *generate_rr_extension_record(char *id, char *descriptor, char *source,
                                                                    int *size);
/*
 * If we need to store this number of bytes, make sure we
 * do not box ourselves in so that we do not have room for
 * a CE entry for the continuation record
 */
#define     RR_CUR_USE  (CE_SIZE + currlen + (ipnt - recstart))

#define     MAYBE_ADD_CE_ENTRY(BYTES) \
      (((int)(BYTES)) + CE_SIZE + currlen + (ipnt - recstart) > reclimit ? 1 : 0)

/*
 * Buffer to build RR attributes
 */
static      Uchar Rock[16384];
static      Uchar symlink_buff[PATH_MAX+1];
static      int   ipnt = 0;   /* Current "write" offset in Rock[] */
static      int   recstart = 0;     /* Start offset in Rock[] for this area   */
static      int   currlen = 0;      /* # of non RR bytes used in this area    */
static      int   mainrec = 0;      /* # of RR bytes use in main dir area     */
static      int   reclimit;   /* Max. # of bytes usable in this area    */

/* if we are using converted filenames, we don't want the '/' character */
static void
rstrncpy(char *t, char *f, int c, struct unls_table *inls, 
                  struct unls_table *onls)
{
      while (c-- && *f) {
            *t = conv_charset(*f, inls, onls);
            if (*t == '/') {
                  *t = '_';
            }
            t++;
            f++;
      }
}

static void
add_CE_entry(char *field, int line)
{
      if (MAYBE_ADD_CE_ENTRY(0)) {
            errmsgno(EX_BAD,
            "Panic: no space, cannot add RR CE entry (%d bytes mising) for %s line %d.\n",
            (CE_SIZE + currlen + (ipnt - recstart) - reclimit),
            field, line);
            errmsgno(EX_BAD, "currlen: %d ipnt: %d, recstart: %d\n",
                        currlen, ipnt, recstart);
            errmsgno(EX_BAD, "Send  bug report to the maintainer.\n");
            comerrno(EX_BAD, "Aborting.\n");
      }

      if (recstart)
            set_733((char *) Rock + recstart - 8, ipnt + 28 - recstart);
      Rock[ipnt++] = 'C';
      Rock[ipnt++] = 'E';
      Rock[ipnt++] = CE_SIZE;
      Rock[ipnt++] = SU_VERSION;
      set_733((char *) Rock + ipnt, 0);
      ipnt += 8;
      set_733((char *) Rock + ipnt, 0);
      ipnt += 8;
      set_733((char *) Rock + ipnt, 0);
      ipnt += 8;
      recstart = ipnt;
      currlen = 0;
      if (!mainrec)
            mainrec = ipnt;
      reclimit = SECTOR_SIZE - 8;   /* Limit to one sector */
}

static int
gen_xa_attr(mode_t attr)
{
      int   ret = 0;

      if (attr & S_IRUSR)
            ret |= XA_O_READ;
      if (attr & S_IXUSR)
            ret |= XA_O_EXEC;

      if (attr & S_IRGRP)
            ret |= XA_G_READ;
      if (attr & S_IXGRP)
            ret |= XA_G_EXEC;

      if (attr & S_IROTH)
            ret |= XA_W_READ;
      if (attr & S_IXOTH)
            ret |= XA_W_EXEC;

      ret |= XA_FORM1;

      if (S_ISDIR(attr))
            ret |= XA_DIR;

      return (ret);
}

static void
gen_xa(struct stat *lstatbuf)
{
            /*
             * Group ID
             */
            set_722((char *) Rock + ipnt, lstatbuf->st_gid);
            ipnt += 2;
            /*
             * User ID
             */
            set_722((char *) Rock + ipnt, lstatbuf->st_uid);
            ipnt += 2;
            /*
             * Attributes
             */
            set_722((char *) Rock + ipnt, gen_xa_attr(lstatbuf->st_mode));
            ipnt += 2;

            Rock[ipnt++] = 'X';     /* XA Signature */
            Rock[ipnt++] = 'A';
            Rock[ipnt++] = 0; /* File number (we always use '0' */

            Rock[ipnt++] = 0; /* Reserved (5 Byte) */
            Rock[ipnt++] = 0;
            Rock[ipnt++] = 0;
            Rock[ipnt++] = 0;
            Rock[ipnt++] = 0;

}

int
generate_xa_rr_attributes(char *whole_name, char *name,
                                                  struct directory_entry *s_entry,
                                                  struct stat *statbuf,
                                                  struct stat *lstatbuf,
                                                  int deep_opt)
{
      int         flagpos;
      int         flagval;
      int         need_ce;

      statbuf = statbuf;      /* this shuts up unreferenced compiler */
                        /* warnings */
      mainrec = recstart = ipnt = 0;

      if (use_XA) {
            gen_xa(lstatbuf);
      }

/*    reclimit = 0xf8; XXX we now use 254 == 0xfe */
      reclimit = MAX_ISODIR;

      /* no need to fill in the RR stuff if we won't see the file */
      if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY)
            return (0);

      /*
       * Obtain the amount of space that is currently used for the directory
       * record.  We may safely use the current name length; because if name
       * confilcts force us to change the ISO-9660 name later, the name will
       * never become longer than now.
       */
      if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
            s_entry->isorec.name_len[0] = 1;
      } else {
            s_entry->isorec.name_len[0] = strlen(s_entry->isorec.name);
      }
      currlen = s_entry->isorec.length[0] = s_entry->isorec.name_len[0] +
                        offsetof(struct iso_directory_record, name[0]);
      if (currlen & 1)
            s_entry->isorec.length[0] = ++currlen;

      if (currlen < 33+37) {
            /*
             * If the ISO-9660 name length is less than 37, we may use
             * ISO-9660:1988 name rules and for this reason, the name len
             * may later increase from adding e.g. ".;1"; in this case
             * just use the upper limit.
             */
            currlen = 33+37;
      }

#ifdef APPLE_HYB
      /* if we have regular file, then add Apple extensions */
      if (S_ISREG(lstatbuf->st_mode) && apple_ext && s_entry->hfs_ent) {
            if (MAYBE_ADD_CE_ENTRY(AA_SIZE))
                  add_CE_entry("AA", __LINE__);
            Rock[ipnt++] = 'A';     /* AppleSignature */
            Rock[ipnt++] = 'A';
            Rock[ipnt++] = AA_SIZE; /* includes AppleSignature bytes */
            Rock[ipnt++] = 0x02;    /* SystemUseID */
            Rock[ipnt++] = s_entry->hfs_ent->u.file.type[0];
            Rock[ipnt++] = s_entry->hfs_ent->u.file.type[1];
            Rock[ipnt++] = s_entry->hfs_ent->u.file.type[2];
            Rock[ipnt++] = s_entry->hfs_ent->u.file.type[3];
            Rock[ipnt++] = s_entry->hfs_ent->u.file.creator[0];
            Rock[ipnt++] = s_entry->hfs_ent->u.file.creator[1];
            Rock[ipnt++] = s_entry->hfs_ent->u.file.creator[2];
            Rock[ipnt++] = s_entry->hfs_ent->u.file.creator[3];
            Rock[ipnt++] = (s_entry->hfs_ent->fdflags >> 8) & 0xff;
            Rock[ipnt++] = s_entry->hfs_ent->fdflags & 0xff;
      }
#endif      /* APPLE_HYB */

      if (!use_RockRidge)
            goto xa_only;

      /* Identify that we are using the SUSP protocol */
      if (deep_opt & NEED_SP) {
            /*
             * We may not use a CE record here but we never will need to
             * do so, as this SP record is only used for the "." entry
             * of the root directory.
             */
            Rock[ipnt++] = 'S';
            Rock[ipnt++] = 'P';
            Rock[ipnt++] = 7;
            Rock[ipnt++] = SU_VERSION;
            Rock[ipnt++] = 0xbe;
            Rock[ipnt++] = 0xef;
            if (use_XA)
                  Rock[ipnt++] = sizeof (struct iso_xa_dir_record);
            else
                  Rock[ipnt++] = 0;
      }

      /* First build the posix name field */
      if (MAYBE_ADD_CE_ENTRY(RR_SIZE))
            add_CE_entry("RR", __LINE__);
      Rock[ipnt++] = 'R';
      Rock[ipnt++] = 'R';
      Rock[ipnt++] = 5;
      Rock[ipnt++] = SU_VERSION;
      flagpos = ipnt;
      flagval = 0;
      Rock[ipnt++] = 0; /* We go back and fix this later */

      if (strcmp(name, ".") && strcmp(name, "..")) {
            char        *npnt;
            int         remain;     /* Remaining name length  */
            int         use;  /* Current name part used */

#ifdef APPLE_HYB
            /* use the HFS name if it exists */
            if (USE_MAC_NAME(s_entry)) {
                  remain = strlen(s_entry->hfs_ent->name);
                  npnt = s_entry->hfs_ent->name;
            } else {
#endif      /* APPLE_HYB */

                  remain = strlen(name);
                  npnt = name;
#ifdef APPLE_HYB
            }
#endif      /* APPLE_HYB */

            if (MAYBE_ADD_CE_ENTRY(NM_SIZE+1))
                  add_CE_entry("NM", __LINE__);
            while (remain) {
                  use = remain;
                  need_ce = 0;
                  /* Can we fit this SUSP and a CE entry? */
                  if (MAYBE_ADD_CE_ENTRY(NM_SIZE+use)) {
                        use = reclimit - NM_SIZE - RR_CUR_USE;
                        need_ce++;
                  }
                  /* Only room for 256 per SUSP field */
                  if (use > 0xf8) {
                        use = 0xf8;
                        need_ce++;
                  }
                  if (use < 0) {
                        comerrno(EX_BAD,
                        "Negative RR name length residual: %d\n",
                              use);
                  }

                  /* First build the posix name field */
                  Rock[ipnt++] = 'N';
                  Rock[ipnt++] = 'M';
                  Rock[ipnt++] = NM_SIZE + use;
                  Rock[ipnt++] = SU_VERSION;
                  Rock[ipnt++] = (remain != use ? 1 : 0);
                  flagval |= (1 << 3);

                  /* convert charsets as required */
#ifdef APPLE_HYB
                  if (USE_MAC_NAME(s_entry))
                        rstrncpy((char *) &Rock[ipnt], npnt, use,
                                          hfs_inls, out_nls);
                  else
#endif      /* APPLE_HYB */
                        rstrncpy((char *) &Rock[ipnt], npnt, use,
                                          in_nls, out_nls);
                  npnt += use;
                  ipnt += use;
                  remain -= use;
                  if (remain && need_ce)
                        add_CE_entry("NM", __LINE__);
            }
      }

      /* Add the posix modes */
      if (MAYBE_ADD_CE_ENTRY(PX_SIZE))
            add_CE_entry("PX", __LINE__);
      Rock[ipnt++] = 'P';
      Rock[ipnt++] = 'X';
      Rock[ipnt++] = PX_SIZE;
      Rock[ipnt++] = SU_VERSION;
      flagval |= (1 << 0);
      set_733((char *) Rock + ipnt, lstatbuf->st_mode);
      ipnt += 8;
      set_733((char *) Rock + ipnt, lstatbuf->st_nlink);
      ipnt += 8;
      set_733((char *) Rock + ipnt, lstatbuf->st_uid);
      ipnt += 8;
      set_733((char *) Rock + ipnt, lstatbuf->st_gid);
      ipnt += 8;

      /* Check for special devices */
#if   defined(S_IFCHR) || defined(S_IFBLK)
      /*
       * The code in this if statement used to be #ifdef'd with NON_UNIXFS.
       * But as statdefs.h always provides the macros S_ISCHR() & S_ISBLK()
       * and device.h always provides major()/minor() it is not needed
       * anymore.
       */
      if (S_ISCHR(lstatbuf->st_mode) || S_ISBLK(lstatbuf->st_mode)) {
            if (MAYBE_ADD_CE_ENTRY(PN_SIZE))
                  add_CE_entry("PN", __LINE__);
            Rock[ipnt++] = 'P';
            Rock[ipnt++] = 'N';
            Rock[ipnt++] = PN_SIZE;
            Rock[ipnt++] = SU_VERSION;
            flagval |= (1 << 1);
#if 1
            /* This is the new and only code which uses <device.h> */
            set_733((char *) Rock + ipnt, major(lstatbuf->st_rdev));
            ipnt += 8;
            set_733((char *) Rock + ipnt, minor(lstatbuf->st_rdev));
            ipnt += 8;
#else
            /*
             * If we don't have sysmacros.h, then we have to guess as to
             * how best to pick apart the device number for major/minor.
             * Note: this may very well be wrong for many systems, so it
             * is always best to use the major/minor macros if the system
             * supports it.
             */
            if (sizeof (dev_t) <= 2) {
                  set_733((char *)Rock + ipnt, (lstatbuf->st_rdev >> 8));
                  ipnt += 8;
                  set_733((char *)Rock + ipnt, lstatbuf->st_rdev & 0xff);
                  ipnt += 8;
            } else if (sizeof (dev_t) <= 4) {
                  set_733((char *)Rock + ipnt,
                                    (lstatbuf->st_rdev >> 8) >> 8);
                  ipnt += 8;
                  set_733((char *)Rock + ipnt,
                                    lstatbuf->st_rdev & 0xffff);
                  ipnt += 8;
            } else {
                  set_733((char *)Rock + ipnt,
                                    (lstatbuf->st_rdev >> 16)>>16);
                  ipnt += 8;
                  set_733((char *)Rock + ipnt, lstatbuf->st_rdev);
                  ipnt += 8;
            }
#endif
      }
#endif      /* defined(S_IFCHR) || defined(S_IFBLK) */

      /* Check for and symbolic links.  VMS does not have these. */
#ifdef S_IFLNK
      if (S_ISLNK(lstatbuf->st_mode)) {
            int         lenpos;
            int         lenval;
            int         j0;
            int         j1;
            int         nchar;
            Uchar       *cpnt;
            Uchar       *cpnt1;

#ifdef      HAVE_READLINK
            nchar = readlink(whole_name, (char *)symlink_buff,
                                    sizeof (symlink_buff)-1);
#else
            nchar = -1;
#endif      /* HAVE_READLINK */
            symlink_buff[nchar < 0 ? 0 : nchar] = 0;
            nchar = strlen((char *) symlink_buff);
            set_733(s_entry->isorec.size, 0);
            cpnt = &symlink_buff[0];
            flagval |= (1 << 2);

            if (!split_SL_field) {
                  int         sl_bytes = 0;

                  for (cpnt1 = cpnt; *cpnt1 != '\0'; cpnt1++) {
                        if (*cpnt1 == '/') {
                              sl_bytes += 4;
                        } else {
                              sl_bytes += 1;
                        }
                  }
                  if (sl_bytes > 250) {
                        /*
                         * the symbolic link won't fit into one
                         * SL System Use Field print an error message
                         * and continue with splited one
                         */
                        fprintf(stderr,
                        "symbolic link ``%s'' to long for one SL System Use Field, splitting",
                                                cpnt);
                  }
                  if (MAYBE_ADD_CE_ENTRY(SL_SIZE + sl_bytes))
                        add_CE_entry("SL+", __LINE__);
            }
            while (nchar) {
                  if (MAYBE_ADD_CE_ENTRY(SL_SIZE))
                        add_CE_entry("SL", __LINE__);
                  Rock[ipnt++] = 'S';
                  Rock[ipnt++] = 'L';
                  lenpos = ipnt;
                  Rock[ipnt++] = SL_SIZE;
                  Rock[ipnt++] = SU_VERSION;
                  Rock[ipnt++] = 0; /* Flags */
                  lenval = 5;
                  while (*cpnt) {
                        cpnt1 = (Uchar *)
                                    strchr((char *)cpnt, '/');
                        if (cpnt1) {
                              nchar--;
                              *cpnt1 = 0;
                        }

                        /*
                         * We treat certain components in a special
                         * way.
                         */
                        if (cpnt[0] == '.' && cpnt[1] == '.' &&
                                                cpnt[2] == 0) {
                              if (MAYBE_ADD_CE_ENTRY(2)) {
                                    add_CE_entry("SL-parent", __LINE__);
                                    if (cpnt1) {
                                          *cpnt1 = '/';
                                          nchar++;
                                          /*
                                           * A kluge so that we
                                           * can restart properly
                                           */
                                          cpnt1 = NULL;
                                    }
                                    break;
                              }
                              Rock[ipnt++] = SL_PARENT;
                              Rock[ipnt++] = 0; /* length is zero */
                              lenval += 2;
                              nchar -= 2;
                        } else if (cpnt[0] == '.' && cpnt[1] == 0) {
                              if (MAYBE_ADD_CE_ENTRY(2)) {
                                    add_CE_entry("SL-current", __LINE__);
                                    if (cpnt1) {
                                          *cpnt1 = '/';
                                          nchar++;
                                          /*
                                           * A kluge so that we
                                           * can restart properly
                                           */
                                          cpnt1 = NULL;
                                    }
                                    break;
                              }
                              Rock[ipnt++] = SL_CURRENT;
                              Rock[ipnt++] = 0; /* length is zero */
                              lenval += 2;
                              nchar -= 1;
                        } else if (cpnt[0] == 0) {
                              if (MAYBE_ADD_CE_ENTRY(2)) {
                                    add_CE_entry("SL-root", __LINE__);
                                    if (cpnt1) {
                                          *cpnt1 = '/';
                                          nchar++;
                                          /*
                                           * A kluge so that we
                                           * can restart properly
                                           */
                                          cpnt1 = NULL;
                                    }
                                    break;
                              }
                              Rock[ipnt++] = SL_ROOT;
                              Rock[ipnt++] = 0; /* length is zero */
                              lenval += 2;
                        } else {
                              /*
                               * If we do not have enough room for a
                               * component, start a new continuations
                               * segment now
                               */
                              if (split_SL_component ?
                                    MAYBE_ADD_CE_ENTRY(6) :
                                    MAYBE_ADD_CE_ENTRY(6 + strlen((char *) cpnt))) {
                                    add_CE_entry("SL++", __LINE__);
                                    if (cpnt1) {
                                          *cpnt1 = '/';
                                          nchar++;
                                          /*
                                           * A kluge so that we
                                           * can restart properly
                                           */
                                          cpnt1 = NULL;
                                    }
                                    break;
                              }
                              j0 = strlen((char *) cpnt);
                              while (j0) {
                                    j1 = j0;
                                    if (j1 > 0xf8)
                                          j1 = 0xf8;
                                    need_ce = 0;
                                    if (j1 + currlen + 2 + CE_SIZE +
                                        (ipnt - recstart) >
                                                reclimit) {

                                          j1 = reclimit -
                                              (currlen + 2) -
                                              CE_SIZE -
                                              (ipnt - recstart);
                                          need_ce++;
                                    }
                                    Rock[ipnt++] =
                                          (j1 != j0 ?
                                          SL_CONTINUE : 0);
                                    Rock[ipnt++] = j1;
                                    strncpy((char *)Rock + ipnt,
                                          (char *) cpnt, j1);
                                    ipnt += j1;
                                    lenval += j1 + 2;
                                    cpnt += j1;
                                    /*
                                     * Number we processed
                                     * this time
                                     */
                                    nchar -= j1;
                                    j0 -= j1;
                                    if (need_ce) {
                                          add_CE_entry(
                                              "SL-path-split",
                                              __LINE__);
                                          if (cpnt1) {
                                                *cpnt1 = '/';
                                                nchar++;
                                                /*
                                                 * A kluge so
                                                 * that we can
                                                 * restart
                                                 * properly
                                                 */
                                                cpnt1 = NULL;
                                          }
                                          break;
                                    }
                              }
                        }
                        if (cpnt1) {
                              cpnt = cpnt1 + 1;
                        } else
                              break;
                  }
                  Rock[lenpos] = lenval;
                  if (nchar) {
                        /* We need another SL entry */
                        Rock[lenpos + 2] = SL_CONTINUE;
                  }
            }     /* while nchar */
      }     /* Is a symbolic link */
#endif      /* S_IFLNK */

      /* Add in the Rock Ridge TF time field */
      if (MAYBE_ADD_CE_ENTRY(TF_SIZE))
            add_CE_entry("TF", __LINE__);
      Rock[ipnt++] = 'T';
      Rock[ipnt++] = 'F';
      Rock[ipnt++] = TF_SIZE;
      Rock[ipnt++] = SU_VERSION;
#if defined(__QNX__) && !defined(__QNXNTO__)    /* Not on Neutrino! never OK? */
      Rock[ipnt++] = 0x0f;
#else
      Rock[ipnt++] = 0x0e;
#endif
      flagval |= (1 << 7);

#if defined(__QNX__) && !defined(__QNXNTO__)    /* Not on Neutrino! never OK? */
      iso9660_date((char *) &Rock[ipnt], lstatbuf->st_ftime);
      ipnt += 7;
#endif
      iso9660_date((char *) &Rock[ipnt], lstatbuf->st_mtime);
      ipnt += 7;
      iso9660_date((char *) &Rock[ipnt], lstatbuf->st_atime);
      ipnt += 7;
      iso9660_date((char *) &Rock[ipnt], lstatbuf->st_ctime);
      ipnt += 7;

      /* Add in the Rock Ridge RE (relocated dir) field */
      if (deep_opt & NEED_RE) {
            if (MAYBE_ADD_CE_ENTRY(RE_SIZE))
                  add_CE_entry("RE", __LINE__);
            Rock[ipnt++] = 'R';
            Rock[ipnt++] = 'E';
            Rock[ipnt++] = RE_SIZE;
            Rock[ipnt++] = SU_VERSION;
            flagval |= (1 << 6);
      }
      /* Add in the Rock Ridge PL record, if required. */
      if (deep_opt & NEED_PL) {
            if (MAYBE_ADD_CE_ENTRY(PL_SIZE))
                  add_CE_entry("PL", __LINE__);
            Rock[ipnt++] = 'P';
            Rock[ipnt++] = 'L';
            Rock[ipnt++] = PL_SIZE;
            Rock[ipnt++] = SU_VERSION;
            set_733((char *) Rock + ipnt, 0);
            ipnt += 8;
            flagval |= (1 << 5);
      }

      /* Add in the Rock Ridge CL field, if required. */
      if (deep_opt & NEED_CL) {
            if (MAYBE_ADD_CE_ENTRY(CL_SIZE))
                  add_CE_entry("CL", __LINE__);
            Rock[ipnt++] = 'C';
            Rock[ipnt++] = 'L';
            Rock[ipnt++] = CL_SIZE;
            Rock[ipnt++] = SU_VERSION;
            set_733((char *) Rock + ipnt, 0);
            ipnt += 8;
            flagval |= (1 << 4);
      }

#ifndef VMS
      /*
       * If transparent compression was requested, fill in the correct field
       * for this file, if (and only if) it is actually a compressed file!
       * This relies only on magic number, but it should in general not
       * be an issue since if you're using -z odds are most of your
       * files are already compressed.
       *
       * In the future it would be nice if genisoimage actually did the
       * compression.
       */
      if (transparent_compression && S_ISREG(lstatbuf->st_mode)) {
            static const Uchar zisofs_magic[8] =
                  { 0x37, 0xE4, 0x53, 0x96, 0xC9, 0xDB, 0xD6, 0x07 };
            FILE        *zffile;
            unsigned int      file_size;
            Uchar       header[16];
            int         OK_flag;
            int         blocksize;
            int         headersize;

            /*
             * First open file and verify that the correct algorithm was
             * used
             */
            file_size = 0;
            OK_flag = 1;

            memset(header, 0, sizeof (header));

            zffile = fopen(whole_name, "rb");
            if (zffile != NULL) {
                  if (fread(header, 1, sizeof (header), zffile) != sizeof (header))
                        OK_flag = 0;

                  /* Check magic number */
                  if (memcmp(header, zisofs_magic, sizeof (zisofs_magic)))
                        OK_flag = 0;

                  /* Get the real size of the file */
                  file_size = get_731((char *)header+8);

                  /* Get the header size (>> 2) */
                  headersize = header[12];

                  /* Get the block size (log2) */
                  blocksize = header[13];

                  fclose(zffile);
            } else {
                  OK_flag = 0;
                  blocksize = headersize = 0; /* Make silly GCC quiet */
            }

            if (OK_flag) {
                  if (MAYBE_ADD_CE_ENTRY(ZF_SIZE))
                        add_CE_entry("ZF", __LINE__);
                  Rock[ipnt++] = 'Z';
                  Rock[ipnt++] = 'F';
                  Rock[ipnt++] = ZF_SIZE;
                  Rock[ipnt++] = SU_VERSION;
                  Rock[ipnt++] = 'p'; /* Algorithm: "paged zlib" */
                  Rock[ipnt++] = 'z';
                  /* 2 bytes for algorithm-specific information */
                  Rock[ipnt++] = headersize;
                  Rock[ipnt++] = blocksize;
                  set_733((char *) Rock + ipnt, file_size); /* Real file size */
                  ipnt += 8;
            }
      }
#endif
      /*
       * Add in the Rock Ridge CE field, if required.  We use  this for the
       * extension record that is stored in the root directory.
       */
      if (deep_opt & NEED_CE)
            add_CE_entry("ER", __LINE__);

      /*
       * Done filling in all of the fields.  Now copy it back to a buffer
       * for the file in question.
       */
      /* Now copy this back to the buffer for the file */
      Rock[flagpos] = flagval;

      /* If there was a CE, fill in the size field */
      if (recstart)
            set_733((char *) Rock + recstart - 8, ipnt - recstart);

xa_only:
      s_entry->rr_attributes = (Uchar *) e_malloc(ipnt);
      s_entry->total_rr_attr_size = ipnt;
      s_entry->rr_attr_size = (mainrec ? mainrec : ipnt);
      memcpy(s_entry->rr_attributes, Rock, ipnt);
      return (ipnt);
}

/*
 * Guaranteed to  return a single sector with the relevant info
 */
char *
generate_rr_extension_record(char *id, char *descriptor, char *source, 
                                                        int *size)
{
      int         lipnt = 0;
      char        *pnt;
      int         len_id;
      int         len_des;
      int         len_src;

      len_id = strlen(id);
      len_des = strlen(descriptor);
      len_src = strlen(source);
      Rock[lipnt++] = 'E';
      Rock[lipnt++] = 'R';
      Rock[lipnt++] = ER_SIZE + len_id + len_des + len_src;
      Rock[lipnt++] = 1;
      Rock[lipnt++] = len_id;
      Rock[lipnt++] = len_des;
      Rock[lipnt++] = len_src;
      Rock[lipnt++] = 1;

      memcpy(Rock + lipnt, id, len_id);
      lipnt += len_id;

      memcpy(Rock + lipnt, descriptor, len_des);
      lipnt += len_des;

      memcpy(Rock + lipnt, source, len_src);
      lipnt += len_src;

      if (lipnt > SECTOR_SIZE) {
#ifdef      USE_LIBSCHILY
            comerrno(EX_BAD, "Extension record too long\n");
#else
            fprintf(stderr, "Extension record too long\n");
            exit(1);
#endif
      }
      pnt = (char *) e_malloc(SECTOR_SIZE);
      memset(pnt, 0, SECTOR_SIZE);
      memcpy(pnt, Rock, lipnt);
      *size = lipnt;
      return (pnt);
}

Generated by  Doxygen 1.6.0   Back to index