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>
39 * Read the ADV from an existing instance, or initialize if invalid.
40 * Returns -1 on fatal errors, 0 if ADV is okay, 1 if the ADV is
41 * invalid, and 2 if the file does not exist.
43 int read_adv(const char *path
, const char *cfg
)
51 rv
= asprintf(&file
, "%s%s%s", path
,
52 path
[0] && path
[strlen(path
) - 1] == '/' ? "" : "/", cfg
);
54 if (rv
< 0 || !file
) {
59 fd
= open(file
, O_RDONLY
);
61 if (errno
!= ENOENT
) {
64 syslinux_reset_adv(syslinux_adv
);
65 err
= 2; /* Nonexistence is not a fatal error */
67 } else if (fstat(fd
, &st
)) {
69 } else if (st
.st_size
< 2 * ADV_SIZE
) {
70 /* Too small to be useful */
71 syslinux_reset_adv(syslinux_adv
);
72 err
= 0; /* Nothing to read... */
73 } else if (xpread(fd
, syslinux_adv
, 2 * ADV_SIZE
,
74 st
.st_size
- 2 * ADV_SIZE
) != 2 * ADV_SIZE
) {
77 /* We got it... maybe? */
78 err
= syslinux_validate_adv(syslinux_adv
) ? 1 : 0;
93 * Update the ADV in an existing installation.
95 int write_adv(const char *path
, const char *cfg
)
97 unsigned char advtmp
[2 * ADV_SIZE
];
104 rv
= asprintf(&file
, "%s%s%s", path
,
105 path
[0] && path
[strlen(path
) - 1] == '/' ? "" : "/", cfg
);
107 if (rv
< 0 || !file
) {
112 fd
= open(file
, O_RDONLY
);
115 } else if (fstat(fd
, &st
)) {
117 } else if (st
.st_size
< 2 * ADV_SIZE
) {
118 /* Too small to be useful */
120 } else if (xpread(fd
, advtmp
, 2 * ADV_SIZE
,
121 st
.st_size
- 2 * ADV_SIZE
) != 2 * ADV_SIZE
) {
124 /* We got it... maybe? */
125 err
= syslinux_validate_adv(advtmp
) ? -2 : 0;
127 /* Got a good one, write our own ADV here */
128 clear_attributes(fd
);
130 /* Need to re-open read-write */
132 fd
= open(file
, O_RDWR
| O_SYNC
);
134 fprintf(stderr
, "Cannot open file '%s' in read/write mode !\nFatal error, exiting.\n", file
);
136 } else if (fstat(fd
, &xst
) || xst
.st_ino
!= st
.st_ino
||
137 xst
.st_dev
!= st
.st_dev
|| xst
.st_size
!= st
.st_size
) {
138 fprintf(stderr
, "%s: race condition on write\n", file
);
141 /* Write our own version ... */
142 if (xpwrite(fd
, syslinux_adv
, 2 * ADV_SIZE
,
143 st
.st_size
- 2 * ADV_SIZE
) != 2 * ADV_SIZE
) {
153 fprintf(stderr
, "%s: cannot write auxiliary data (need --update)?\n",