Add wrappers around rename, unlink, mkdir, opendir, readdir and

closedir to handle filename charset translation.
This commit is contained in:
Vladimir 'phcoder' Serbinenko 2013-10-15 14:11:34 +02:00
parent d7750b324f
commit f6a81f0aaf
6 changed files with 237 additions and 26 deletions

View file

@ -1,3 +1,8 @@
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> 2013-10-15 Vladimir Serbinenko <phcoder@gmail.com>
* include/grub/emu/hostdisk.h: Move file operations to * include/grub/emu/hostdisk.h: Move file operations to

View file

@ -34,8 +34,6 @@
#include <stdio.h> #include <stdio.h>
#include <errno.h> #include <errno.h>
/* dirent.d_type is a BSD extension, not part of POSIX */
#include <sys/stat.h> #include <sys/stat.h>
#include <string.h> #include <string.h>
@ -63,32 +61,32 @@ is_dir (const char *path, const char *name)
struct grub_hostfs_data struct grub_hostfs_data
{ {
char *filename; char *filename;
FILE *f; grub_util_fd_t f;
}; };
static grub_err_t static grub_err_t
grub_hostfs_dir (grub_device_t device, const char *path, grub_hostfs_dir (grub_device_t device, const char *path,
grub_fs_dir_hook_t hook, void *hook_data) 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. */ /* Check if the disk is our dummy disk. */
if (grub_strcmp (device->disk->name, "host")) if (grub_strcmp (device->disk->name, "host"))
return grub_error (GRUB_ERR_BAD_FS, "not a hostfs"); return grub_error (GRUB_ERR_BAD_FS, "not a hostfs");
dir = opendir (path); dir = grub_util_fd_opendir (path);
if (! dir) if (! dir)
return grub_error (GRUB_ERR_BAD_FILENAME, return grub_error (GRUB_ERR_BAD_FILENAME,
N_("can't open `%s': %s"), path, N_("can't open `%s': %s"), path,
strerror (errno)); grub_util_fd_strerror ());
while (1) while (1)
{ {
struct dirent *de; grub_util_fd_dirent_t de;
struct grub_dirhook_info info; struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info)); grub_memset (&info, 0, sizeof (info));
de = readdir (dir); de = grub_util_fd_readdir (dir);
if (! de) if (! de)
break; break;
@ -97,7 +95,7 @@ grub_hostfs_dir (grub_device_t device, const char *path,
} }
closedir (dir); grub_util_fd_closedir (dir);
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
@ -106,25 +104,25 @@ grub_hostfs_dir (grub_device_t device, const char *path,
static grub_err_t static grub_err_t
grub_hostfs_open (struct grub_file *file, const char *name) grub_hostfs_open (struct grub_file *file, const char *name)
{ {
FILE *f; grub_util_fd_t f;
struct grub_hostfs_data *data; struct grub_hostfs_data *data;
f = grub_util_fopen (name, "rb"); f = grub_util_fd_open (name, GRUB_UTIL_FD_O_RDONLY);
if (! f) if (! GRUB_UTIL_FD_IS_VALID (f))
return grub_error (GRUB_ERR_BAD_FILENAME, return grub_error (GRUB_ERR_BAD_FILENAME,
N_("can't open `%s': %s"), name, N_("can't open `%s': %s"), name,
strerror (errno)); strerror (errno));
data = grub_malloc (sizeof (*data)); data = grub_malloc (sizeof (*data));
if (!data) if (!data)
{ {
fclose (f); grub_util_fd_close (f);
return grub_errno; return grub_errno;
} }
data->filename = grub_strdup (name); data->filename = grub_strdup (name);
if (!data->filename) if (!data->filename)
{ {
grub_free (data); grub_free (data);
fclose (f); grub_util_fd_close (f);
return grub_errno; return grub_errno;
} }
@ -132,13 +130,7 @@ grub_hostfs_open (struct grub_file *file, const char *name)
file->data = data; file->data = data;
#if defined (__CYGWIN__) || defined (__MINGW32__) || defined (__AROS__) file->size = grub_util_get_fd_size (f, name, NULL);
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
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
@ -149,17 +141,17 @@ grub_hostfs_read (grub_file_t file, char *buf, grub_size_t len)
struct grub_hostfs_data *data; struct grub_hostfs_data *data;
data = file->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"), grub_error (GRUB_ERR_OUT_OF_RANGE, N_("cannot seek `%s': %s"),
data->filename, strerror (errno)); data->filename, grub_util_fd_strerror ());
return -1; 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) if (s != len)
grub_error (GRUB_ERR_FILE_READ_ERROR, N_("cannot read `%s': %s"), 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; return (signed) s;
} }
@ -170,7 +162,7 @@ grub_hostfs_close (grub_file_t file)
struct grub_hostfs_data *data; struct grub_hostfs_data *data;
data = file->data; data = file->data;
fclose (data->f); grub_util_fd_close (data->f);
grub_free (data->filename); grub_free (data->filename);
grub_free (data); grub_free (data);

View file

@ -291,6 +291,116 @@ canonicalize_file_name (const char *path)
return ret; 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__ #ifdef __MINGW32__

View file

@ -22,6 +22,48 @@
#include <config.h> #include <config.h>
#include <stdarg.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 struct grub_util_fd
{ {
enum { GRUB_UTIL_FD_FILE, GRUB_UTIL_FD_DISK } type; enum { GRUB_UTIL_FD_FILE, GRUB_UTIL_FD_DISK } type;

View file

@ -28,6 +28,44 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.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__) #if defined (__NetBSD__)
/* NetBSD uses /boot for its boot block. */ /* NetBSD uses /boot for its boot block. */

View file

@ -31,6 +31,30 @@ typedef HANDLE grub_util_fd_t;
#define DEFAULT_DIRECTORY "C:\\"GRUB_BOOT_DIR_NAME"\\"GRUB_DIR_NAME #define DEFAULT_DIRECTORY "C:\\"GRUB_BOOT_DIR_NAME"\\"GRUB_DIR_NAME
#define DEFAULT_DEVICE_MAP DEFAULT_DIRECTORY "/device.map" #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 enum grub_util_fd_open_flags_t
{ {
GRUB_UTIL_FD_O_RDONLY = 1, GRUB_UTIL_FD_O_RDONLY = 1,