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