summaryrefslogtreecommitdiff
path: root/innobase/os/os0file.c
diff options
context:
space:
mode:
Diffstat (limited to 'innobase/os/os0file.c')
-rw-r--r--innobase/os/os0file.c215
1 files changed, 206 insertions, 9 deletions
diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c
index a87ab974b83..7973cfc6fe8 100644
--- a/innobase/os/os0file.c
+++ b/innobase/os/os0file.c
@@ -716,7 +716,9 @@ os_file_create_simple(
string */
ulint create_mode,/* in: OS_FILE_OPEN if an existing file is opened
(if does not exist, error), or OS_FILE_CREATE if a new
- file is created (if exists, error) */
+ file is created (if exists, error), or
+ OS_FILE_CREATE_PATH if new file (if exists, error) and
+ subdirectories along its path are created (if needed)*/
ulint access_type,/* in: OS_FILE_READ_ONLY or OS_FILE_READ_WRITE */
ibool* success)/* out: TRUE if succeed, FALSE if error */
{
@@ -734,6 +736,14 @@ try_again:
create_flag = OPEN_EXISTING;
} else if (create_mode == OS_FILE_CREATE) {
create_flag = CREATE_NEW;
+ } else if (create_mode == OS_FILE_CREATE_PATH) {
+ /* create subdirs along the path if needed */
+ *success = os_file_create_subdirs_if_needed(name);
+ if (!*success) {
+ ut_error;
+ }
+ create_flag = CREATE_NEW;
+ create_mode = OS_FILE_CREATE;
} else {
create_flag = 0;
ut_error;
@@ -787,6 +797,14 @@ try_again:
}
} else if (create_mode == OS_FILE_CREATE) {
create_flag = O_RDWR | O_CREAT | O_EXCL;
+ } else if (create_mode == OS_FILE_CREATE_PATH) {
+ /* create subdirs along the path if needed */
+ *success = os_file_create_subdirs_if_needed(name);
+ if (!*success) {
+ return (-1);
+ }
+ create_flag = O_RDWR | O_CREAT | O_EXCL;
+ create_mode = OS_FILE_CREATE;
} else {
create_flag = 0;
ut_error;
@@ -1068,7 +1086,7 @@ try_again:
} else if (type == OS_DATA_FILE) {
type_str = "DATA";
} else {
- ut_a(0);
+ ut_error;
}
if (purpose == OS_FILE_AIO) {
@@ -1076,7 +1094,7 @@ try_again:
} else if (purpose == OS_FILE_NORMAL) {
purpose_str = "NORMAL";
} else {
- ut_a(0);
+ ut_error;
}
/* printf("Opening file %s, mode %s, type %s, purpose %s\n",
@@ -1558,7 +1576,7 @@ os_file_flush(
/* It is a fatal error if a file flush does not succeed, because then
the database can get corrupt on disk */
- ut_a(0);
+ ut_error;
return(FALSE);
#else
@@ -1593,7 +1611,7 @@ os_file_flush(
/* It is a fatal error if a file flush does not succeed, because then
the database can get corrupt on disk */
- ut_a(0);
+ ut_error;
return(FALSE);
#endif
@@ -2114,6 +2132,185 @@ retry:
#endif
}
+/***********************************************************************
+Check the existence and type of the given file. */
+
+ibool
+os_file_status(
+/*===========*/
+ /* out: TRUE if call succeeded */
+ char* path, /* in: pathname of the file */
+ ibool* exists, /* out: TRUE if file exists */
+ os_file_type_t* type) /* out: type of the file (if it exists) */
+{
+#ifdef __WIN__
+ int ret;
+ struct _stat statinfo;
+
+ ret = _stat(path, &statinfo);
+ if (ret && (errno == ENOENT || errno == ENOTDIR)) {
+ /* file does not exist */
+ *exists = FALSE;
+ return(TRUE);
+ } else if (ret) {
+ /* file exists, but stat call failed */
+
+ os_file_handle_error_no_exit(0, path, "stat");
+
+ return(FALSE);
+ }
+
+ if (_S_IFDIR & statinfo.st_mode) {
+ *type = OS_FILE_TYPE_DIR;
+ } else if (_S_IFREG & statinfo.st_mode) {
+ *type = OS_FILE_TYPE_FILE;
+ } else {
+ *type = OS_FILE_TYPE_UNKNOWN;
+ }
+
+ *exists = TRUE;
+
+ return(TRUE);
+#else
+ int ret;
+ struct stat statinfo;
+
+ ret = stat(path, &statinfo);
+ if (ret && (errno == ENOENT || errno == ENOTDIR)) {
+ /* file does not exist */
+ *exists = FALSE;
+ return(TRUE);
+ } else if (ret) {
+ /* file exists, but stat call failed */
+
+ os_file_handle_error_no_exit(0, path, "stat");
+
+ return(FALSE);
+ }
+
+ if (S_ISDIR(statinfo.st_mode)) {
+ *type = OS_FILE_TYPE_DIR;
+ } else if (S_ISLNK(statinfo.st_mode)) {
+ *type = OS_FILE_TYPE_LINK;
+ } else if (S_ISREG(statinfo.st_mode)) {
+ *type = OS_FILE_TYPE_FILE;
+ } else {
+ *type = OS_FILE_TYPE_UNKNOWN;
+ }
+
+ *exists = TRUE;
+
+ return(TRUE);
+#endif
+}
+
+/* path name separator character */
+#ifdef __WIN__
+# define OS_FILE_PATH_SEPARATOR '\\'
+#else
+# define OS_FILE_PATH_SEPARATOR '/'
+#endif
+
+/********************************************************************
+The function os_file_dirname returns a directory component of a
+null-terminated pathname string. In the usual case, dirname returns
+the string up to, but not including, the final '/', and basename
+is the component following the final '/'. Trailing '/' charac­
+ters are not counted as part of the pathname.
+
+If path does not contain a slash, dirname returns the string ".".
+
+Concatenating the string returned by dirname, a "/", and the basename
+yields a complete pathname.
+
+The return value is a copy of the directory component of the pathname.
+The copy is allocated from heap. It is the caller responsibility
+to free it after it is no longer needed.
+
+The following list of examples (taken from SUSv2) shows the strings
+returned by dirname and basename for different paths:
+
+ path dirname basename
+ "/usr/lib" "/usr" "lib"
+ "/usr/" "/" "usr"
+ "usr" "." "usr"
+ "/" "/" "/"
+ "." "." "."
+ ".." "." ".."
+*/
+
+char*
+os_file_dirname(
+/*============*/
+ /* out, own: directory component of the
+ pathname */
+ char* path) /* in: pathname */
+{
+ char* dir;
+ int i, length, last_slash;
+
+ /* find the offset of the last slash */
+ length = ut_strlen(path);
+ for (i = length - 1; i >= 0 && path[i] != OS_FILE_PATH_SEPARATOR; i++);
+ last_slash = i;
+
+ if (last_slash < 0) {
+ /* no slash in the path, return "." */
+ return(ut_strdup((char*)"."));
+ }
+
+ /* ok, there is a slash */
+
+ if (last_slash == 0) {
+ /* last slash is the first char of the path */
+ return(ut_strdup((char*)"/"));
+ }
+
+ /* non-trivial directory component */
+ dir = ut_strdup(path);
+ dir[last_slash] = 0;
+
+ return(dir);
+}
+
+/********************************************************************
+Creates all missing subdirectories along the given path. */
+
+ibool
+os_file_create_subdirs_if_needed(
+/*=============================*/
+ /* out: TRUE if call succeeded
+ FALSE otherwise */
+ char* path) /* in: path name */
+{
+ char* subdir;
+ static char rootdir[2] = { OS_FILE_PATH_SEPARATOR, 0 };
+ ibool success, subdir_exists;
+ os_file_type_t type;
+
+ subdir = os_file_dirname(path);
+ if (0 == strcmp(subdir, rootdir) || 0 == strcmp(subdir, ".")) {
+ /* subdir is root or cwd, nothing to do */
+ ut_free(subdir);
+ return(TRUE);
+ }
+
+ /* test if subdir exists */
+ success = os_file_status(subdir, &subdir_exists, &type);
+ if (success && !subdir_exists) {
+ /* subdir does not exist, create it */
+ success = os_file_create_subdirs_if_needed(subdir);
+ if (!success) {
+ ut_free(subdir);
+ return(FALSE);
+ }
+ success = os_file_create_directory(subdir, FALSE);
+ }
+
+ ut_free(subdir);
+ return(success);
+}
+
/********************************************************************
Returns a pointer to the nth slot in the aio array. */
static
@@ -2430,7 +2627,7 @@ os_aio_get_array_no(
return(3);
} else {
- ut_a(0);
+ ut_error;
return(0);
}
@@ -2457,7 +2654,7 @@ os_aio_get_array_from_no(
return(os_aio_write_array);
} else {
- ut_a(0);
+ ut_error;
return(NULL);
}
@@ -3047,7 +3244,7 @@ os_aio_posix_handle(
if (sig != SIGRTMIN + 1 + array_no) {
- ut_a(0);
+ ut_error;
return(FALSE);
}
@@ -3312,7 +3509,7 @@ consecutive_loop:
slot->name, (ulong) slot->offset_high,
(ulong) slot->offset,
(ulong) total_len);
- ut_a(0);
+ ut_error;
}
/* Do a 'last millisecond' check that the page end