VirtualBox

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

Last change on this file was 106061, checked in by vboxsync, 3 days 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.4 KB
Line 
1/* $Id: VBoxBs2Linker.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * VirtualBox Validation Kit - Boot Sector 2 "linker".
4 */
5
6/*
7 * Copyright (C) 2006-2024 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: 106061 $");
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 for (unsigned i = 0; i < cInputs && rcExit == 0; i++)
162 {
163#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS)
164 FILE *pInput = fopen(papszInputs[i], "rb");
165#else
166 FILE *pInput = fopen(papszInputs[i], "r");
167#endif
168 if (pInput)
169 {
170 for (;;)
171 {
172 /* Read a block from the input file. */
173 uint8_t abBuf[4096];
174 size_t cbRead = fread(abBuf, sizeof(uint8_t), 4096, pInput);
175 if (!cbRead || ferror(pInput))
176 break;
177
178 /* Padd the end of the file if necessary. */
179 if (cbRead != 4096 && !feof(pInput))
180 {
181 fprintf(stderr, "error: fread returned %u bytes, but we're not at the end of the file yet...\n",
182 (unsigned)cbRead);
183 rcExit = 1;
184 break;
185 }
186 if ((cbRead & 0x1ff) != 0)
187 {
188 memset(&abBuf[cbRead], 0, 4096 - cbRead);
189 cbRead = (cbRead + 0x1ff) & ~0x1ffU;
190 }
191
192 /* Write the block to the output file. */
193 if (fwrite(abBuf, sizeof(uint8_t), cbRead, pOutput) != cbRead)
194 {
195 fprintf(stderr, "error: fwrite failed\n");
196 rcExit = 1;
197 break;
198 }
199 }
200
201 if (ferror(pInput))
202 {
203 fprintf(stderr, "error: Error reading '%s'.\n", papszInputs[i]);
204 rcExit = 1;
205 }
206 fclose(pInput);
207 }
208 else
209 {
210 fprintf(stderr, "error: Failed to open '%s' for reading.\n", papszInputs[i]);
211 rcExit = 1;
212 }
213 }
214
215 /* Finally, close the output file (can fail because of buffered data). */
216 if (fclose(stderr) != 0)
217 {
218 fprintf(stderr, "error: Error closing '%s'.\n", pszOutput);
219 rcExit = 1;
220 }
221
222 fclose(pOutput);
223 free(papszInputs);
224 return rcExit;
225}
226
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