2 Copyright (c) 2000-2002 Craig Condit, Stefan Hülswitt.
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are met:
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.
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
26 #define _LARGEFILE64_SOURCE
33 #include <linux/cdrom.h>
35 #include <sys/ioctl.h>
42 /* size of leadin/out depending of how many tracks are on cd */
43 #define MIN_FREE_1 (11400*CD_FRAMESIZE) /* 1th track */
44 #define MIN_FREE_2 (6900*CD_FRAMESIZE) /* 2nd and more tracks */
45 /* number of (unreadable) runout sectos */
48 struct toc_entry *toc=0;
49 long long cd_used, cd_avail;
53 extern char *prg_name;
55 /****************************************************************************/
57 int open_cdr(char *device)
59 return open(device, O_RDONLY | O_NONBLOCK);
62 /****************************************************************************/
64 void close_cdr(int cd_fd)
69 /****************************************************************************/
71 void get_param(int fd, unsigned long *ahead, unsigned long *fahead)
73 #if defined(BLKRAGET) && defined(BLKFRAGET)
75 ioctl(fd,BLKRAGET,ahead);
76 ioctl(fd,BLKFRAGET,fahead);
77 DEBUG("get_param: readahead=%ld freadahead=%ld\n",*ahead,*fahead);
79 fprintf("Can't get readahead parameter. Ioctl's not available\n");
83 /****************************************************************************/
85 void set_param(int fd, unsigned long ahead, unsigned long fahead)
87 #if defined(BLKRAGET) && defined(BLKFRAGET)
88 ioctl(fd, BLKRASET, ahead);
89 ioctl(fd, BLKFRASET, fahead);
90 DEBUG("set_param: readahead=%ld freadahead=%ld\n",ahead,fahead);
92 fprintf("Can't set readahead parameter. Ioctl's not available\n");
96 /****************************************************************************/
98 int full_read(int fd, void *buf, int count)
104 bytes=read(fd,buf,count); if(bytes<0) return bytes;
106 count-=bytes; total+=bytes; buf+=bytes;
111 /****************************************************************************/
115 if(toc) { free(toc); toc=0; }
118 /****************************************************************************/
120 int read_toc(int cd_fd, int trackinfos)
123 struct cdrom_tochdr cd_header;
124 struct cdrom_tocentry cd_entry;
125 int tracks,start_track;
127 /* read table of contents header */
128 if(ioctl(cd_fd,CDROMREADTOCHDR,&cd_header)) {
129 if(verbose) fprintf(stderr,"%s: Unable to read CD header, assuming empty CD-R\n", prg_name);
130 cd_used=0; cd_avail=(long long)cd_len*CD_FRAMESIZE; return 0;
133 /* get start and end tracks */
134 start_track = cd_header.cdth_trk0;
135 tracks = cd_header.cdth_trk1-start_track+1;
136 DEBUG("read_toc: starttrack=%d tracks=%d\n",start_track,tracks);
139 if(!(toc=calloc(tracks+1,sizeof(struct toc_entry)))) serror("No memory for TOC");
141 /* set some parameters */
142 cd_entry.cdte_format=CDROM_LBA;
145 cd_entry.cdte_track=CDROM_LEADOUT;
146 if(ioctl(cd_fd,CDROMREADTOCENTRY,&cd_entry)) error("Error reading lead-out");
148 toc[0].track_no=CDROM_LEADOUT; /* not a real track */
149 toc[0].sec_start=cd_entry.cdte_addr.lba;
151 cd_used =(long long)toc[0].sec_start*CD_FRAMESIZE;
152 cd_avail =(long long)cd_len*CD_FRAMESIZE-cd_used;
153 cd_avail-=(tracks>1?MIN_FREE_2:MIN_FREE_1);
154 DEBUG("read_toc: cd_used=%lld (%lld secs) cd_avail=%lld (%lld secs)\n",cd_used,cd_used/CD_FRAMESIZE,cd_avail,cd_avail/CD_FRAMESIZE);
156 if(cd_avail<0) cd_avail=0; /* can be <0 due to assumed additional lead-in/out */
158 /* read rest of tracks */
159 for(i=1; i<=tracks; i++) {
160 cd_entry.cdte_track=start_track+i-1;
161 if(ioctl(cd_fd,CDROMREADTOCENTRY,&cd_entry)) error("Error reading TOC");
163 toc[i].track_no=start_track+i-1;
164 toc[i].sec_start=cd_entry.cdte_addr.lba;
165 if(cd_entry.cdte_ctrl&CDROM_DATA_TRACK) toc[i].is_data=1;
168 /* calculate end sectors */
169 toc[tracks].sec_end = toc[ 0].sec_start - 1 - RUNOUT;
170 for(i=1; i<tracks; i++)
171 toc[i].sec_end = toc[i+1].sec_start - 1 - RUNOUT - (i>1?(MIN_FREE_2/CD_FRAMESIZE):(MIN_FREE_1/CD_FRAMESIZE));
174 /* now loop through tracks and read header info */
175 for(i=1; i<=tracks; i++) {
176 char inbuffer[CD_FRAMESIZE];
177 struct header_block *track_header=(struct header_block *)&inbuffer[0];
179 if (toc[i].is_data == 1) {
180 if(lseek64(cd_fd,(long long)toc[i].sec_start*CD_FRAMESIZE,SEEK_SET)<0) error("Seek failed");
182 if(full_read(cd_fd,inbuffer,CD_FRAMESIZE)==CD_FRAMESIZE) {
183 if(!strncmp(SHORT_HDR,track_header->id_str,strlen(SHORT_HDR))) {
184 toc[i].is_cdbackup=1;
185 strncpy(toc[i].id_str,track_header->id_str,32); toc[i].id_str[32]=0;
186 strncpy(toc[i].vol_id, track_header->vol_id,32); toc[i].vol_id[32]=0;
187 strncpy(toc[i].t_stamp, track_header->t_stamp,12); toc[i].t_stamp[12]=0;
188 toc[i].disk_set = track_header->disk_set;
197 /****************************************************************************/
203 "Disk size: %7lld kB (%7ld blocks)\n"
204 "Space used: %7lld kB (%7lld blocks)\n"
205 "Space avail:%7lld kB (%7lld blocks)\n",
206 (long long)cd_len*CD_FRAMESIZE/1024,cd_len,
207 cd_used/1024, cd_used/CD_FRAMESIZE,
208 cd_avail/1024, cd_avail/CD_FRAMESIZE);