cdrom.c
author nathan
Sat, 29 Dec 2007 15:22:44 +0100
branchtrunk
changeset 1 6b6864d2c4ce
parent 0 d85c12073dea
child 2 6bcb44b9edb1
permissions -rw-r--r--
Added tag 0.6.2 for changeset d85c12073dea
nathan@0
     1
/* cdrom.c
nathan@0
     2
Copyright (c) 2000-2002 Craig Condit, Stefan Hülswitt.
nathan@0
     3
nathan@0
     4
Redistribution and use in source and binary forms, with or without
nathan@0
     5
modification, are permitted provided that the following conditions are met: 
nathan@0
     6
nathan@0
     7
1. Redistributions of source code must retain the above copyright notice,
nathan@0
     8
   this list of conditions and the following disclaimer. 
nathan@0
     9
2. Redistributions in binary form must reproduce the above copyright notice,
nathan@0
    10
   this list of conditions and the following disclaimer in the documentation
nathan@0
    11
   and/or other materials provided with the distribution. 
nathan@0
    12
nathan@0
    13
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
nathan@0
    14
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
nathan@0
    15
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
nathan@0
    16
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
nathan@0
    17
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
nathan@0
    18
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
nathan@0
    19
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
nathan@0
    20
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
nathan@0
    21
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
nathan@0
    22
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
nathan@0
    23
SUCH DAMAGE.
nathan@0
    24
*/
nathan@0
    25
nathan@0
    26
#define _LARGEFILE64_SOURCE
nathan@0
    27
nathan@0
    28
#include <stdlib.h>
nathan@0
    29
#include <stdio.h>
nathan@0
    30
#include <unistd.h>
nathan@0
    31
#include <fcntl.h>
nathan@0
    32
#include <string.h>
nathan@0
    33
#include <linux/cdrom.h>
nathan@0
    34
#include <sys/ioctl.h>
nathan@0
    35
nathan@0
    36
#include "cdbackup.h"
nathan@0
    37
#include "misc.h"
nathan@0
    38
nathan@0
    39
/* size of leadin/out depending of how many tracks are on cd */
nathan@0
    40
#define MIN_FREE_1	(11400*CD_FRAMESIZE) /* 1th track */
nathan@0
    41
#define MIN_FREE_2	(6900*CD_FRAMESIZE)  /* 2nd and more tracks */
nathan@0
    42
nathan@0
    43
struct toc_entry *toc=0;
nathan@0
    44
long long cd_used, cd_avail;
nathan@0
    45
nathan@0
    46
extern long cd_len;
nathan@0
    47
extern int verbose;
nathan@0
    48
extern char *prg_name;
nathan@0
    49
nathan@0
    50
/****************************************************************************/
nathan@0
    51
nathan@0
    52
int open_cdr(char *device) 
nathan@0
    53
{
nathan@0
    54
  return open(device, O_RDONLY | O_NONBLOCK);
nathan@0
    55
}
nathan@0
    56
nathan@0
    57
/****************************************************************************/
nathan@0
    58
nathan@0
    59
void close_cdr(int cd_fd)
nathan@0
    60
{
nathan@0
    61
  close(cd_fd);
nathan@0
    62
}
nathan@0
    63
nathan@0
    64
/****************************************************************************/
nathan@0
    65
nathan@0
    66
int full_read(int fd, void *buf, int count)
nathan@0
    67
{
nathan@0
    68
  int total=0;
nathan@0
    69
nathan@0
    70
  while(count>0) {
nathan@0
    71
    int bytes;
nathan@0
    72
    bytes=read(fd,buf,count); if(bytes<0) return bytes;
nathan@0
    73
    if(bytes==0) break;
nathan@0
    74
    count-=bytes; total+=bytes; buf+=bytes;
nathan@0
    75
    }
nathan@0
    76
  return total;
nathan@0
    77
}
nathan@0
    78
nathan@0
    79
/****************************************************************************/
nathan@0
    80
nathan@0
    81
void free_toc()
nathan@0
    82
{
nathan@0
    83
  if(toc) { free(toc); toc=0; }
nathan@0
    84
}
nathan@0
    85
nathan@0
    86
/****************************************************************************/
nathan@0
    87
nathan@0
    88
int read_toc(int cd_fd, int trackinfos)
nathan@0
    89
{
nathan@0
    90
  int i;
nathan@0
    91
  struct cdrom_tochdr cd_header;
nathan@0
    92
  struct cdrom_tocentry cd_entry;
nathan@0
    93
  int tracks,start_track;
nathan@0
    94
 
nathan@0
    95
  /* read table of contents header */
nathan@0
    96
  if(ioctl(cd_fd,CDROMREADTOCHDR,&cd_header)) {
nathan@0
    97
    if(verbose) fprintf(stderr,"%s: Unable to read CD header, assuming empty CD-R\n", prg_name);
nathan@0
    98
    cd_used=0; cd_avail=(long long)cd_len*CD_FRAMESIZE; return 0;
nathan@0
    99
    }
nathan@0
   100
nathan@0
   101
  /* get start and end tracks */
nathan@0
   102
  start_track = cd_header.cdth_trk0;
nathan@0
   103
  tracks = cd_header.cdth_trk1-start_track+1;
nathan@0
   104
nathan@0
   105
  free_toc();
nathan@0
   106
  if(!(toc=calloc(tracks+1,sizeof(struct toc_entry)))) serror("No memory for TOC");
nathan@0
   107
nathan@0
   108
  /* set some parameters */
nathan@0
   109
  cd_entry.cdte_format=CDROM_LBA;
nathan@0
   110
nathan@0
   111
  /* read lead-out */
nathan@0
   112
  cd_entry.cdte_track=CDROM_LEADOUT;
nathan@0
   113
  if(ioctl(cd_fd,CDROMREADTOCENTRY,&cd_entry)) error("Error reading lead-out");
nathan@0
   114
nathan@0
   115
  toc[0].track_no=CDROM_LEADOUT;  /* not a real track */
nathan@0
   116
  toc[0].sec_start=cd_entry.cdte_addr.lba;
nathan@0
   117
nathan@0
   118
  cd_used=(long long)toc[0].sec_start*CD_FRAMESIZE; cd_avail=(long long)cd_len*CD_FRAMESIZE-cd_used;
nathan@0
   119
  cd_avail-=(tracks>1?MIN_FREE_2:MIN_FREE_1);
nathan@0
   120
  if(cd_avail<0) cd_avail=0; /* can be <0 due to assumed additional lead-in/out */
nathan@0
   121
nathan@0
   122
  /* read rest of tracks */
nathan@0
   123
  for(i=1; i<=tracks; i++) {
nathan@0
   124
    cd_entry.cdte_track=start_track+i-1;
nathan@0
   125
    if(ioctl(cd_fd,CDROMREADTOCENTRY,&cd_entry)) error("Error reading TOC");  
nathan@0
   126
nathan@0
   127
    toc[i].track_no=start_track+i-1;
nathan@0
   128
    toc[i].sec_start=cd_entry.cdte_addr.lba;
nathan@0
   129
    if(cd_entry.cdte_ctrl&CDROM_DATA_TRACK) toc[i].is_data=1;
nathan@0
   130
    }    
nathan@0
   131
nathan@0
   132
 if(trackinfos)
nathan@0
   133
  /* now loop through tracks and read header info */
nathan@0
   134
  for(i=1; i<=tracks; i++) {
nathan@0
   135
    char inbuffer[CD_FRAMESIZE];
nathan@0
   136
    struct header_block *track_header=(struct header_block *)&inbuffer[0];
nathan@0
   137
nathan@0
   138
    if (toc[i].is_data == 1) {
nathan@0
   139
      if(lseek64(cd_fd,(long long)toc[i].sec_start*CD_FRAMESIZE,SEEK_SET)<0) error("Seek failed");
nathan@0
   140
nathan@0
   141
      if(full_read(cd_fd,inbuffer,CD_FRAMESIZE)==CD_FRAMESIZE) {
nathan@0
   142
        if(!strncmp(SHORT_HDR,track_header->id_str,strlen(SHORT_HDR))) {
nathan@0
   143
          toc[i].is_cdbackup=1;
nathan@0
   144
          strncpy(toc[i].id_str,track_header->id_str,32); toc[i].id_str[32]=0;
nathan@0
   145
          strncpy(toc[i].vol_id, track_header->vol_id,32); toc[i].vol_id[32]=0;
nathan@0
   146
          strncpy(toc[i].t_stamp, track_header->t_stamp,12); toc[i].t_stamp[12]=0;
nathan@0
   147
          toc[i].disk_set = track_header->disk_set;
nathan@0
   148
          }
nathan@0
   149
        }      
nathan@0
   150
      }
nathan@0
   151
    }
nathan@0
   152
  
nathan@0
   153
  return tracks;
nathan@0
   154
}
nathan@0
   155
nathan@0
   156
/****************************************************************************/
nathan@0
   157
nathan@0
   158
void print_space() 
nathan@0
   159
{
nathan@0
   160
  if(verbose)
nathan@0
   161
    fprintf(stderr,
nathan@0
   162
      "Disk size:  %7lld kB (%7ld blocks)\n"
nathan@0
   163
      "Space used: %7lld kB (%7lld blocks)\n"
nathan@0
   164
      "Space avail:%7lld kB (%7lld blocks)\n",
nathan@0
   165
      (long long)cd_len*CD_FRAMESIZE/1024,cd_len,
nathan@0
   166
      cd_used/1024, cd_used/CD_FRAMESIZE,
nathan@0
   167
      cd_avail/1024, cd_avail/CD_FRAMESIZE);
nathan@0
   168
}