diff --git a/ChangeLog b/ChangeLog index 620672ead..d51d82dc4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2013-10-15 Vladimir Serbinenko + + Add wrappers around rename, unlink, mkdir, opendir, readdir and + closedir to handle filename charset translation. + 2013-10-15 Vladimir Serbinenko * include/grub/emu/hostdisk.h: Move file operations to diff --git a/grub-core/kern/emu/hostfs.c b/grub-core/kern/emu/hostfs.c index 3d9cf24b0..719c624de 100644 --- a/grub-core/kern/emu/hostfs.c +++ b/grub-core/kern/emu/hostfs.c @@ -34,8 +34,6 @@ #include #include - -/* dirent.d_type is a BSD extension, not part of POSIX */ #include #include @@ -63,32 +61,32 @@ is_dir (const char *path, const char *name) 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; @@ -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; } @@ -106,25 +104,25 @@ grub_hostfs_dir (grub_device_t device, const char *path, 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; } @@ -132,13 +130,7 @@ grub_hostfs_open (struct grub_file *file, const char *name) 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; } @@ -149,17 +141,17 @@ grub_hostfs_read (grub_file_t file, char *buf, grub_size_t len) 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; } @@ -170,7 +162,7 @@ grub_hostfs_close (grub_file_t file) struct grub_hostfs_data *data; data = file->data; - fclose (data->f); + grub_util_fd_close (data->f); grub_free (data->filename); grub_free (data); diff --git a/grub-core/osdep/windows/hostdisk.c b/grub-core/osdep/windows/hostdisk.c index 06f25aac2..f0318faf8 100644 --- a/grub-core/osdep/windows/hostdisk.c +++ b/grub-core/osdep/windows/hostdisk.c @@ -291,6 +291,116 @@ canonicalize_file_name (const char *path) 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__ diff --git a/include/grub/osdep/hostfile_aros.h b/include/grub/osdep/hostfile_aros.h index c1ee49e3a..3a5043587 100644 --- a/include/grub/osdep/hostfile_aros.h +++ b/include/grub/osdep/hostfile_aros.h @@ -22,6 +22,48 @@ #include #include +#include +#include +#include +#include +#include +#include + +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; diff --git a/include/grub/osdep/hostfile_unix.h b/include/grub/osdep/hostfile_unix.h index cdd98f703..8a0d52acd 100644 --- a/include/grub/osdep/hostfile_unix.h +++ b/include/grub/osdep/hostfile_unix.h @@ -28,6 +28,44 @@ #include #include #include +#include +#include +#include + +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. */ diff --git a/include/grub/osdep/hostfile_windows.h b/include/grub/osdep/hostfile_windows.h index e04dfbeb0..21419de3c 100644 --- a/include/grub/osdep/hostfile_windows.h +++ b/include/grub/osdep/hostfile_windows.h @@ -31,6 +31,30 @@ typedef HANDLE grub_util_fd_t; #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,