closedir to handle filename charset translation.
+2013-10-15 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Add wrappers around rename, unlink, mkdir, opendir, readdir and
+ closedir to handle filename charset translation.
+
2013-10-15 Vladimir Serbinenko <phcoder@gmail.com>
* include/grub/emu/hostdisk.h: Move file operations to
#include <stdio.h>
#include <errno.h>
-
-/* dirent.d_type is a BSD extension, not part of POSIX */
#include <sys/stat.h>
#include <string.h>
struct grub_hostfs_data
{
char *filename;
- FILE *f;
+ grub_util_fd_t f;
};
static grub_err_t
grub_hostfs_dir (grub_device_t device, const char *path,
grub_fs_dir_hook_t hook, void *hook_data)
{
- DIR *dir;
+ grub_util_fd_dir_t dir;
/* Check if the disk is our dummy disk. */
if (grub_strcmp (device->disk->name, "host"))
return grub_error (GRUB_ERR_BAD_FS, "not a hostfs");
- dir = opendir (path);
+ dir = grub_util_fd_opendir (path);
if (! dir)
return grub_error (GRUB_ERR_BAD_FILENAME,
N_("can't open `%s': %s"), path,
- strerror (errno));
+ grub_util_fd_strerror ());
while (1)
{
- struct dirent *de;
+ grub_util_fd_dirent_t de;
struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info));
- de = readdir (dir);
+ de = grub_util_fd_readdir (dir);
if (! de)
break;
}
- closedir (dir);
+ grub_util_fd_closedir (dir);
return GRUB_ERR_NONE;
}
static grub_err_t
grub_hostfs_open (struct grub_file *file, const char *name)
{
- FILE *f;
+ grub_util_fd_t f;
struct grub_hostfs_data *data;
- f = grub_util_fopen (name, "rb");
- if (! f)
+ f = grub_util_fd_open (name, GRUB_UTIL_FD_O_RDONLY);
+ if (! GRUB_UTIL_FD_IS_VALID (f))
return grub_error (GRUB_ERR_BAD_FILENAME,
N_("can't open `%s': %s"), name,
strerror (errno));
data = grub_malloc (sizeof (*data));
if (!data)
{
- fclose (f);
+ grub_util_fd_close (f);
return grub_errno;
}
data->filename = grub_strdup (name);
if (!data->filename)
{
grub_free (data);
- fclose (f);
+ grub_util_fd_close (f);
return grub_errno;
}
file->data = data;
-#if defined (__CYGWIN__) || defined (__MINGW32__) || defined (__AROS__)
- fseek (f, 0, SEEK_END);
- file->size = ftello (f);
- fseek (f, 0, SEEK_SET);
-#else
- file->size = grub_util_get_fd_size (fileno (f), name, NULL);
-#endif
+ file->size = grub_util_get_fd_size (f, name, NULL);
return GRUB_ERR_NONE;
}
struct grub_hostfs_data *data;
data = file->data;
- if (fseeko (data->f, file->offset, SEEK_SET) != 0)
+ if (grub_util_fd_seek (data->f, file->offset) != 0)
{
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("cannot seek `%s': %s"),
- data->filename, strerror (errno));
+ data->filename, grub_util_fd_strerror ());
return -1;
}
- unsigned int s = fread (buf, 1, len, data->f);
+ unsigned int s = grub_util_fd_read (data->f, buf, len);
if (s != len)
grub_error (GRUB_ERR_FILE_READ_ERROR, N_("cannot read `%s': %s"),
- data->filename, strerror (errno));
+ data->filename, grub_util_fd_strerror ());
return (signed) s;
}
struct grub_hostfs_data *data;
data = file->data;
- fclose (data->f);
+ grub_util_fd_close (data->f);
grub_free (data->filename);
grub_free (data);
return ret;
}
+void
+grub_util_mkdir (const char *dir)
+{
+ LPTSTR windows_name;
+
+ windows_name = grub_util_get_windows_path (dir);
+ CreateDirectory (windows_name, NULL);
+ free (windows_name);
+}
+
+int
+grub_util_rename (const char *from, const char *to)
+{
+ LPTSTR windows_from, windows_to;
+ int ret;
+
+ windows_from = grub_util_get_windows_path (from);
+ windows_to = grub_util_get_windows_path (to);
+ ret = !MoveFile (windows_from, windows_to);
+ free (windows_from);
+ free (windows_to);
+ return ret;
+}
+
+struct grub_util_fd_dir
+{
+ WIN32_FIND_DATA fd;
+ HANDLE hnd;
+ int is_end;
+ char *last;
+};
+
+grub_util_fd_dir_t
+grub_util_fd_opendir (const char *name)
+{
+ struct grub_util_fd_dir *ret;
+ LPTSTR name_windows;
+ LPTSTR pattern;
+ ssize_t l;
+
+ name_windows = grub_util_get_windows_path (name);
+ for (l = 0; name_windows[l]; l++);
+ for (l--; l >= 0 && (name_windows[l] == '\\' || name_windows[l] == '/'); l--);
+ l++;
+ pattern = xmalloc ((l + 3) * sizeof (pattern[0]));
+ memcpy (pattern, name_windows, l * sizeof (pattern[0]));
+ pattern[l] = '\\';
+ pattern[l + 1] = '*';
+ pattern[l + 2] = '\0';
+
+ ret = xmalloc (sizeof (*ret));
+ memset (ret, 0, sizeof (*ret));
+
+ ret->hnd = FindFirstFile (pattern, &ret->fd);
+
+ free (name_windows);
+ free (pattern);
+
+ if (ret->hnd == INVALID_HANDLE_VALUE)
+ {
+ DWORD err = GetLastError ();
+ if (err == ERROR_FILE_NOT_FOUND)
+ {
+ ret->is_end = 1;
+ return ret;
+ }
+ return NULL;
+ }
+ return ret;
+}
+
+void
+grub_util_fd_closedir (grub_util_fd_dir_t dirp)
+{
+ if (dirp->hnd != INVALID_HANDLE_VALUE)
+ CloseHandle (dirp->hnd);
+ free (dirp->last);
+ free (dirp);
+}
+
+grub_util_fd_dirent_t
+grub_util_fd_readdir (grub_util_fd_dir_t dirp)
+{
+ char *ret;
+ free (dirp->last);
+ dirp->last = NULL;
+
+ if (dirp->is_end)
+ return NULL;
+
+ ret = grub_util_tchar_to_utf8 (dirp->fd.cFileName);
+ dirp->last = ret;
+
+ if (!FindNextFile (dirp->hnd, &dirp->fd))
+ dirp->is_end = 1;
+ return (grub_util_fd_dirent_t) ret;
+}
+
+int
+grub_util_unlink (const char *name)
+{
+ LPTSTR name_windows;
+ int ret;
+
+ name_windows = grub_util_get_windows_path (name);
+
+ ret = !DeleteFile (name_windows);
+ free (name_windows);
+ return ret;
+}
#ifdef __MINGW32__
#include <config.h>
#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <stdio.h>
+
+typedef struct dirent *grub_util_fd_dirent_t;
+typedef DIR *grub_util_fd_dir_t;
+
+static inline grub_util_fd_dir_t
+grub_util_fd_opendir (const char *name)
+{
+ return opendir (name);
+}
+
+static inline void
+grub_util_fd_closedir (grub_util_fd_dir_t dirp)
+{
+ closedir (dirp);
+}
+
+static inline grub_util_fd_dirent_t
+grub_util_fd_readdir (grub_util_fd_dir_t dirp)
+{
+ return readdir (dirp);
+}
+
+static inline int
+grub_util_unlink (const char *pathname)
+{
+ return unlink (pathname);
+}
+
+static inline int
+grub_util_rename (const char *from, const char *to)
+{
+ return rename (from, to);
+}
+
+#define grub_util_mkdir(a) mkdir (a)
+
struct grub_util_fd
{
enum { GRUB_UTIL_FD_FILE, GRUB_UTIL_FD_DISK } type;
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <stdio.h>
+
+typedef struct dirent *grub_util_fd_dirent_t;
+typedef DIR *grub_util_fd_dir_t;
+
+static inline grub_util_fd_dir_t
+grub_util_fd_opendir (const char *name)
+{
+ return opendir (name);
+}
+
+static inline void
+grub_util_fd_closedir (grub_util_fd_dir_t dirp)
+{
+ closedir (dirp);
+}
+
+static inline grub_util_fd_dirent_t
+grub_util_fd_readdir (grub_util_fd_dir_t dirp)
+{
+ return readdir (dirp);
+}
+
+static inline int
+grub_util_unlink (const char *pathname)
+{
+ return unlink (pathname);
+}
+
+static inline int
+grub_util_rename (const char *from, const char *to)
+{
+ return rename (from, to);
+}
+
+#define grub_util_mkdir(a) mkdir ((a), 0700)
#if defined (__NetBSD__)
/* NetBSD uses /boot for its boot block. */
#define DEFAULT_DIRECTORY "C:\\"GRUB_BOOT_DIR_NAME"\\"GRUB_DIR_NAME
#define DEFAULT_DEVICE_MAP DEFAULT_DIRECTORY "/device.map"
+struct grub_util_fd_dirent
+{
+ char d_name[0];
+};
+struct grub_util_fd_dir;
+typedef struct grub_util_fd_dirent *grub_util_fd_dirent_t;
+typedef struct grub_util_fd_dir *grub_util_fd_dir_t;
+
+int
+grub_util_rename (const char *from, const char *to);
+int
+grub_util_unlink (const char *name);
+void
+grub_util_mkdir (const char *dir);
+
+grub_util_fd_dir_t
+grub_util_fd_opendir (const char *name);
+
+void
+grub_util_fd_closedir (grub_util_fd_dir_t dirp);
+
+grub_util_fd_dirent_t
+grub_util_fd_readdir (grub_util_fd_dir_t dirp);
+
enum grub_util_fd_open_flags_t
{
GRUB_UTIL_FD_O_RDONLY = 1,