libcdio-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Libcdio-devel] modifications of ISO9660 and UDF headers for MSVC


From: Rocky Bernstein
Subject: Re: [Libcdio-devel] modifications of ISO9660 and UDF headers for MSVC
Date: Sun, 29 Jan 2012 21:28:01 -0500

On Sun, Jan 29, 2012 at 12:39 PM, Pete Batard <address@hidden> wrote:

> Two additional patches that modify the ISO9660 and UDF headers for MSVC
> usage.
>
> The most controversial has to be the ISO9660 as MSVC simply cannot use a
> zero sized array, even at the end of a struct, if that struct is going to
> be included in the middle of another.
>
> Therefore, instead of defining:
>
>     iso711_t filename_len;
>     char     filename[];
>
> We leverage the fact that iso711_t and char are the same size and the
> following union:
>
> union {
>     iso711_t        len;
>     char            str[1];
> } filename;
>
> This avoids the use of an empty array, while most of the existing code
> unchanged. The only gotcha however is that the actual string payload of
> filename.str[] starts at 1, not 0.
>
> I'm hoping this is acceptable as a workaround, as dealing with zero sized
> arrays is the one item we cannot avoid for MSVC support.
>

It is exactly for changes like this that I wish there were more preexisting
tests. Still, it is not too late to start going forth.


>
> I guess these can be construed as API change, so probably warrant an API
> bump.
>

Yep.


>
> Regards,
>
> /Pete
>
> From c40dd3269e049611cc1f53e01b1d0bec0fb50957 Mon Sep 17 00:00:00 2001
> From: Pete Batard <address@hidden>
> Date: Sun, 29 Jan 2012 17:15:50 +0000
> Subject: [PATCH 1/3] ISO9660: fix iso9660.h header for MSVC compatibility
>
> * MSVC compilers cannot handle a zero sized array in the middle
>  of a struct, and iso9660_dir_s is reused within iso9660_pvd_s.
> * Leverage the fact that iso711_t and char are the same size and
>  use an union.
> * The only gotcha is that the actual string payload now starts at 1
> * also fix the use of pre_user_data as MSVC cannot use a const to
>  initialize the size of an array
> ---
>  include/cdio/iso9660.h   |   14 ++++++++++++--
>  lib/iso9660/iso9660.c    |    4 ++--
>  lib/iso9660/iso9660_fs.c |   26 ++++++++++++--------------
>  lib/iso9660/rock.c       |    8 ++++----
>  4 files changed, 30 insertions(+), 22 deletions(-)
>
> diff --git a/include/cdio/iso9660.h b/include/cdio/iso9660.h
> index 4f5786f..c6ddf64 100644
> --- a/include/cdio/iso9660.h
> +++ b/include/cdio/iso9660.h
> @@ -273,8 +273,18 @@ struct iso9660_dir_s {
>                                           the Extent described by this
>                                           Directory Record is
>                                           recorded. (9.1.9) */
> -  iso711_t         filename_len;      /*! number of bytes in filename
> field */
> -  char             filename[EMPTY_ARRAY_SIZE];
> +/*! MSVC compilers cannot handle a zero sized array in the middle
> +    of a struct, and iso9660_dir_s is reused within iso9660_pvd_s.
> +    Therefore, instead of defining:
> +       iso711_t filename_len;
> +       char     filename[];
> +    we leverage the fact that iso711_t and char are the same size
> +    and use an union. The only gotcha is that the actual string
> +    payload of filename.str[] starts at 1, not 0. */
> +  union {
> +    iso711_t        len;
> +    char            str[1];
> +  } filename;
>  } GNUC_PACKED;
>
>  /*!
> diff --git a/lib/iso9660/iso9660.c b/lib/iso9660/iso9660.c
> index e06ebad..6edd7bd 100644
> --- a/lib/iso9660/iso9660.c
> +++ b/lib/iso9660/iso9660.c
> @@ -771,10 +771,10 @@ iso9660_dir_add_entry_su(void *dir,
>
>   idr->volume_sequence_number = to_723(1);
>
> -  idr->filename_len = to_711(strlen(filename)
> +  idr->filename.len = to_711(strlen(filename)
>                              ? strlen(filename) : 1); /* working hack! */
>
> -  memcpy(idr->filename, filename, from_711(idr->filename_len));
> +  memcpy(&idr->filename.str[1], filename, from_711(idr->filename.len));
>   memcpy(&dir8[offset] + su_offset, su_data, su_size);
>  }
>
> diff --git a/lib/iso9660/iso9660_fs.c b/lib/iso9660/iso9660_fs.c
> index ff62077..61f8560 100644
> --- a/lib/iso9660/iso9660_fs.c
> +++ b/lib/iso9660/iso9660_fs.c
> @@ -107,12 +107,10 @@ adjust_fuzzy_pvd( iso9660_t *p_iso )
>      frame and a header.
>    */
>   if (CDIO_CD_FRAMESIZE_RAW == p_iso->i_framesize) {
> -    const int pre_user_data=CDIO_CD_SYNC_SIZE +  CDIO_CD_HEADER_SIZE
> -      + CDIO_CD_SUBHEADER_SIZE;
> -    char buf[pre_user_data];
> -
> -    i_byte_offset -= pre_user_data;
> -
> +    char buf[CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE +
> CDIO_CD_SUBHEADER_SIZE];
> +
> +    i_byte_offset -= CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE +
> CDIO_CD_SUBHEADER_SIZE;
> +
>     if ( DRIVER_OP_SUCCESS != cdio_stream_seek (p_iso->stream,
> i_byte_offset,
>                                                SEEK_SET) )
>       return;
> @@ -739,7 +737,7 @@ _iso9660_dir_to_statbuf (iso9660_dir_t *p_iso9660_dir,
> bool_3way_t b_xa,
>
>   if (!dir_len) return NULL;
>
> -  i_fname  = from_711(p_iso9660_dir->filename_len);
> +  i_fname  = from_711(p_iso9660_dir->filename.len);
>
>   /* .. string in statbuf is one longer than in p_iso9660_dir's listing
> '\1' */
>   stat_len      = sizeof(iso9660_stat_t)+i_fname+2;
> @@ -784,15 +782,15 @@ _iso9660_dir_to_statbuf (iso9660_dir_t
> *p_iso9660_dir, bool_3way_t b_xa,
>       }
>       strncpy(p_stat->filename, rr_fname, i_rr_fname+1);
>     } else {
> -      if ('\0' == p_iso9660_dir->filename[0] && 1 == i_fname)
> +      if ('\0' == p_iso9660_dir->filename.str[1] && 1 == i_fname)
>        strncpy (p_stat->filename, ".", sizeof("."));
> -      else if ('\1' == p_iso9660_dir->filename[0] && 1 == i_fname)
> +      else if ('\1' == p_iso9660_dir->filename.str[1] && 1 == i_fname)
>        strncpy (p_stat->filename, "..", sizeof(".."));
>  #ifdef HAVE_JOLIET
>       else if (i_joliet_level) {
>        int i_inlen = i_fname;
>        cdio_utf8_t *p_psz_out = NULL;
> -       if (cdio_charset_to_utf8(p_iso9660_dir->filename, i_inlen,
> +       if (cdio_charset_to_utf8(&p_iso9660_dir->filename.str[1], i_inlen,
>                              &p_psz_out, "UCS-2BE")) {
>           strncpy(p_stat->filename, p_psz_out, i_fname);
>           free(p_psz_out);
> @@ -804,7 +802,7 @@ _iso9660_dir_to_statbuf (iso9660_dir_t *p_iso9660_dir,
> bool_3way_t b_xa,
>       }
>  #endif /*HAVE_JOLIET*/
>       else {
> -       strncpy (p_stat->filename, p_iso9660_dir->filename, i_fname);
> +       strncpy (p_stat->filename, &p_iso9660_dir->filename.str[1],
> i_fname);
>       }
>     }
>   }
> @@ -878,12 +876,12 @@ iso9660_dir_to_name (const iso9660_dir_t
> *iso9660_dir)
>
>   /* (iso9660_dir->file_flags & ISO_DIRECTORY) */
>
> -  if (iso9660_dir->filename[0] == '\0')
> +  if (iso9660_dir->filename.str[1] == '\0')
>     return strdup(".");
> -  else if (iso9660_dir->filename[0] == '\1')
> +  else if (iso9660_dir->filename.str[1] == '\1')
>     return strdup("..");
>   else {
> -    return strdup(iso9660_dir->filename);
> +    return strdup(&iso9660_dir->filename.str[1]);
>   }
>  }
>
> diff --git a/lib/iso9660/rock.c b/lib/iso9660/rock.c
> index 1a91297..1a887c3 100644
> --- a/lib/iso9660/rock.c
> +++ b/lib/iso9660/rock.c
> @@ -105,7 +105,7 @@ realloc_symlink(/*in/out*/ iso9660_stat_t *p_stat,
> uint8_t i_grow)
>
>  #define SETUP_ROCK_RIDGE(DE,CHR,LEN)                           \
>   {                                                            \
> -    LEN= sizeof(iso9660_dir_t) + DE->filename_len;             \
> +    LEN= sizeof(iso9660_dir_t) + DE->filename.len;             \
>     if(LEN & 1) LEN++;                                         \
>     CHR = ((unsigned char *) DE) + LEN;                                \
>     LEN = *((unsigned char *) DE) - LEN;                       \
> @@ -178,10 +178,10 @@ get_rock_ridge_filename(iso9660_dir_t *
> p_iso9660_dir,
>        break;
>       case SIG('C','E'):
>        {
> -         iso711_t i_fname = from_711(p_iso9660_dir->filename_len);
> -         if ('\0' == p_iso9660_dir->filename[0] && 1 == i_fname)
> +         iso711_t i_fname = from_711(p_iso9660_dir->filename.len);
> +         if ('\0' == p_iso9660_dir->filename.str[1] && 1 == i_fname)
>            break;
> -         if ('\1' == p_iso9660_dir->filename[0] && 1 == i_fname)
> +         if ('\1' == p_iso9660_dir->filename.str[1] && 1 == i_fname)
>            break;
>        }
>        CHECK_CE;
> --
> 1.7.8.msysgit.0
>
>
> From 2d92744537978446cea3cd4bfe4ae583c3747995 Mon Sep 17 00:00:00 2001
> From: Pete Batard <address@hidden>
> Date: Sun, 29 Jan 2012 17:21:08 +0000
> Subject: [PATCH 2/3] UDF: fix ecma_167.h header for MSVC compatibility
>
> * multiple zero sized arrays are not allowed with MSVC
> * use an union of zero sized arrays instead
> ---
>  include/cdio/ecma_167.h |   22 ++++++++++++++--------
>  lib/udf/udf_fs.c        |    2 +-
>  2 files changed, 15 insertions(+), 9 deletions(-)
>
> diff --git a/include/cdio/ecma_167.h b/include/cdio/ecma_167.h
> index 9c7c1bb..b97cba7 100644
> --- a/include/cdio/ecma_167.h
> +++ b/include/cdio/ecma_167.h
> @@ -499,9 +499,11 @@ struct logvol_integrity_desc_s
>   udf_Uint8_t     logvol_contents_use[32];
>   udf_Uint32_t    i_partitions;
>   udf_Uint32_t    imp_use_len;
> -  udf_Uint32_t    freespace_table[0];
> -  udf_Uint32_t    size_table[0];
> -  udf_Uint8_t     imp_use[0];
> +  union { /* MSVC workaround for multiple zero sized arrays */
> +    udf_Uint32_t  freespace_table[0];
> +    udf_Uint32_t  size_table[0];
> +    udf_Uint8_t   imp_use[0];
> +  } u;
>  } GNUC_PACKED;
>
>  /** Integrity Type (ECMA 167r3 3/10.10.3) */
> @@ -571,9 +573,11 @@ struct udf_fileid_desc_s
>   udf_Uint8_t  i_file_id;
>   udf_long_ad_t        icb;
>   udf_Uint16_t i_imp_use;
> -  udf_Uint8_t  imp_use[0];
> -  udf_Uint8_t  file_id[0];
> -  udf_Uint8_t  padding[0];
> +  union { /* MSVC workaround for multiple zero sized arrays */
> +    udf_Uint8_t        imp_use[0];
> +    udf_Uint8_t        file_id[0];
> +    udf_Uint8_t        padding[0];
> +  } u;
>  } GNUC_PACKED;
>
>  typedef struct udf_fileid_desc_s udf_fileid_desc_t;
> @@ -991,8 +995,10 @@ struct extended_file_entry
>   udf_Uint64_t    unique_ID;
>   udf_Uint32_t    length_extended_attr;
>   udf_Uint32_t    length_alloc_descs;
> -  udf_Uint8_t     ext_attr[0];
> -  udf_Uint8_t     alloc_descs[0];
> +  union { /* MSVC workaround for multiple zero sized arrays */
> +    udf_Uint8_t   ext_attr[0];
> +    udf_Uint8_t   alloc_descs[0];
> +  } u;
>  } GNUC_PACKED;
>
>  PRAGMA_END_PACKED
> diff --git a/lib/udf/udf_fs.c b/lib/udf/udf_fs.c
> index 1669bc2..d99c9a4 100644
> --- a/lib/udf/udf_fs.c
> +++ b/lib/udf/udf_fs.c
> @@ -681,7 +681,7 @@ udf_readdir(udf_dirent_t *p_udf_dirent)
>          p_udf_dirent->psz_name = (char *)
>            realloc(p_udf_dirent->psz_name, sizeof(char)*i_len+1);
>
> -       unicode16_decode(p_udf_dirent->fid->imp_use
> +       unicode16_decode(p_udf_dirent->fid->u.imp_use
>                         + p_udf_dirent->fid->i_imp_use,
>                         i_len, p_udf_dirent->psz_name);
>       }
> --
> 1.7.8.msysgit.0
>
>
>


reply via email to

[Prev in Thread] Current Thread [Next in Thread]