1 /* ----------------------------------------------------------------------- *
3 * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved
4 * Copyright 2010 Intel Corporation; author: H. Peter Anvin
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.
12 * ----------------------------------------------------------------------- */
19 * Return 0 on success, -1 on error, and set errno.
33 #include <sys/types.h>
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.
42 int read_adv(const char *path
, const char *cfg
)
50 rv
= asprintf(&file
, "%s%s%s", path
,
51 path
[0] && path
[strlen(path
) - 1] == '/' ? "" : "/", cfg
);
53 if (rv
< 0 || !file
) {
58 fd
= open(file
, O_RDONLY
);
60 if (errno
!= ENOENT
) {
63 syslinux_reset_adv(syslinux_adv
);
64 err
= 2; /* Nonexistence is not a fatal error */
66 } else if (fstat(fd
, &st
)) {
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
) {
76 /* We got it... maybe? */
77 err
= syslinux_validate_adv(syslinux_adv
) ? 1 : 0;
92 * Update the ADV in an existing installation.
94 int write_adv(const char *path
, const char *cfg
)
96 unsigned char advtmp
[2 * ADV_SIZE
];
103 rv
= asprintf(&file
, "%s%s%s", path
,
104 path
[0] && path
[strlen(path
) - 1] == '/' ? "" : "/", cfg
);
106 if (rv
< 0 || !file
) {
111 fd
= open(file
, O_RDONLY
);
114 } else if (fstat(fd
, &st
)) {
116 } else if (st
.st_size
< 2 * ADV_SIZE
) {
117 /* Too small to be useful */
119 } else if (xpread(fd
, advtmp
, 2 * ADV_SIZE
,
120 st
.st_size
- 2 * ADV_SIZE
) != 2 * ADV_SIZE
) {
123 /* We got it... maybe? */
124 err
= syslinux_validate_adv(advtmp
) ? -2 : 0;
126 /* Got a good one, write our own ADV here */
127 clear_attributes(fd
);
129 /* Need to re-open read-write */
131 fd
= open(file
, O_RDWR
| O_SYNC
);
133 fprintf(stderr
, "Cannot open file '%s' in read/write mode !\nFatal error, exiting.\n", file
);
135 } else if (fstat(fd
, &xst
) || xst
.st_ino
!= st
.st_ino
||
136 xst
.st_dev
!= st
.st_dev
|| xst
.st_size
!= st
.st_size
) {
137 fprintf(stderr
, "%s: race condition on write\n", file
);
140 /* Write our own version ... */
141 if (xpwrite(fd
, syslinux_adv
, 2 * ADV_SIZE
,
142 st
.st_size
- 2 * ADV_SIZE
) != 2 * ADV_SIZE
) {
152 fprintf(stderr
, "%s: cannot write auxilliary data (need --update)?\n",