📄 io.c
字号:
const char *suffix, svn_boolean_t delete_on_close, apr_pool_t *pool){ return svn_io_open_unique_file2(f, unique_name_p, path, suffix, delete_on_close ? svn_io_file_del_on_close : svn_io_file_del_none, pool);}svn_error_t *svn_io_create_unique_link(const char **unique_name_p, const char *path, const char *dest, const char *suffix, apr_pool_t *pool){#ifdef HAVE_SYMLINK unsigned int i; const char *unique_name; const char *unique_name_apr; const char *dest_apr; int rv;#ifdef AS400_UTF8 const char *dest_apr_ebcdic;#endif SVN_ERR(svn_path_cstring_from_utf8(&dest_apr, dest, pool));#ifdef AS400_UTF8 /* On OS400 with UTF support a native cstring is UTF-8, but * symlink() *really* needs EBCDIC paths. */ SVN_ERR(svn_utf_cstring_from_utf8_ex2(&dest_apr_ebcdic, dest_apr, (const char*)0, pool)); dest_apr = dest_apr_ebcdic;#endif for (i = 1; i <= 99999; i++) { apr_status_t apr_err; /* Special case the first attempt -- if we can avoid having a generated numeric portion at all, that's best. So first we try with just the suffix; then future tries add a number before the suffix. (A do-while loop could avoid the repeated conditional, but it's not worth the clarity loss.) If the first attempt fails, the first number will be "2". This is good, since "1" would misleadingly imply that the second attempt was actually the first... and if someone's got conflicts on their conflicts, we probably don't want to add to their confusion :-). */ if (i == 1) unique_name = apr_psprintf(pool, "%s%s", path, suffix); else unique_name = apr_psprintf(pool, "%s.%u%s", path, i, suffix); /* Hmmm. Ideally, we would append to a native-encoding buf before starting iteration, then convert back to UTF-8 for return. But I suppose that would make the appending code sensitive to i18n in a way it shouldn't be... Oh well. */#ifndef AS400_UTF8 SVN_ERR(svn_path_cstring_from_utf8(&unique_name_apr, unique_name, pool));#else /* On OS400 with UTF support a native cstring is UTF-8, * but symlink() *really* needs an EBCDIC path. */ SVN_ERR(svn_utf_cstring_from_utf8_ex2(&unique_name_apr, unique_name, (const char*)0, pool));#endif do { rv = symlink(dest_apr, unique_name_apr); } while (rv == -1 && APR_STATUS_IS_EINTR(apr_get_os_error())); apr_err = apr_get_os_error(); if (rv == -1 && APR_STATUS_IS_EEXIST(apr_err)) continue; else if (rv == -1 && apr_err) { /* On Win32, CreateFile failswith an "Access Denied" error code, rather than "File Already Exists", if the colliding name belongs to a directory. */ if (APR_STATUS_IS_EACCES(apr_err)) { apr_finfo_t finfo; apr_status_t apr_err_2 = apr_stat(&finfo, unique_name_apr, APR_FINFO_TYPE, pool); if (!apr_err_2 && (finfo.filetype == APR_DIR)) continue; /* Else ignore apr_err_2; better to fall through and return the original error. */ } *unique_name_p = NULL; return svn_error_wrap_apr(apr_err, _("Can't open '%s'"), svn_path_local_style(unique_name, pool)); } else { *unique_name_p = unique_name; return SVN_NO_ERROR; } } *unique_name_p = NULL; return svn_error_createf(SVN_ERR_IO_UNIQUE_NAMES_EXHAUSTED, NULL, _("Unable to make name for '%s'"), svn_path_local_style(path, pool));#else return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL, _("Symbolic links are not supported on this " "platform"));#endif}svn_error_t *svn_io_read_link(svn_string_t **dest, const char *path, apr_pool_t *pool){#ifdef HAVE_READLINK svn_string_t dest_apr; const char *path_apr; char buf[1025]; int rv;#ifdef AS400_UTF8 const char *buf_utf8;#endif #ifndef AS400_UTF8 SVN_ERR(svn_path_cstring_from_utf8(&path_apr, path, pool));#else /* On OS400 with UTF support a native cstring is UTF-8, but * readlink() *really* needs an EBCDIC path. */ SVN_ERR(svn_utf_cstring_from_utf8_ex2(&path_apr, path, (const char*)0, pool));#endif do { rv = readlink(path_apr, buf, sizeof(buf) - 1); } while (rv == -1 && APR_STATUS_IS_EINTR(apr_get_os_error())); if (rv == -1) return svn_error_wrap_apr (apr_get_os_error(), _("Can't read contents of link")); buf[rv] = '\0'; dest_apr.data = buf; dest_apr.len = rv;#ifndef AS400_UTF8 /* ### Cast needed, one of these interfaces is wrong */ SVN_ERR(svn_utf_string_to_utf8((const svn_string_t **)dest, &dest_apr, pool));#else /* The buf filled by readline() is ebcdic encoded * despite V5R4's UTF support. */ SVN_ERR(svn_utf_cstring_to_utf8_ex2(&buf_utf8, dest_apr.data, (const char *)0, pool)); *dest = svn_string_create(buf_utf8, pool);#endif return SVN_NO_ERROR;#else return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL, _("Symbolic links are not supported on this " "platform"));#endif}svn_error_t *svn_io_copy_link(const char *src, const char *dst, apr_pool_t *pool){#ifdef HAVE_READLINK svn_string_t *link_dest; const char *dst_tmp; /* Notice what the link is pointing at... */ SVN_ERR(svn_io_read_link(&link_dest, src, pool)); /* Make a tmp-link pointing at the same thing. */ SVN_ERR(svn_io_create_unique_link(&dst_tmp, dst, link_dest->data, ".tmp", pool)); /* Move the tmp-link to link. */ return svn_io_file_rename(dst_tmp, dst, pool);#else return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL, _("Symbolic links are not supported on this " "platform"));#endif}svn_error_t *svn_io_temp_dir(const char **dir, apr_pool_t *pool){ apr_status_t apr_err = apr_temp_dir_get(dir, pool); if (apr_err) return svn_error_wrap_apr(apr_err, _("Can't find a temporary directory")); *dir = svn_path_canonicalize(*dir, pool); return svn_path_cstring_to_utf8(dir, *dir, pool);}/*** Creating, copying and appending files. ***/#ifdef AS400/* CCSID insensitive replacement for apr_file_copy() on OS400. * * (See comments for file_open() for more info on CCSIDs.) * * On OS400 apr_file_copy() attempts to convert the contents of the source * file from its CCSID to the CCSID of the destination file. This may * corrupt the destination file's contents if the files' CCSIDs differ from * each other and/or the system CCSID. * * This new function prevents this by forcing a binary copy. It is * stripped down copy of the private function apr_file_transfer_contents in * srclib/apr/file_io/unix/copy.c of version 2.0.54 of the Apache HTTP * Server (http://httpd.apache.org/) excepting that APR_LARGEFILE is not * used, from_path is always opened with APR_BINARY, and * APR_FILE_SOURCE_PERMS is not supported. */ static apr_status_tos400_file_copy(const char *from_path, const char *to_path, apr_fileperms_t perms, apr_pool_t *pool){ apr_file_t *s, *d; apr_status_t status; /* Open source file. */ status = apr_file_open(&s, from_path, APR_READ | APR_BINARY, APR_OS_DEFAULT, pool); if (status) return status; /* Open dest file. * * apr_file_copy() does not require the destination file to exist and will * overwrite it if it does. Since this is a replacement for * apr_file_copy() we enforce similar behavior. */ status = apr_file_open(&d, to_path, APR_WRITE | APR_CREATE | APR_TRUNCATE | APR_BINARY, perms, pool); if (status) { apr_file_close(s); /* toss any error */ return status; } /* Copy bytes till the cows come home. */ while (1) { char buf[BUFSIZ]; apr_size_t bytes_this_time = sizeof(buf); apr_status_t read_err; apr_status_t write_err; /* Read 'em. */ read_err = apr_file_read(s, buf, &bytes_this_time); if (read_err && !APR_STATUS_IS_EOF(read_err)) { apr_file_close(s); /* toss any error */ apr_file_close(d); /* toss any error */ return read_err; } /* Write 'em. */ write_err = apr_file_write_full(d, buf, bytes_this_time, NULL); if (write_err) { apr_file_close(s); /* toss any error */ apr_file_close(d); /* toss any error */ return write_err; } if (read_err && APR_STATUS_IS_EOF(read_err)) { status = apr_file_close(s); if (status) { apr_file_close(d); /* toss any error */ return status; } /* return the results of this close: an error, or success */ return apr_file_close(d); } } /* NOTREACHED */}#endif /* AS400 */svn_error_t *svn_io_copy_file(const char *src, const char *dst, svn_boolean_t copy_perms, apr_pool_t *pool){ apr_status_t apr_err; const char *src_apr, *dst_tmp_apr; const char *dst_tmp; SVN_ERR(svn_path_cstring_from_utf8(&src_apr, src, pool)); /* For atomicity, we translate to a tmp file and then rename the tmp file over the real destination. */ SVN_ERR(svn_io_open_unique_file2(NULL, &dst_tmp, dst, ".tmp", svn_io_file_del_none, pool)); SVN_ERR(svn_path_cstring_from_utf8(&dst_tmp_apr, dst_tmp, pool));#ifndef AS400 apr_err = apr_file_copy(src_apr, dst_tmp_apr, APR_OS_DEFAULT, pool);#else apr_err = os400_file_copy(src_apr, dst_tmp_apr, APR_OS_DEFAULT, pool);#endif if (apr_err) { apr_file_remove(dst_tmp_apr, pool); return svn_error_wrap_apr (apr_err, _("Can't copy '%s' to '%s'"), svn_path_local_style(src, pool), svn_path_local_style(dst_tmp, pool)); } /* If copying perms, set the perms on dst_tmp now, so they will be atomically inherited in the upcoming rename. But note that we had to wait until now to set perms, because if they say read-only, then we'd have failed filling dst_tmp's contents. */ /* ### FIXME: apr_file_copy with perms may fail on Win32. We need a platform-specific implementation to get the permissions right. */#ifndef WIN32 if (copy_perms) { apr_file_t *s; apr_finfo_t finfo; SVN_ERR(svn_io_file_open(&s, src, APR_READ, APR_OS_DEFAULT, pool)); SVN_ERR(svn_io_file_info_get(&finfo, APR_FINFO_PROT, s, pool)); SVN_ERR(svn_io_file_close(s, pool)); apr_err = apr_file_perms_set(dst_tmp_apr, finfo.protection); /* We shouldn't be able to get APR_INCOMPLETE or APR_ENOTIMPL here under normal circumstances, because the perms themselves came from a call to apr_file_info_get(), and we already know this is the non-Win32 case. But if it does happen, it's not an error. */ if ((apr_err != APR_SUCCESS) && (apr_err != APR_INCOMPLETE) && (apr_err != APR_ENOTIMPL)) { return svn_error_wrap_apr (apr_err, _("Can't set permissions on '%s'"), svn_path_local_style(dst_tmp, pool)); } }#endif /* ! WIN32 */ return svn_io_file_rename(dst_tmp, dst, pool);}svn_error_t *svn_io_append_file(const char *src, const char *dst, apr_pool_t *pool){ apr_status_t apr_err; const char *src_apr, *dst_apr; SVN_ERR(svn_path_cstring_from_utf8(&src_apr, src, pool)); SVN_ERR(svn_path_cstring_from_utf8(&dst_apr, dst, pool)); apr_err = apr_file_append(src_apr, dst_apr, APR_OS_DEFAULT, pool); if (apr_err) return svn_error_wrap_apr(apr_err, _("Can't append '%s' to '%s'"), svn_path_local_style(src, pool), svn_path_local_style(dst, pool));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -