source: bootcd/isolinux/syslinux-6.03/libinstaller/advio.c @ dd1be7c

Last change on this file since dd1be7c was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 3.7 KB
Line 
1/* ----------------------------------------------------------------------- *
2 *
3 *   Copyright 2007-2008 H. Peter Anvin - All Rights Reserved
4 *   Copyright 2010 Intel Corporation; author: H. Peter Anvin
5 *
6 *   This program is free software; you can redistribute it and/or modify
7 *   it under the terms of the GNU General Public License as published by
8 *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
9 *   Boston MA 02111-1307, USA; either version 2 of the License, or
10 *   (at your option) any later version; incorporated herein by reference.
11 *
12 * ----------------------------------------------------------------------- */
13
14/*
15 * advio.c
16 *
17 * Linux ADV I/O
18 *
19 * Return 0 on success, -1 on error, and set errno.
20 *
21 */
22#define  _GNU_SOURCE
23
24#include <stdio.h>
25#include <stdlib.h>
26#include <stddef.h>
27#include <stdint.h>
28#include <string.h>
29#include <unistd.h>
30#include <errno.h>
31#include <fcntl.h>
32#include <sys/stat.h>
33#include <sys/types.h>
34#include "syslxint.h"
35#include "syslxcom.h"
36
37/*
38 * Read the ADV from an existing instance, or initialize if invalid.
39 * Returns -1 on fatal errors, 0 if ADV is okay, 1 if the ADV is
40 * invalid, and 2 if the file does not exist.
41 */
42int read_adv(const char *path, const char *cfg)
43{
44    char *file;
45    int fd = -1;
46    struct stat st;
47    int err = 0;
48    int rv;
49
50    rv = asprintf(&file, "%s%s%s", path,
51                  path[0] && path[strlen(path) - 1] == '/' ? "" : "/", cfg);
52
53    if (rv < 0 || !file) {
54        perror(program);
55        return -1;
56    }
57
58    fd = open(file, O_RDONLY);
59    if (fd < 0) {
60        if (errno != ENOENT) {
61            err = -1;
62        } else {
63            syslinux_reset_adv(syslinux_adv);
64            err = 2;            /* Nonexistence is not a fatal error */
65        }
66    } else if (fstat(fd, &st)) {
67        err = -1;
68    } else if (st.st_size < 2 * ADV_SIZE) {
69        /* Too small to be useful */
70        syslinux_reset_adv(syslinux_adv);
71        err = 0;                /* Nothing to read... */
72    } else if (xpread(fd, syslinux_adv, 2 * ADV_SIZE,
73                      st.st_size - 2 * ADV_SIZE) != 2 * ADV_SIZE) {
74        err = -1;
75    } else {
76        /* We got it... maybe? */
77        err = syslinux_validate_adv(syslinux_adv) ? 1 : 0;
78    }
79
80    if (err < 0)
81        perror(file);
82
83    if (fd >= 0)
84        close(fd);
85
86    free(file);
87
88    return err;
89}
90
91/*
92 * Update the ADV in an existing installation.
93 */
94int write_adv(const char *path, const char *cfg)
95{
96    unsigned char advtmp[2 * ADV_SIZE];
97    char *file;
98    int fd = -1;
99    struct stat st, xst;
100    int err = 0;
101    int rv;
102
103    rv = asprintf(&file, "%s%s%s", path,
104                  path[0] && path[strlen(path) - 1] == '/' ? "" : "/", cfg);
105
106    if (rv < 0 || !file) {
107        perror(program);
108        return -1;
109    }
110
111    fd = open(file, O_RDONLY);
112    if (fd < 0) {
113        err = -1;
114    } else if (fstat(fd, &st)) {
115        err = -1;
116    } else if (st.st_size < 2 * ADV_SIZE) {
117        /* Too small to be useful */
118        err = -2;
119    } else if (xpread(fd, advtmp, 2 * ADV_SIZE,
120                      st.st_size - 2 * ADV_SIZE) != 2 * ADV_SIZE) {
121        err = -1;
122    } else {
123        /* We got it... maybe? */
124        err = syslinux_validate_adv(advtmp) ? -2 : 0;
125        if (!err) {
126            /* Got a good one, write our own ADV here */
127            clear_attributes(fd);
128
129            /* Need to re-open read-write */
130            close(fd);
131            fd = open(file, O_RDWR | O_SYNC);
132            if (fd < 0) {
133                err = -1;
134            } else if (fstat(fd, &xst) || xst.st_ino != st.st_ino ||
135                       xst.st_dev != st.st_dev || xst.st_size != st.st_size) {
136                fprintf(stderr, "%s: race condition on write\n", file);
137                err = -2;
138            }
139            /* Write our own version ... */
140            if (xpwrite(fd, syslinux_adv, 2 * ADV_SIZE,
141                        st.st_size - 2 * ADV_SIZE) != 2 * ADV_SIZE) {
142                err = -1;
143            }
144
145            sync();
146            set_attributes(fd);
147        }
148    }
149
150    if (err == -2)
151        fprintf(stderr, "%s: cannot write auxilliary data (need --update)?\n",
152                file);
153    else if (err == -1)
154        perror(file);
155
156    if (fd >= 0)
157        close(fd);
158    if (file)
159        free(file);
160
161    return err;
162}
Note: See TracBrowser for help on using the repository browser.