Blame example/isofile2.c

Packit dd8086
/*
Packit dd8086
  Copyright (C) 2003-2006, 2009, 2013 Rocky Bernstein <rocky@gnu.org>
Packit dd8086
Packit dd8086
  This program is free software: you can redistribute it and/or modify
Packit dd8086
  it under the terms of the GNU General Public License as published by
Packit dd8086
  the Free Software Foundation, either version 3 of the License, or
Packit dd8086
  (at your option) any later version.
Packit dd8086
Packit dd8086
  This program is distributed in the hope that it will be useful,
Packit dd8086
  but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit dd8086
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit dd8086
  GNU General Public License for more details.
Packit dd8086
Packit dd8086
  You should have received a copy of the GNU General Public License
Packit dd8086
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
Packit dd8086
*/
Packit dd8086
Packit dd8086
/* Simple program to show using libiso9660 to extract a file from a
Packit dd8086
   CUE/BIN CD image.
Packit dd8086
Packit dd8086
   If a single argument is given, it is used as the CUE file of a CD image
Packit dd8086
   to use. Otherwise a compiled-in default image name (that
Packit dd8086
   comes with the libcdio distribution) will be used.
Packit dd8086
Packit dd8086
   This program can be compiled with either a C or C++ compiler. In
Packit dd8086
   the distribution we prefer C++ just to make sure we haven't broken
Packit dd8086
   things on the C++ side.
Packit dd8086
 */
Packit dd8086
Packit dd8086
/* This is the CD-image with an ISO-9660 filesystem */
Packit dd8086
#define ISO9660_IMAGE_PATH "../"
Packit dd8086
#define ISO9660_IMAGE ISO9660_IMAGE_PATH "test/data/isofs-m1.cue"
Packit dd8086
Packit dd8086
#define ISO9660_PATH "/"
Packit dd8086
#define ISO9660_FILENAME "COPYING"
Packit dd8086
#define LOCAL_FILENAME "copying"
Packit dd8086
Packit dd8086
/* portable.h has to come first else _FILE_OFFSET_BITS are redefined in
Packit dd8086
   say opensolaris. */
Packit dd8086
#include "portable.h"
Packit dd8086
Packit dd8086
#ifdef HAVE_SYS_TYPES_H
Packit dd8086
#include <sys/types.h>
Packit dd8086
#endif
Packit dd8086
#ifdef HAVE_STDLIB_H
Packit dd8086
#include <stdlib.h>
Packit dd8086
#endif
Packit dd8086
#ifdef HAVE_STDIO_H
Packit dd8086
#include <stdio.h>
Packit dd8086
#endif
Packit dd8086
#ifdef HAVE_ERRNO_H
Packit dd8086
#include <errno.h>
Packit dd8086
#endif
Packit dd8086
#ifdef HAVE_STRING_H
Packit dd8086
#include <string.h>
Packit dd8086
#endif
Packit dd8086
#ifdef HAVE_UNISTD_H
Packit dd8086
#include <unistd.h>
Packit dd8086
#endif
Packit dd8086
#ifdef HAVE_SYS_TYPES_H
Packit dd8086
#include <sys/types.h>
Packit dd8086
#endif
Packit dd8086
Packit dd8086
#include <cdio/cdio.h>
Packit dd8086
#include <cdio/iso9660.h>
Packit dd8086
#include <cdio/logging.h>
Packit dd8086
Packit dd8086
#define CEILING(x, y) ((x+(y-1))/y)
Packit dd8086
Packit dd8086
#define my_exit(rc)				\
Packit dd8086
  fclose (p_outfd);				\
Packit dd8086
  free(p_statbuf);				\
Packit dd8086
  cdio_destroy(p_cdio);				\
Packit dd8086
  return rc;					\
Packit dd8086
Packit dd8086
Packit dd8086
int
Packit dd8086
main(int argc, const char *argv[])
Packit dd8086
{
Packit dd8086
  iso9660_stat_t *p_statbuf;
Packit dd8086
  FILE *p_outfd;
Packit dd8086
  int i;
Packit dd8086
  char const *psz_image;
Packit dd8086
  char const *psz_fname;
Packit dd8086
  char translated_name[256];
Packit dd8086
  char untranslated_name[256] = ISO9660_PATH;
Packit dd8086
  CdIo_t *p_cdio;
Packit dd8086
  unsigned int i_fname=sizeof(ISO9660_FILENAME);
Packit dd8086
Packit dd8086
  if (argc > 3) {
Packit dd8086
    printf("usage %s [CD-ROM-or-image [filename]]\n", argv[0]);
Packit dd8086
    printf("Extracts filename from CD-ROM-or-image.\n");
Packit dd8086
    return 1;
Packit dd8086
  }
Packit dd8086
Packit dd8086
  if (argc > 1)
Packit dd8086
    psz_image = argv[1];
Packit dd8086
  else
Packit dd8086
    psz_image = ISO9660_IMAGE;
Packit dd8086
Packit dd8086
  if (argc > 2) {
Packit dd8086
    psz_fname = argv[2];
Packit dd8086
    i_fname   = strlen(psz_fname)+1;
Packit dd8086
  } else
Packit dd8086
    psz_fname = ISO9660_FILENAME;
Packit dd8086
Packit dd8086
  strncat(untranslated_name, psz_fname, i_fname);
Packit dd8086
Packit dd8086
  // cdio_loglevel_default = CDIO_LOG_DEBUG;
Packit dd8086
Packit dd8086
  p_cdio = cdio_open (psz_image, DRIVER_UNKNOWN);
Packit dd8086
  if (!p_cdio) {
Packit dd8086
    fprintf(stderr, "Sorry, couldn't open %s\n", psz_image);
Packit dd8086
    return 1;
Packit dd8086
  }
Packit dd8086
Packit dd8086
  p_statbuf = iso9660_fs_stat (p_cdio, untranslated_name);
Packit dd8086
Packit dd8086
  if (NULL == p_statbuf)
Packit dd8086
    {
Packit dd8086
      fprintf(stderr,
Packit dd8086
	      "Could not get ISO-9660 file information for file %s\n",
Packit dd8086
	      untranslated_name);
Packit dd8086
      cdio_destroy(p_cdio);
Packit dd8086
      return 2;
Packit dd8086
    }
Packit dd8086
Packit dd8086
  iso9660_name_translate(psz_fname, translated_name);
Packit dd8086
Packit dd8086
  if (!(p_outfd = fopen (translated_name, "wb"))) {
Packit dd8086
      perror ("fopen()");
Packit dd8086
      cdio_destroy(p_cdio);
Packit dd8086
      free(p_statbuf);
Packit dd8086
      return 3;
Packit dd8086
    }
Packit dd8086
Packit dd8086
  /* Copy the blocks from the ISO-9660 filesystem to the local filesystem. */
Packit dd8086
  {
Packit dd8086
    const unsigned int i_blocks = CEILING(p_statbuf->size, ISO_BLOCKSIZE);
Packit dd8086
    for (i = 0; i < i_blocks; i ++) {
Packit dd8086
	char buf[ISO_BLOCKSIZE];
Packit dd8086
	const lsn_t lsn = p_statbuf->lsn + i;
Packit dd8086
Packit dd8086
	memset (buf, 0, ISO_BLOCKSIZE);
Packit dd8086
Packit dd8086
	if ( 0 != cdio_read_data_sectors (p_cdio, buf, lsn, ISO_BLOCKSIZE, 1) )
Packit dd8086
	  {
Packit dd8086
	    fprintf(stderr, "Error reading ISO 9660 file at lsn %lu\n",
Packit dd8086
		    (long unsigned int) p_statbuf->lsn);
Packit dd8086
	    my_exit(4);
Packit dd8086
	  }
Packit dd8086
Packit dd8086
	fwrite (buf, ISO_BLOCKSIZE, 1, p_outfd);
Packit dd8086
Packit dd8086
	if (ferror (p_outfd)) {
Packit dd8086
	    perror ("fwrite()");
Packit dd8086
	    my_exit(5);
Packit dd8086
	}
Packit dd8086
      }
Packit dd8086
  }
Packit dd8086
Packit dd8086
Packit dd8086
  fflush (p_outfd);
Packit dd8086
Packit dd8086
  /* Make sure the file size has the exact same byte size. Without the
Packit dd8086
     truncate below, the file will a multiple of ISO_BLOCKSIZE.
Packit dd8086
   */
Packit dd8086
  if (ftruncate (fileno (p_outfd), p_statbuf->size))
Packit dd8086
    perror ("ftruncate()");
Packit dd8086
Packit dd8086
  printf("-- Extraction of file '%s' from '%s' successful.\n",
Packit dd8086
	 translated_name, untranslated_name);
Packit dd8086
Packit dd8086
  my_exit(0);
Packit dd8086
}