--- /dev/null
+#ifndef GRUB_EMU_MISC_H
+#define GRUB_EMU_MISC_H 1
+
+#include <grub/symbol.h>
+#include <grub/types.h>
+
+#ifdef __NetBSD__
+/* NetBSD uses /boot for its boot block. */
+# define DEFAULT_DIRECTORY "/grub"
+#else
+# define DEFAULT_DIRECTORY "/boot/grub"
+#endif
+
+#define DEFAULT_DEVICE_MAP DEFAULT_DIRECTORY "/device.map"
+
+extern int verbosity;
+extern const char *program_name;
+
+void grub_init_all (void);
+void grub_fini_all (void);
+
++char *grub_make_system_path_relative_to_its_root (const char *path);
++
+void * EXPORT_FUNC(xmalloc) (grub_size_t size);
+void * EXPORT_FUNC(xrealloc) (void *ptr, grub_size_t size);
+char * EXPORT_FUNC(xstrdup) (const char *str);
+char * EXPORT_FUNC(xasprintf) (const char *fmt, ...);
+
+void EXPORT_FUNC(grub_util_warn) (const char *fmt, ...);
+void EXPORT_FUNC(grub_util_info) (const char *fmt, ...);
+void EXPORT_FUNC(grub_util_error) (const char *fmt, ...) __attribute__ ((noreturn));
+
+#ifndef HAVE_VASPRINTF
+int EXPORT_FUNC(vasprintf) (char **buf, const char *fmt, va_list ap);
+#endif
+
+#ifndef HAVE_ASPRINTF
+int EXPORT_FUNC(asprintf) (char **buf, const char *fmt, ...);
+#endif
+
+char * EXPORT_FUNC(xasprintf) (const char *fmt, ...);
+
+#endif /* GRUB_EMU_MISC_H */
#include <unistd.h>
#include <string.h>
#include <dirent.h>
++#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
++#include <stdint.h>
#ifdef __CYGWIN__
# include <sys/fcntl.h>
else
return 0;
}
--
if (strcmp (root_dev, "host") == 0)
dir = xstrdup (dir);
else
- dir = grub_get_prefix (dir);
- dir = make_system_path_relative_to_its_root (dir);
++ dir = grub_make_system_path_relative_to_its_root (dir);
prefix = xmalloc (strlen (root_dev) + 2 + strlen (dir) + 1);
sprintf (prefix, "(%s)%s", root_dev, dir);
free (dir);
--- /dev/null
+#include <config.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
++#include <stdint.h>
+#include <string.h>
+#include <sys/time.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <unistd.h>
+
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/env.h>
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/i18n.h>
+#include <grub/time.h>
+#include <grub/emu/misc.h>
+
+int verbosity;
+
+void
+grub_util_warn (const char *fmt, ...)
+{
+ va_list ap;
+
+ fprintf (stderr, _("%s: warn:"), program_name);
+ fprintf (stderr, " ");
+ va_start (ap, fmt);
+ vfprintf (stderr, fmt, ap);
+ va_end (ap);
+ fprintf (stderr, ".\n");
+ fflush (stderr);
+}
+
+void
+grub_util_info (const char *fmt, ...)
+{
+ if (verbosity > 0)
+ {
+ va_list ap;
+
+ fprintf (stderr, _("%s: info:"), program_name);
+ fprintf (stderr, " ");
+ va_start (ap, fmt);
+ vfprintf (stderr, fmt, ap);
+ va_end (ap);
+ fprintf (stderr, ".\n");
+ fflush (stderr);
+ }
+}
+
+void
+grub_util_error (const char *fmt, ...)
+{
+ va_list ap;
+
+ fprintf (stderr, _("%s: error:"), program_name);
+ fprintf (stderr, " ");
+ va_start (ap, fmt);
+ vfprintf (stderr, fmt, ap);
+ va_end (ap);
+ fprintf (stderr, ".\n");
+ exit (1);
+}
+
+void *
+xmalloc (grub_size_t size)
+{
+ void *p;
+
+ p = malloc (size);
+ if (! p)
+ grub_util_error ("out of memory");
+
+ return p;
+}
+
+void *
+xrealloc (void *ptr, grub_size_t size)
+{
+ ptr = realloc (ptr, size);
+ if (! ptr)
+ grub_util_error ("out of memory");
+
+ return ptr;
+}
+
+char *
+xstrdup (const char *str)
+{
+ size_t len;
+ char *newstr;
+
+ len = strlen (str);
+ newstr = (char *) xmalloc (len + 1);
+ memcpy (newstr, str, len + 1);
+
+ return newstr;
+}
+
+#ifndef HAVE_VASPRINTF
+
+int
+vasprintf (char **buf, const char *fmt, va_list ap)
+{
+ /* Should be large enough. */
+ *buf = xmalloc (512);
+
+ return vsprintf (*buf, fmt, ap);
+}
+
+#endif
+
+#ifndef HAVE_ASPRINTF
+
+int
+asprintf (char **buf, const char *fmt, ...)
+{
+ int status;
+ va_list ap;
+
+ va_start (ap, fmt);
+ status = vasprintf (*buf, fmt, ap);
+ va_end (ap);
+
+ return status;
+}
+
+#endif
+
+char *
+xasprintf (const char *fmt, ...)
+{
+ va_list ap;
+ char *result;
+
+ va_start (ap, fmt);
+ if (vasprintf (&result, fmt, ap) < 0)
+ {
+ if (errno == ENOMEM)
+ grub_util_error ("out of memory");
+ return NULL;
+ }
+
+ return result;
+}
+
+void
+grub_exit (void)
+{
+ exit (1);
+}
+
+grub_uint64_t
+grub_get_time_ms (void)
+{
+ struct timeval tv;
+
+ gettimeofday (&tv, 0);
+
+ return (tv.tv_sec * 1000 + tv.tv_usec / 1000);
+}
+
+grub_uint32_t
+grub_get_rtc (void)
+{
+ struct timeval tv;
+
+ gettimeofday (&tv, 0);
+
+ return (tv.tv_sec * GRUB_TICKS_PER_SECOND
+ + (((tv.tv_sec % GRUB_TICKS_PER_SECOND) * 1000000 + tv.tv_usec)
+ * GRUB_TICKS_PER_SECOND / 1000000));
+}
++
++
++/* This function never prints trailing slashes (so that its output
++ can be appended a slash unconditionally). */
++char *
++grub_make_system_path_relative_to_its_root (const char *path)
++{
++ struct stat st;
++ char *p, *buf, *buf2, *buf3;
++ uintptr_t offset = 0;
++ dev_t num;
++ size_t len;
++
++ /* canonicalize. */
++ p = canonicalize_file_name (path);
++
++ if (p == NULL)
++ grub_util_error ("failed to get canonical path of %s", path);
++
++ len = strlen (p) + 1;
++ buf = xstrdup (p);
++ free (p);
++
++ if (stat (buf, &st) < 0)
++ grub_util_error ("cannot stat %s: %s", buf, strerror (errno));
++
++ buf2 = xstrdup (buf);
++ num = st.st_dev;
++
++ /* This loop sets offset to the number of chars of the root
++ directory we're inspecting. */
++ while (1)
++ {
++ p = strrchr (buf, '/');
++ if (p == NULL)
++ /* This should never happen. */
++ grub_util_error ("FIXME: no / in buf. (make_system_path_relative_to_its_root)");
++ if (p != buf)
++ *p = 0;
++ else
++ *++p = 0;
++
++ if (stat (buf, &st) < 0)
++ grub_util_error ("cannot stat %s: %s", buf, strerror (errno));
++
++ /* buf is another filesystem; we found it. */
++ if (st.st_dev != num)
++ {
++ /* offset == 0 means path given is the mount point.
++ This works around special-casing of "/" in Un*x. This function never
++ prints trailing slashes (so that its output can be appended a slash
++ unconditionally). Each slash in is considered a preceding slash, and
++ therefore the root directory is an empty string. */
++ if (offset == 0)
++ {
++ free (buf);
++ free (buf2);
++ return xstrdup ("");
++ }
++ else
++ break;
++ }
++
++ offset = p - buf;
++ /* offset == 1 means root directory. */
++ if (offset == 1)
++ {
++ /* Include leading slash. */
++ offset = 0;
++ break;
++ }
++ }
++ free (buf);
++ buf3 = xstrdup (buf2 + offset);
++ free (buf2);
++
++#ifdef __CYGWIN__
++ if (st.st_dev != (DEV_CYGDRIVE_MAJOR << 16))
++ {
++ /* Reached some mount point not below /cygdrive.
++ GRUB does not know Cygwin's emulated mounts,
++ convert to Win32 path. */
++ grub_util_info ("Cygwin path = %s\n", buf3);
++ char * temp = get_win32_path (buf3);
++ free (buf3);
++ buf3 = temp;
++ }
++#endif
++
++ /* Remove trailing slashes, return empty string if root directory. */
++ len = strlen (buf3);
++ while (len > 0 && buf3[len - 1] == '/')
++ {
++ buf3[len - 1] = '\0';
++ len--;
++ }
++
++ return buf3;
++}
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <stdio.h>
#include <grub/util/misc.h>
++#include <grub/emu/misc.h>
#include <grub/i18n.h>
#include <getopt.h>
argument = argv[optind];
-- relpath = make_system_path_relative_to_its_root (argument);
++ relpath = grub_make_system_path_relative_to_its_root (argument);
printf ("%s\n", relpath);
free (relpath);
grub_util_info ("reading %s via OS facilities", path);
filebuf_via_sys = grub_util_read_image (path);
-- rel_path = make_system_path_relative_to_its_root (path);
++ rel_path = grub_make_system_path_relative_to_its_root (path);
grub_path = xasprintf ("(%s)%s", drive_name, rel_path);
free (rel_path);
grub_util_info ("reading %s via GRUB facilities", grub_path);
return ret;
}
- /* This function never prints trailing slashes (so that its output
- can be appended a slash unconditionally). */
- char *
- make_system_path_relative_to_its_root (const char *path)
+ #ifdef __CYGWIN__
+ /* Convert POSIX path to Win32 path,
+ remove drive letter, replace backslashes. */
+ static char *
+ get_win32_path (const char *path)
{
- struct stat st;
- char *p, *buf, *buf2, *buf3;
- uintptr_t offset = 0;
- dev_t num;
- size_t len;
-
- /* canonicalize. */
- p = canonicalize_file_name (path);
-
- if (p == NULL)
- grub_util_error ("failed to get canonical path of %s", path);
-
- len = strlen (p) + 1;
- buf = xstrdup (p);
- free (p);
-
- if (stat (buf, &st) < 0)
- grub_util_error ("cannot stat %s: %s", buf, strerror (errno));
-
- buf2 = xstrdup (buf);
- num = st.st_dev;
-
- /* This loop sets offset to the number of chars of the root
- directory we're inspecting. */
- while (1)
- {
- p = strrchr (buf, '/');
- if (p == NULL)
- /* This should never happen. */
- grub_util_error ("FIXME: no / in buf. (make_system_path_relative_to_its_root)");
- if (p != buf)
- *p = 0;
- else
- *++p = 0;
-
- if (stat (buf, &st) < 0)
- grub_util_error ("cannot stat %s: %s", buf, strerror (errno));
-
- /* buf is another filesystem; we found it. */
- if (st.st_dev != num)
- {
- /* offset == 0 means path given is the mount point.
- This works around special-casing of "/" in Un*x. This function never
- prints trailing slashes (so that its output can be appended a slash
- unconditionally). Each slash in is considered a preceding slash, and
- therefore the root directory is an empty string. */
- if (offset == 0)
- {
- free (buf);
- free (buf2);
- return xstrdup ("");
- }
- else
- break;
- }
-
- offset = p - buf;
- /* offset == 1 means root directory. */
- if (offset == 1)
- {
- free (buf);
- len = strlen (buf2);
- while (buf2[len - 1] == '/' && len > 1)
- {
- buf2[len - 1] = '\0';
- len--;
- }
- if (len > 1)
- return buf2;
- else
- {
- /* This means path given is just a backslash. As above
- we have to return an empty string. */
- free (buf2);
- return xstrdup ("");
- }
- }
- }
- free (buf);
- buf3 = xstrdup (buf2 + offset);
- free (buf2);
-
- len = strlen (buf3);
- while (buf3[len - 1] == '/' && len > 1)
- {
- buf3[len - 1] = '\0';
- len--;
- }
-
- return buf3;
+ char winpath[PATH_MAX];
+ if (cygwin_conv_path (CCP_POSIX_TO_WIN_A, path, winpath, sizeof(winpath)))
+ grub_util_error ("cygwin_conv_path() failed");
+
+ int len = strlen (winpath);
+ int offs = (len > 2 && winpath[1] == ':' ? 2 : 0);
+
+ int i;
+ for (i = offs; i < len; i++)
+ if (winpath[i] == '\\')
+ winpath[i] = '/';
+ return xstrdup (winpath + offs);
}
+ #endif
-/* This function never prints trailing slashes (so that its output
- can be appended a slash unconditionally). */
-char *
-make_system_path_relative_to_its_root (const char *path)
-{
- struct stat st;
- char *p, *buf, *buf2, *buf3;
- uintptr_t offset = 0;
- dev_t num;
- size_t len;
-
- /* canonicalize. */
- p = canonicalize_file_name (path);
-
- if (p == NULL)
- grub_util_error ("failed to get canonical path of %s", path);
-
- len = strlen (p) + 1;
- buf = xstrdup (p);
- free (p);
-
- if (stat (buf, &st) < 0)
- grub_util_error ("cannot stat %s: %s", buf, strerror (errno));
-
- buf2 = xstrdup (buf);
- num = st.st_dev;
-
- /* This loop sets offset to the number of chars of the root
- directory we're inspecting. */
- while (1)
- {
- p = strrchr (buf, '/');
- if (p == NULL)
- /* This should never happen. */
- grub_util_error ("FIXME: no / in buf. (make_system_path_relative_to_its_root)");
- if (p != buf)
- *p = 0;
- else
- *++p = 0;
-
- if (stat (buf, &st) < 0)
- grub_util_error ("cannot stat %s: %s", buf, strerror (errno));
-
- /* buf is another filesystem; we found it. */
- if (st.st_dev != num)
- {
- /* offset == 0 means path given is the mount point.
- This works around special-casing of "/" in Un*x. This function never
- prints trailing slashes (so that its output can be appended a slash
- unconditionally). Each slash in is considered a preceding slash, and
- therefore the root directory is an empty string. */
- if (offset == 0)
- {
- free (buf);
- free (buf2);
- return xstrdup ("");
- }
- else
- break;
- }
-
- offset = p - buf;
- /* offset == 1 means root directory. */
- if (offset == 1)
- {
- /* Include leading slash. */
- offset = 0;
- break;
- }
- }
- free (buf);
- buf3 = xstrdup (buf2 + offset);
- free (buf2);
-
-#ifdef __CYGWIN__
- if (st.st_dev != (DEV_CYGDRIVE_MAJOR << 16))
- {
- /* Reached some mount point not below /cygdrive.
- GRUB does not know Cygwin's emulated mounts,
- convert to Win32 path. */
- grub_util_info ("Cygwin path = %s\n", buf3);
- char * temp = get_win32_path (buf3);
- free (buf3);
- buf3 = temp;
- }
-#endif
-
- /* Remove trailing slashes, return empty string if root directory. */
- len = strlen (buf3);
- while (len > 0 && buf3[len - 1] == '/')
- {
- buf3[len - 1] = '\0';
- len--;
- }
-
- return buf3;
-}
-
#ifdef GRUB_UTIL
void
grub_util_init_nls (void)