The game rogue(6) has a potential buffer overflow allowing
[dragonfly.git] / release / sysinstall / cdrom.c
1 /*
2  * The new sysinstall program.
3  *
4  * This is probably the last attempt in the `sysinstall' line, the next
5  * generation being slated to essentially a complete rewrite.
6  *
7  * $FreeBSD: src/release/sysinstall/cdrom.c,v 1.47.2.5 2002/10/24 12:56:06 nyan Exp $
8  * $DragonFly: src/release/sysinstall/Attic/cdrom.c,v 1.2 2003/06/17 04:27:21 dillon Exp $
9  *
10  * Copyright (c) 1995
11  *      Jordan Hubbard.  All rights reserved.
12  * Copyright (c) 1995
13  *      Gary J Palmer. All rights reserved.
14  *
15  * Redistribution and use in source and binary forms, with or without
16  * modification, are permitted provided that the following conditions
17  * are met:
18  * 1. Redistributions of source code must retain the above copyright
19  *    notice, this list of conditions and the following disclaimer,
20  *    verbatim and that no modifications are made prior to this
21  *    point in the file.
22  * 2. Redistributions in binary form must reproduce the above copyright
23  *    notice, this list of conditions and the following disclaimer in the
24  *    documentation and/or other materials provided with the distribution.
25  *
26  * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  */
39
40 /* These routines deal with getting things off of CDROM media */
41
42 #include "sysinstall.h"
43 #include <sys/stat.h>
44 #include <sys/errno.h>
45 #include <sys/param.h>
46 #include <sys/wait.h>
47 #include <unistd.h>
48 #include <grp.h>
49 #include <fcntl.h>
50 #include <libutil.h>
51
52 #define CD9660
53 #include <sys/mount.h>
54 #include <isofs/cd9660/cd9660_mount.h>
55 #undef CD9660
56
57 static Boolean cdromMounted;
58 static Boolean previouslyMounted; /* Was the disc already mounted? */
59 static char mountpoint[MAXPATHLEN] = "/dist";
60
61 static properties
62 read_props(char *name)
63 {
64         int fd;
65         properties n;
66
67         fd = open(name, O_RDONLY);
68         if (fd == -1)
69             return NULL;
70         n = properties_read(fd);
71         close(fd);
72         return n;
73 }
74
75 Boolean
76 mediaInitCDROM(Device *dev)
77 {
78     struct iso_args     args;
79     properties cd_attr = NULL;
80     char *cp = NULL;
81     Boolean readInfo = TRUE;
82     static Boolean bogusCDOK = FALSE;
83
84     if (cdromMounted)
85         return TRUE;
86
87     Mkdir(mountpoint);
88     bzero(&args, sizeof(args));
89     args.fspec = dev->devname;
90     args.flags = 0;
91     if (mount("cd9660", mountpoint, MNT_RDONLY, (caddr_t) &args) == -1) {
92         if (errno == EINVAL) {
93             msgConfirm("The disc in your drive looks more like an Audio disc than a FreeBSD release.");
94             return FALSE;
95         } else if (errno == EBUSY) {
96             /* Perhaps the CDROM drive is already mounted as /cdrom */
97             if (file_readable("/cdrom/cdrom.inf")) {
98                 previouslyMounted = TRUE;
99                 strlcpy(mountpoint, "/cdrom", 7);
100             }
101         } else {
102             msgConfirm("Error mounting %s on %s: %s (%u)", dev->devname, mountpoint, strerror(errno), errno);
103             return FALSE;
104         }
105     }
106     cdromMounted = TRUE;
107
108     if (!file_readable(string_concat(mountpoint, "/cdrom.inf")) && !bogusCDOK) {
109         if (msgYesNo("Warning: The disc currently in the drive is either not a FreeBSD\n"
110                      "disc or it is an older (pre 2.1.5) FreeBSD CD which does not\n"
111                      "have a version number on it.  Do you wish to use this disc anyway?") != 0) {
112             if (!previouslyMounted)
113                 unmount(mountpoint, MNT_FORCE);
114             cdromMounted = FALSE;
115             return FALSE;
116         }
117         else {
118             readInfo = FALSE;
119             bogusCDOK = TRUE;
120         }
121     }
122
123     if (readInfo) {
124         if (!(cd_attr = read_props(string_concat(mountpoint, "/cdrom.inf")))
125             || !(cp = property_find(cd_attr, "CD_VERSION"))) {
126             msgConfirm("Unable to find a %s/cdrom.inf file.\n"
127                        "Either this is not a FreeBSD disc, there is a problem with\n"
128                        "the CDROM driver or something is wrong with your hardware.\n"
129                        "Please fix this problem (check the console logs on VTY2) and\n"
130                        "try again.", mountpoint);
131         }
132         else {
133             if (variable_cmp(VAR_RELNAME, cp) &&
134                 variable_cmp(VAR_RELNAME, "any") &&
135                 variable_cmp(cp, "any") &&
136                 !bogusCDOK) {
137                 msgConfirm("Warning: The version of the FreeBSD disc currently in the drive\n"
138                            "(%s) does not match the version of the boot floppy\n"
139                            "(%s).\n\n"
140                            "If this is intentional, to avoid this message in the future\n"
141                            "please visit the Options editor to set the boot floppy version\n"
142                            "string to match that of the disc before selecting it as your\n"
143                            "installation media.", cp, variable_get(VAR_RELNAME));
144
145                 if (msgYesNo("Would you like to try and use this disc anyway?") != 0) {
146                     if (!previouslyMounted)
147                         unmount(mountpoint, MNT_FORCE);
148                     cdromMounted = FALSE;
149                     properties_free(cd_attr);
150                     return FALSE;
151                 }
152                 else
153                     bogusCDOK = TRUE;
154             }
155             if ((cp = property_find(cd_attr, "CD_MACHINE_ARCH")) != NULL) {
156                 if (strcmp(cp, "any") &&
157 #ifdef __alpha__
158                   strcmp(cp, "alpha")) {
159 #elif defined(PC98)
160                   strcmp(cp, "pc98")) {
161 #else
162                   strcmp(cp, "x86")) {
163 #endif
164                     msgConfirm("Fatal: The FreeBSD install CD/DVD currently in the drive\n"
165                            "is for the %s architecture, not the machine you're using.\n\n"
166
167                            "Please use the correct installation CD/DVD for your machine type.", cp);
168
169                     if (!previouslyMounted)
170                         unmount(mountpoint, MNT_FORCE);
171                     cdromMounted = FALSE;
172                     properties_free(cd_attr);
173                     return FALSE;
174                 }
175             }
176             if ((cp = property_find(cd_attr, "CD_VOLUME")) != NULL) {
177                 dev->volume = atoi(cp);
178                 /* XXX - Sanity check the volume here? */
179                 msgDebug("CD Volume %d initialized!\n", dev->volume);
180             } else {
181                 dev->volume = 0;
182             }
183         }
184     }
185     if (cd_attr)
186         properties_free(cd_attr);
187     return TRUE;
188 }
189
190 FILE *
191 mediaGetCDROM(Device *dev, char *file, Boolean probe)
192 {
193     return mediaGenericGet(mountpoint, file);
194 }
195
196 void
197 mediaShutdownCDROM(Device *dev)
198 {
199     if (!cdromMounted)
200         return;
201
202     if (previouslyMounted) {
203         cdromMounted = FALSE;
204         return;
205     }
206
207     if (unmount(mountpoint, MNT_FORCE) != 0)
208         msgConfirm("Could not unmount the CDROM/DVD from %s: %s", mountpoint, strerror(errno));
209     else
210         cdromMounted = FALSE;
211 }