VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/bootsectors/VBoxBs2Linker.cpp@ 100800

Last change on this file since 100800 was 98103, checked in by vboxsync, 2 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.5 KB
Line 
1/* $Id: VBoxBs2Linker.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * VirtualBox Validation Kit - Boot Sector 2 "linker".
4 */
5
6/*
7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#include <stdio.h>
42#include <string.h>
43#include <stdlib.h>
44#include <iprt/types.h>
45
46
47int main(int argc, char **argv)
48{
49 const char *pszOutput = NULL;
50 const char **papszInputs = (const char **)calloc(argc, sizeof(const char *));
51 unsigned cInputs = 0;
52
53 /*
54 * Scan the arguments.
55 */
56 for (int i = 1; i < argc; i++)
57 {
58 if (argv[i][0] == '-')
59 {
60 const char *pszOpt = &argv[i][1];
61 if (*pszOpt == '-')
62 {
63 /* Convert long options to short ones. */
64 pszOpt--;
65 if (!strcmp(pszOpt, "--output"))
66 pszOpt = "o";
67 else if (!strcmp(pszOpt, "--version"))
68 pszOpt = "V";
69 else if (!strcmp(pszOpt, "--help"))
70 pszOpt = "h";
71 else
72 {
73 fprintf(stderr, "syntax errro: Unknown options '%s'\n", pszOpt);
74 free(papszInputs);
75 return 2;
76 }
77 }
78
79 /* Process the list of short options. */
80 while (*pszOpt)
81 {
82 switch (*pszOpt++)
83 {
84 case 'o':
85 {
86 const char *pszValue = pszOpt;
87 pszOpt = strchr(pszOpt, '\0');
88 if (*pszValue == '=')
89 pszValue++;
90 else if (!*pszValue)
91 {
92 if (i + 1 >= argc)
93 {
94 fprintf(stderr, "syntax error: The --output option expects a filename.\n");
95 free(papszInputs);
96 return 12;
97 }
98 pszValue = argv[++i];
99 }
100 if (pszOutput)
101 {
102 fprintf(stderr, "Only one output file is allowed. You've specified '%s' and '%s'\n",
103 pszOutput, pszValue);
104 free(papszInputs);
105 return 2;
106 }
107 pszOutput = pszValue;
108 pszOpt = "";
109 break;
110 }
111
112 case 'V':
113 printf("%s\n", "$Revision: 98103 $");
114 free(papszInputs);
115 return 0;
116
117 case '?':
118 case 'h':
119 printf("usage: %s [options] -o <output> <input1> [input2 ... [inputN]]\n", argv[0]);
120 free(papszInputs);
121 return 0;
122 }
123 }
124 }
125 else
126 papszInputs[cInputs++] = argv[i];
127 }
128
129 if (!pszOutput)
130 {
131 fprintf(stderr, "syntax error: No output file was specified (-o or --output).\n");
132 free(papszInputs);
133 return 2;
134 }
135 if (cInputs == 0)
136 {
137 fprintf(stderr, "syntax error: No input files was specified.\n");
138 free(papszInputs);
139 return 2;
140 }
141
142
143 /*
144 * Do the job.
145 */
146 /* Open the output file. */
147#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS)
148 FILE *pOutput = fopen(pszOutput, "wb");
149#else
150 FILE *pOutput = fopen(pszOutput, "w");
151#endif
152 if (!pOutput)
153 {
154 fprintf(stderr, "error: Failed to open output file '%s' for writing\n", pszOutput);
155 free(papszInputs);
156 return 1;
157 }
158
159 /* Copy the input files to the output file, with sector padding applied. */
160 int rcExit = 0;
161 size_t off = 0;
162 for (unsigned i = 0; i < cInputs && rcExit == 0; i++)
163 {
164#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS)
165 FILE *pInput = fopen(papszInputs[i], "rb");
166#else
167 FILE *pInput = fopen(papszInputs[i], "r");
168#endif
169 if (pInput)
170 {
171 for (;;)
172 {
173 /* Read a block from the input file. */
174 uint8_t abBuf[4096];
175 size_t cbRead = fread(abBuf, sizeof(uint8_t), 4096, pInput);
176 if (!cbRead || ferror(pInput))
177 break;
178
179 /* Padd the end of the file if necessary. */
180 if (cbRead != 4096 && !feof(pInput))
181 {
182 fprintf(stderr, "error: fread returned %u bytes, but we're not at the end of the file yet...\n",
183 (unsigned)cbRead);
184 rcExit = 1;
185 break;
186 }
187 if ((cbRead & 0x1ff) != 0)
188 {
189 memset(&abBuf[cbRead], 0, 4096 - cbRead);
190 cbRead = (cbRead + 0x1ff) & ~0x1ffU;
191 }
192
193 /* Write the block to the output file. */
194 if (fwrite(abBuf, sizeof(uint8_t), cbRead, pOutput) == cbRead)
195 off += cbRead;
196 else
197 {
198 fprintf(stderr, "error: fwrite failed\n");
199 rcExit = 1;
200 break;
201 }
202 }
203
204 if (ferror(pInput))
205 {
206 fprintf(stderr, "error: Error reading '%s'.\n", papszInputs[i]);
207 rcExit = 1;
208 }
209 fclose(pInput);
210 }
211 else
212 {
213 fprintf(stderr, "error: Failed to open '%s' for reading.\n", papszInputs[i]);
214 rcExit = 1;
215 }
216 }
217
218 /* Finally, close the output file (can fail because of buffered data). */
219 if (fclose(stderr) != 0)
220 {
221 fprintf(stderr, "error: Error closing '%s'.\n", pszOutput);
222 rcExit = 1;
223 }
224
225 fclose(pOutput);
226 free(papszInputs);
227 return rcExit;
228}
229
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette