HAMMER VFS - Hack cursor iterator when locked cursor moved to parent
[dragonfly.git] / usr.sbin / installer / libinstaller / functions.c
blobc700ae2c98e2eb09f0c95236f5a4e3358d514720
1 /*
2 * Copyright (c)2004 The DragonFly Project. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
8 * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
14 * distribution.
16 * Neither the name of the DragonFly Project nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 * OF THE POSSIBILITY OF SUCH DAMAGE.
35 * functions.c
36 * Generic functions for installer.
37 * $Id: functions.c,v 1.22 2005/02/06 21:05:18 cpressey Exp $
40 #include <ctype.h>
41 #include <stdio.h>
42 #include <stdarg.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <unistd.h>
47 #include "libaura/mem.h"
48 #include "libaura/dict.h"
50 #include "libdfui/dfui.h"
52 #include "functions.h"
53 #include "diskutil.h"
54 #include "uiutil.h"
56 /*** INSTALLER CONTEXT CONSTRUCTOR ***/
58 struct i_fn_args *
59 i_fn_args_new(const char *os_root, const char *def_tmp_dir, int transport, const char *rendezvous)
61 struct i_fn_args *a;
62 char *filename;
64 AURA_MALLOC(a, i_fn_args);
66 a->c = NULL;
67 a->os_root = aura_strdup(os_root);
68 a->cfg_root = "";
69 a->name = "";
70 a->short_desc = "";
71 a->long_desc = "";
72 a->result = 0;
73 a->log = NULL;
74 a->s = NULL;
75 a->tmp = NULL;
76 a->temp_files = NULL;
77 a->cmd_names = NULL;
79 asprintf(&filename, "%sinstall.log", def_tmp_dir);
80 a->log = fopen(filename, "w");
81 free(filename);
82 if (a->log == NULL) {
83 i_fn_args_free(a);
84 return(NULL);
87 i_log(a, "Installer started");
88 i_log(a, "-----------------");
90 i_log(a, "+ Creating DFUI connection on ``%s''\n", rendezvous);
92 if ((a->c = dfui_connection_new(transport, rendezvous)) == NULL) {
93 i_log(a, "! ERROR: Couldn't create connection on ``%s''\n", rendezvous);
94 i_fn_args_free(a);
95 return(NULL);
98 i_log(a, "+ Connecting on ``%s''\n", rendezvous);
100 if (!dfui_be_start(a->c)) {
101 i_log(a, "! ERROR: Couldn't connect to frontend on ``%s''\n", rendezvous);
102 i_fn_args_free(a);
103 return(NULL);
106 if ((a->s = storage_new()) == NULL) {
107 i_log(a, "! ERROR: Couldn't create storage descriptor");
108 i_fn_args_free(a);
109 return(NULL);
112 a->tmp = def_tmp_dir; /* XXX temporarily set to this */
113 a->temp_files = aura_dict_new(23, AURA_DICT_HASH);
114 a->cmd_names = config_vars_new();
115 if (!config_vars_read(a, a->cmd_names, CONFIG_TYPE_SH,
116 "usr/share/installer/cmdnames.conf")) {
117 i_log(a, "! ERROR: Couldn't read cmdnames config file");
118 i_fn_args_free(a);
119 return(NULL);
122 a->tmp = cmd_name(a, "INSTALLER_TEMP");
124 i_log(a, "+ Starting installer state machine");
126 return(a);
129 void
130 i_fn_args_free(struct i_fn_args *a)
132 if (a != NULL) {
133 if (a->temp_files != NULL) {
134 temp_files_clean(a);
135 aura_dict_free(a->temp_files);
137 if (a->cmd_names != NULL) {
138 config_vars_free(a->cmd_names);
140 if (a->s != NULL) {
141 storage_free(a->s);
143 if (a->c != NULL) {
144 dfui_be_stop(a->c);
146 if (a->log != NULL) {
147 fclose(a->log);
149 AURA_FREE(a, i_fn_args);
153 /*** INSTALLER CONTEXT FUNCTIONS ***/
155 void
156 i_log(struct i_fn_args *a, const char *fmt, ...)
158 va_list args;
160 va_start(args, fmt);
161 vfprintf(stderr, fmt, args);
162 fprintf(stderr, "\n");
163 va_end(args);
164 if (a->log != NULL) {
165 va_start(args, fmt);
166 vfprintf(a->log, fmt, args);
167 fprintf(a->log, "\n");
168 fflush(a->log);
169 va_end(args);
171 va_end(args);
174 /*** UTILITY ***/
176 void
177 abort_backend(void)
179 exit(1);
183 assert_clean(struct dfui_connection *c, const char *name, const char *field,
184 const char *not_allowed)
186 if (strpbrk(field, not_allowed) != NULL) {
187 inform(c, "The %s field may not contain any of the "
188 "following characters:\n\n%s",
189 name, not_allowed);
190 return(0);
191 } else {
192 return(1);
197 * Expects a leading 0x.
200 hex_to_int(const char *hex, int *result)
202 int i, a = 0;
203 char d;
205 if (strncmp(hex, "0x", 2) != 0)
206 return(0);
208 for (i = 2; hex[i] != '\0'; i++) {
209 d = toupper(hex[i]);
210 if (isspace(d))
211 continue;
212 if (isdigit(d))
213 a = a * 16 + (d - '0');
214 else if (d >= 'A' && d <= 'F')
215 a = a * 16 + (d + 10 - 'A');
216 else
217 return(0);
220 *result = a;
221 return(1);
225 first_non_space_char_is(const char *line, char x)
227 int i;
229 for (i = 0; line[i] != '\0'; i++) {
230 if (isspace(line[i]))
231 continue;
232 if (line[i] == x)
233 return(1);
234 return(0);
237 return(0);
240 const char *
241 capacity_to_string(long capacity)
243 static char string[256];
245 if (capacity < 0)
246 strlcpy(string, "*", 2);
247 else
248 snprintf(string, 255, "%ldM", capacity);
250 return(string);
254 string_to_capacity(const char *string, long *capacity)
256 char unit;
258 unit = string[strlen(string) - 1];
259 if (!strcmp(string, "*")) {
260 *capacity = -1;
261 return(1);
262 } else if (unit == 'm' || unit == 'M') {
263 *capacity = strtol(string, NULL, 10);
264 return(1);
265 } else if (unit == 'g' || unit == 'G') {
266 *capacity = strtol(string, NULL, 10) * 1024;
267 return(1);
268 } else {
269 return(0);
274 * Round a number up to the nearest power of two.
276 unsigned long
277 next_power_of_two(unsigned long n)
279 unsigned long p, op;
281 p = 1;
282 op = 0;
283 while (p < n && p > op) {
284 op = p;
285 p <<= 1;
288 return(p > op ? p : n);
292 * Returns file name without extension.
293 * e.g.
294 * ru.koi8-r.kbd -> ru.koi8-r
295 * README -> README
297 * Caller is responsible for freeing the string returned.
299 char *
300 filename_noext(const char *filename)
302 int i;
303 char *buffer, *p;
305 buffer = aura_strdup(filename);
307 if (strlen(filename) == 0) {
308 buffer[0] = '\0';
309 return(buffer);
312 p = strrchr(filename, '.');
314 if (p != NULL) {
315 i = strlen(filename) - strlen(p);
316 buffer[i] = 0;
319 return(buffer);
323 * Temp files
327 temp_file_add(struct i_fn_args *a, const char *filename)
329 aura_dict_store(a->temp_files, filename, strlen(filename) + 1, "", 1);
330 return(1);
334 temp_files_clean(struct i_fn_args *a)
336 void *rk;
337 size_t rk_len;
338 char *filename;
340 aura_dict_rewind(a->temp_files);
341 while (!aura_dict_eof(a->temp_files)) {
342 aura_dict_get_current_key(a->temp_files, &rk, &rk_len);
343 asprintf(&filename, "%s%s", a->tmp, (char *)rk);
344 (void)unlink(filename); /* not much we can do if it fails */
345 free(filename);
346 aura_dict_next(a->temp_files);
348 return(1);
352 * Command names
354 const char *
355 cmd_name(const struct i_fn_args *a, const char *cmd_key)
357 const char *name;
359 name = config_var_get(a->cmd_names, cmd_key);
360 if (strcmp(name, "") == 0)
361 return("bin/echo"); /* XXX usr/local/sbin/error? */
362 else
363 return(name);