1 /* $NetBSD: main.c,v 1.3 2005/07/25 11:26:40 drochner Exp $ */
4 * Copyright (c) 2002, 2005
5 * Matthias Drochner. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 * Generate an in-core disklabel for a CD, containing entries for
31 * previous data tracks (supposed to be of previous sessions).
33 * - support simulation of multisession CDs in a vnd(4) disk
40 #include <sys/ioctl.h>
42 #include <sys/disklabel.h>
43 #include <sys/param.h>
49 #include "mscdlabel.h"
51 static int getcdtoc(int);
52 static int getfaketoc(int);
53 int main(int, char **);
55 const char *disk
= "cd0";
57 struct cd_toc_entry
*tocbuf
;
63 struct ioc_toc_header th
;
64 struct ioc_read_toc_entry te
;
67 memset(&th
, 0, sizeof(th
));
68 res
= ioctl(fd
, CDIOREADTOCHEADER
, &th
);
70 warn("CDIOREADTOCHEADER");
74 ntracks
= th
.ending_track
- th
.starting_track
+ 1;
75 /* one more for leadout track, for tracklen calculation */
76 tocbufsize
= (ntracks
+ 1) * sizeof(struct cd_toc_entry
);
77 tocbuf
= malloc(tocbufsize
);
79 err(3, "alloc TOC buffer");
80 memset(&te
, 0, sizeof(te
));
81 te
.address_format
= CD_LBA_FORMAT
;
82 te
.starting_track
= th
.starting_track
; /* always 1 ??? */
83 te
.data_len
= tocbufsize
;
85 res
= ioctl(fd
, CDIOREADTOCENTRIES
, &te
);
87 err(4, "CDIOREADTOCENTRIES");
101 if (st
.st_size
% 2048) {
102 warnx("size not multiple of 2048");
106 tocbuf
= malloc(2 * sizeof(struct cd_toc_entry
));
108 err(3, "alloc TOC buffer");
111 * fake up a data track spanning the whole file and a leadout track,
112 * just as much as necessary for the scan below
114 tocbuf
[0].addr
.lba
= 0;
115 tocbuf
[0].control
= 4;
116 tocbuf
[1].addr
.lba
= st
.st_size
/ 2048;
117 tocbuf
[1].control
= 0;
127 int fd
, res
, i
, j
, rawpart
;
128 char fullname
[MAXPATHLEN
];
129 struct cd_toc_entry
*track
;
130 struct disklabel label
;
137 fd
= opendisk(disk
, O_RDWR
, fullname
, MAXPATHLEN
, 0);
139 warn("opendisk (read-write) %s", disk
);
140 fd
= opendisk(disk
, O_RDONLY
, fullname
, MAXPATHLEN
, 0);
142 err(1, "opendisk %s", disk
);
147 * Get the TOC: first try to read a real one from a CD drive.
148 * If this fails we might have something else keeping an ISO image
149 * (eg. vnd(4) or plain file).
151 if (getcdtoc(fd
) < 0 && getfaketoc(fd
) < 0)
155 * Get label template. If this fails we might have a plain file.
156 * Proceed to print out possible ISO label information, but
157 * don't try to write a label back.
159 res
= ioctl(fd
, DIOCGDINFO
, &label
);
166 * We want entries for the sessions beginning with the most recent
167 * one, in reversed time order.
168 * We don't have session information here, but it is uncommon
169 * to have more than one data track in one session, so we get
172 if ((rawpart
= getrawpartition()) == -1)
173 err(1, "Cannot get raw partition");
176 while (--i
>= 0 && j
< MAXPARTITIONS
) {
178 printf("track (ctl=%d) at sector %d\n", track
->control
,
180 if ((track
->control
& 4) /* data track */
181 && check_primary_vd(fd
, track
->addr
.lba
,
182 (track
+1)->addr
.lba
- track
->addr
.lba
)) {
183 printf(" adding as '%c'\n", 'a' + j
);
184 p
= &label
.d_partitions
[j
];
185 memset(p
, 0, sizeof(struct partition
));
186 p
->p_size
= label
.d_partitions
[rawpart
].p_size
;
187 p
->p_fstype
= FS_ISO9660
;
188 p
->p_cdsession
= track
->addr
.lba
;
193 if (!j
) /* no ISO track, let the label alone */
197 /* write back label */
198 if (label
.d_npartitions
< j
)
199 label
.d_npartitions
= j
;
200 strncpy(label
.d_packname
, "mscdlabel's", 16);
201 label
.d_checksum
= 0;
202 label
.d_checksum
= dkcksum(&label
);
203 res
= ioctl(fd
, DIOCSDINFO
, &label
);
205 err(6, "DIOCSDINFO");
207 printf("disklabel not written\n");