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>
34 #include <sys/ioctl.h>
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 */
43 struct toc_entry *toc=0;
44 long long cd_used, cd_avail;
48 extern char *prg_name;
50 /****************************************************************************/
52 int open_cdr(char *device)
54 return open(device, O_RDONLY | O_NONBLOCK);
57 /****************************************************************************/
59 void close_cdr(int cd_fd)
64 /****************************************************************************/
66 int full_read(int fd, void *buf, int count)
72 bytes=read(fd,buf,count); if(bytes<0) return bytes;
74 count-=bytes; total+=bytes; buf+=bytes;
79 /****************************************************************************/
83 if(toc) { free(toc); toc=0; }
86 /****************************************************************************/
88 int read_toc(int cd_fd, int trackinfos)
91 struct cdrom_tochdr cd_header;
92 struct cdrom_tocentry cd_entry;
93 int tracks,start_track;
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;
101 /* get start and end tracks */
102 start_track = cd_header.cdth_trk0;
103 tracks = cd_header.cdth_trk1-start_track+1;
106 if(!(toc=calloc(tracks+1,sizeof(struct toc_entry)))) serror("No memory for TOC");
108 /* set some parameters */
109 cd_entry.cdte_format=CDROM_LBA;
112 cd_entry.cdte_track=CDROM_LEADOUT;
113 if(ioctl(cd_fd,CDROMREADTOCENTRY,&cd_entry)) error("Error reading lead-out");
115 toc[0].track_no=CDROM_LEADOUT; /* not a real track */
116 toc[0].sec_start=cd_entry.cdte_addr.lba;
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 */
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");
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;
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];
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");
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;
156 /****************************************************************************/
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);