Merge #10589 'os/fs: introduce os_fopen()'

This commit is contained in:
Justin M. Keyes 2019-07-26 11:18:19 +02:00 committed by GitHub
commit b42bfa599b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 134 additions and 54 deletions

View File

@ -951,7 +951,7 @@ static int check_external_diff(diffio_T *diffio)
TriState ok = kFalse;
for (;;) {
ok = kFalse;
FILE *fd = mch_fopen((char *)diffio->dio_orig.din_fname, "w");
FILE *fd = os_fopen((char *)diffio->dio_orig.din_fname, "w");
if (fd == NULL) {
io_error = true;
@ -960,7 +960,7 @@ static int check_external_diff(diffio_T *diffio)
io_error = true;
}
fclose(fd);
fd = mch_fopen((char *)diffio->dio_new.din_fname, "w");
fd = os_fopen((char *)diffio->dio_new.din_fname, "w");
if (fd == NULL) {
io_error = true;
@ -971,7 +971,7 @@ static int check_external_diff(diffio_T *diffio)
fclose(fd);
fd = NULL;
if (diff_file(diffio) == OK) {
fd = mch_fopen((char *)diffio->dio_diff.dout_fname, "r");
fd = os_fopen((char *)diffio->dio_diff.dout_fname, "r");
}
if (fd == NULL) {
@ -1505,7 +1505,7 @@ static void diff_read(int idx_orig, int idx_new, diffout_T *dout)
if (dout->dout_fname == NULL) {
diffstyle = DIFF_UNIFIED;
} else {
fd = mch_fopen((char *)dout->dout_fname, "r");
fd = os_fopen((char *)dout->dout_fname, "r");
if (fd == NULL) {
EMSG(_("E98: Cannot read diff output"));
return;

View File

@ -2844,7 +2844,7 @@ static void ins_compl_files(int count, char_u **files, int thesaurus, int flags,
int add_r;
for (i = 0; i < count && !got_int && !compl_interrupted; i++) {
fp = mch_fopen((char *)files[i], "r"); /* open dictionary file */
fp = os_fopen((char *)files[i], "r"); // open dictionary file
if (flags != DICT_EXACT) {
vim_snprintf((char *)IObuff, IOSIZE,
_("Scanning dictionary: %s"), (char *)files[i]);

View File

@ -13616,7 +13616,7 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr)
// Always open the file in binary mode, library functions have a mind of
// their own about CR-LF conversion.
const char *const fname = tv_get_string(&argvars[0]);
if (*fname == NUL || (fd = mch_fopen(fname, READBIN)) == NULL) {
if (*fname == NUL || (fd = os_fopen(fname, READBIN)) == NULL) {
EMSG2(_(e_notopen), *fname == NUL ? _("<empty>") : fname);
return;
}

View File

@ -4557,7 +4557,7 @@ void ex_help(exarg_T *eap)
} else {
// There is no help window yet.
// Try to open the file specified by the "helpfile" option.
if ((helpfd = mch_fopen((char *)p_hf, READBIN)) == NULL) {
if ((helpfd = os_fopen((char *)p_hf, READBIN)) == NULL) {
smsg(_("Sorry, help file \"%s\" not found"), p_hf);
goto erret;
}
@ -5087,7 +5087,7 @@ void fix_help_buffer(void)
continue;
}
FILE *const fd = mch_fopen((char *)fnames[fi], "r");
FILE *const fd = os_fopen((char *)fnames[fi], "r");
if (fd == NULL) {
continue;
}
@ -5223,7 +5223,7 @@ static void helptags_one(char_u *const dir, const char_u *const ext,
return;
}
FILE *const fd_tags = mch_fopen((char *)NameBuff, "w");
FILE *const fd_tags = os_fopen((char *)NameBuff, "w");
if (fd_tags == NULL) {
EMSG2(_("E152: Cannot open %s for writing"), NameBuff);
FreeWild(filecount, files);
@ -5247,7 +5247,7 @@ static void helptags_one(char_u *const dir, const char_u *const ext,
* Go over all the files and extract the tags.
*/
for (int fi = 0; fi < filecount && !got_int; fi++) {
FILE *const fd = mch_fopen((char *)files[fi], "r");
FILE *const fd = os_fopen((char *)files[fi], "r");
if (fd == NULL) {
EMSG2(_("E153: Unable to open %s for reading"), files[fi]);
continue;

View File

@ -990,7 +990,7 @@ void profile_dump(void)
FILE *fd;
if (profile_fname != NULL) {
fd = mch_fopen((char *)profile_fname, "w");
fd = os_fopen((char *)profile_fname, "w");
if (fd == NULL) {
EMSG2(_(e_notopen), profile_fname);
} else {
@ -1139,7 +1139,7 @@ static void script_dump_profile(FILE *fd)
fprintf(fd, "\n");
fprintf(fd, "count total (s) self (s)\n");
sfd = mch_fopen((char *)si->sn_name, "r");
sfd = os_fopen((char *)si->sn_name, "r");
if (sfd == NULL) {
fprintf(fd, "Cannot open file!\n");
} else {
@ -2858,7 +2858,7 @@ static int requires_py_version(char_u *filename)
lines = 5;
}
file = mch_fopen((char *)filename, "r");
file = os_fopen((char *)filename, "r");
if (file != NULL) {
for (i = 0; i < lines; i++) {
if (vim_fgets(IObuff, IOSIZE, file)) {

View File

@ -8106,8 +8106,9 @@ open_exfile (
return NULL;
}
if ((fd = mch_fopen((char *)fname, mode)) == NULL)
if ((fd = os_fopen((char *)fname, mode)) == NULL) {
EMSG2(_("E190: Cannot open \"%s\" for writing"), fname);
}
return fd;
}

View File

@ -1670,7 +1670,7 @@ static int prt_open_resource(struct prt_ps_resource_S *resource)
FILE *fd_resource;
struct prt_dsc_line_S dsc_line;
fd_resource = mch_fopen((char *)resource->filename, READBIN);
fd_resource = os_fopen((char *)resource->filename, READBIN);
if (fd_resource == NULL) {
EMSG2(_("E624: Can't open file \"%s\""), resource->filename);
return FALSE;
@ -2343,11 +2343,11 @@ int mch_print_init(prt_settings_T *psettings, char_u *jobname, int forceit)
EMSG(_(e_notmp));
return FAIL;
}
prt_ps_fd = mch_fopen((char *)prt_ps_file_name, WRITEBIN);
prt_ps_fd = os_fopen((char *)prt_ps_file_name, WRITEBIN);
} else {
p = expand_env_save(psettings->outfile);
if (p != NULL) {
prt_ps_fd = mch_fopen((char *)p, WRITEBIN);
prt_ps_fd = os_fopen((char *)p, WRITEBIN);
xfree(p);
}
}
@ -2382,7 +2382,7 @@ static int prt_add_resource(struct prt_ps_resource_S *resource)
char_u resource_buffer[512];
size_t bytes_read;
fd_resource = mch_fopen((char *)resource->filename, READBIN);
fd_resource = os_fopen((char *)resource->filename, READBIN);
if (fd_resource == NULL) {
EMSG2(_("E456: Can't open file \"%s\""), resource->filename);
return FALSE;

View File

@ -1008,10 +1008,10 @@ static int cs_find_common(char *opt, char *pat, int forceit, int verbose,
qf_info_T *qi = NULL;
win_T *wp = NULL;
f = mch_fopen((char *)tmp, "w");
if (f == NULL)
f = os_fopen((char *)tmp, "w");
if (f == NULL) {
EMSG2(_(e_notopen), tmp);
else {
} else {
cs_file_results(f, nummatches);
fclose(f);
if (use_ll) /* Use location list */

View File

@ -86,8 +86,6 @@
#define READBIN "rb"
#define APPENDBIN "ab"
# define mch_fopen(n, p) fopen((n), (p))
/* mch_open_rw(): invoke os_open() with third argument for user R/W. */
#if defined(UNIX) /* open in rw------- mode */
# define mch_open_rw(n, f) os_open((n), (f), (mode_t)0600)

View File

@ -1174,8 +1174,8 @@ scripterror:
if (scriptout != NULL) {
goto scripterror;
}
if ((scriptout = mch_fopen(argv[0],
c == 'w' ? APPENDBIN : WRITEBIN)) == NULL) {
if ((scriptout = os_fopen(argv[0], c == 'w' ? APPENDBIN : WRITEBIN))
== NULL) {
mch_errmsg(_("Cannot open for script output: \""));
mch_errmsg(argv[0]);
mch_errmsg("\"\n");
@ -1263,8 +1263,9 @@ static void init_params(mparm_T *paramp, int argc, char **argv)
static void init_startuptime(mparm_T *paramp)
{
for (int i = 1; i < paramp->argc; i++) {
if (STRICMP(paramp->argv[i], "--startuptime") == 0 && i + 1 < paramp->argc) {
time_fd = mch_fopen(paramp->argv[i + 1], "a");
if (STRICMP(paramp->argv[i], "--startuptime") == 0
&& i + 1 < paramp->argc) {
time_fd = os_fopen(paramp->argv[i + 1], "a");
time_start("--- NVIM STARTING ---");
break;
}

View File

@ -2992,7 +2992,7 @@ int verbose_open(void)
/* Only give the error message once. */
verbose_did_open = TRUE;
verbose_fd = mch_fopen((char *)p_vfile, "a");
verbose_fd = os_fopen((char *)p_vfile, "a");
if (verbose_fd == NULL) {
EMSG2(_(e_notopen), p_vfile);
return FAIL;

View File

@ -2836,7 +2836,7 @@ char_u *get_cmd_output(char_u *cmd, char_u *infile, ShellOpts flags,
xfree(command);
// read the names from the file into memory
FILE *fd = mch_fopen((char *)tempname, READBIN);
FILE *fd = os_fopen((char *)tempname, READBIN);
if (fd == NULL) {
EMSG2(_(e_notopen), tempname);

View File

@ -404,10 +404,11 @@ end:
/// calls (read, write, lseek, fcntl, etc.). If the operation fails, a libuv
/// error code is returned, and no file is created or modified.
///
/// @param path Filename
/// @param flags Bitwise OR of flags defined in <fcntl.h>
/// @param mode Permissions for the newly-created file (IGNORED if 'flags' is
/// not `O_CREAT` or `O_TMPFILE`), subject to the current umask
/// @return file descriptor, or libuv error code on failure
/// @return file descriptor, or negative error code on failure
int os_open(const char *path, int flags, int mode)
{
if (path == NULL) { // uv_fs_open asserts on NULL. #7561
@ -418,6 +419,68 @@ int os_open(const char *path, int flags, int mode)
return r;
}
/// Compatibility wrapper conforming to fopen(3).
///
/// Windows: works with UTF-16 filepaths by delegating to libuv (os_open).
///
/// Future: remove this, migrate callers to os/fileio.c ?
/// But file_open_fd does not support O_RDWR yet.
///
/// @param path Filename
/// @param flags String flags, one of { r w a r+ w+ a+ rb wb ab }
/// @return FILE pointer, or NULL on error.
FILE *os_fopen(const char *path, const char *flags)
{
assert(flags != NULL && strlen(flags) > 0 && strlen(flags) <= 2);
int iflags = 0;
// Per table in fopen(3) manpage.
if (flags[1] == '\0' || flags[1] == 'b') {
switch (flags[0]) {
case 'r':
iflags = O_RDONLY;
break;
case 'w':
iflags = O_WRONLY | O_CREAT | O_TRUNC;
break;
case 'a':
iflags = O_WRONLY | O_CREAT | O_APPEND;
break;
default:
abort();
}
#ifdef WIN32
if (flags[1] == 'b') {
iflags |= O_BINARY;
}
#endif
} else {
// char 0 must be one of ('r','w','a').
// char 1 is always '+' ('b' is handled above).
assert(flags[1] == '+');
switch (flags[0]) {
case 'r':
iflags = O_RDWR;
break;
case 'w':
iflags = O_RDWR | O_CREAT | O_TRUNC;
break;
case 'a':
iflags = O_RDWR | O_CREAT | O_APPEND;
break;
default:
abort();
}
}
// Per open(2) manpage.
assert((iflags|O_RDONLY) || (iflags|O_WRONLY) || (iflags|O_RDWR));
// Per fopen(3) manpage: default to 0666, it will be umask-adjusted.
int fd = os_open(path, iflags, 0666);
if (fd < 0) {
return NULL;
}
return fdopen(fd, flags);
}
/// Sets file descriptor `fd` to close-on-exec.
//
// @return -1 if failed to set, 0 otherwise.
@ -829,12 +892,12 @@ int os_mkdir_recurse(const char *const dir, int32_t mode,
// We're done when it's "/" or "c:/".
const size_t dirlen = strlen(dir);
char *const curdir = xmemdupz(dir, dirlen);
char *const past_head = (char *) get_past_head((char_u *) curdir);
char *const past_head = (char *)get_past_head((char_u *)curdir);
char *e = curdir + dirlen;
const char *const real_end = e;
const char past_head_save = *past_head;
while (!os_isdir((char_u *) curdir)) {
e = (char *) path_tail_with_sep((char_u *) curdir);
while (!os_isdir((char_u *)curdir)) {
e = (char *)path_tail_with_sep((char_u *)curdir);
if (e <= past_head) {
*past_head = NUL;
break;
@ -986,7 +1049,7 @@ bool os_fileinfo_fd(int file_descriptor, FileInfo *file_info)
///
/// @return `true` if the two FileInfos represent the same file.
bool os_fileinfo_id_equal(const FileInfo *file_info_1,
const FileInfo *file_info_2)
const FileInfo *file_info_2)
FUNC_ATTR_NONNULL_ALL
{
return file_info_1->stat.st_ino == file_info_2->stat.st_ino

View File

@ -863,7 +863,7 @@ qf_init_ext(
fields.errmsg = xmalloc(fields.errmsglen);
fields.pattern = xmalloc(CMDBUFFSIZE + 1);
if (efile != NULL && (state.fd = mch_fopen((char *)efile, "r")) == NULL) {
if (efile != NULL && (state.fd = os_fopen((char *)efile, "r")) == NULL) {
EMSG2(_(e_openerrf), efile);
goto qf_init_end;
}
@ -5495,7 +5495,7 @@ void ex_helpgrep(exarg_T *eap)
+ STRLEN(fnames[fi]) - 3, 3) == 0)) {
continue;
}
fd = mch_fopen((char *)fnames[fi], "r");
fd = os_fopen((char *)fnames[fi], "r");
if (fd != NULL) {
lnum = 1;
while (!vim_fgets(IObuff, IOSIZE, fd) && !got_int) {

View File

@ -4575,10 +4575,9 @@ find_pattern_in_path(
xfree(files);
files = bigger;
}
if ((files[depth + 1].fp = mch_fopen((char *)new_fname, "r"))
== NULL)
if ((files[depth + 1].fp = os_fopen((char *)new_fname, "r")) == NULL) {
xfree(new_fname);
else {
} else {
if (++depth == old_files) {
// Something wrong. We will forget one of our already visited files
// now.

View File

@ -3262,7 +3262,7 @@ static void spell_suggest_file(suginfo_T *su, char_u *fname)
char_u cword[MAXWLEN];
// Open the file.
fd = mch_fopen((char *)fname, "r");
fd = os_fopen((char *)fname, "r");
if (fd == NULL) {
EMSG2(_(e_notopen), fname);
return;

View File

@ -586,7 +586,7 @@ spell_load_file (
int c = 0;
int res;
fd = mch_fopen((char *)fname, "r");
fd = os_fopen((char *)fname, "r");
if (fd == NULL) {
if (!silent)
EMSG2(_(e_notopen), fname);
@ -885,9 +885,10 @@ void suggest_load_files(void)
continue;
}
STRCPY(dotp, ".sug");
fd = mch_fopen((char *)slang->sl_fname, "r");
if (fd == NULL)
fd = os_fopen((char *)slang->sl_fname, "r");
if (fd == NULL) {
goto nextone;
}
// <SUGHEADER>: <fileID> <versionnr> <timestamp>
for (i = 0; i < VIMSUGMAGICL; ++i)
@ -1984,7 +1985,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
char_u *sofoto = NULL; // SOFOTO value
// Open the file.
fd = mch_fopen((char *)fname, "r");
fd = os_fopen((char *)fname, "r");
if (fd == NULL) {
EMSG2(_(e_notopen), fname);
return NULL;
@ -3019,7 +3020,7 @@ static int spell_read_dic(spellinfo_T *spin, char_u *fname, afffile_T *affile)
int duplicate = 0;
// Open the file.
fd = mch_fopen((char *)fname, "r");
fd = os_fopen((char *)fname, "r");
if (fd == NULL) {
EMSG2(_(e_notopen), fname);
return FAIL;
@ -3539,7 +3540,7 @@ static int spell_read_wordfile(spellinfo_T *spin, char_u *fname)
int regionmask;
// Open the file.
fd = mch_fopen((char *)fname, "r");
fd = os_fopen((char *)fname, "r");
if (fd == NULL) {
EMSG2(_(e_notopen), fname);
return FAIL;
@ -4185,7 +4186,7 @@ static int write_vim_spell(spellinfo_T *spin, char_u *fname)
int retval = OK;
int regionmask;
FILE *fd = mch_fopen((char *)fname, "w");
FILE *fd = os_fopen((char *)fname, "w");
if (fd == NULL) {
EMSG2(_(e_notopen), fname);
return FAIL;
@ -4986,7 +4987,7 @@ static int offset2bytes(int nr, char_u *buf)
static void sug_write(spellinfo_T *spin, char_u *fname)
{
// Create the file. Note that an existing file is silently overwritten!
FILE *fd = mch_fopen((char *)fname, "w");
FILE *fd = os_fopen((char *)fname, "w");
if (fd == NULL) {
EMSG2(_(e_notopen), fname);
return;
@ -5365,7 +5366,7 @@ spell_add_word (
if (bad || undo) {
// When the word appears as good word we need to remove that one,
// since its flags sort before the one with WF_BANNED.
fd = mch_fopen((char *)fname, "r");
fd = os_fopen((char *)fname, "r");
if (fd != NULL) {
while (!vim_fgets(line, MAXWLEN * 2, fd)) {
fpos = fpos_next;
@ -5376,7 +5377,7 @@ spell_add_word (
// the start of the line. Mixing reading and writing
// doesn't work for all systems, close the file first.
fclose(fd);
fd = mch_fopen((char *)fname, "r+");
fd = os_fopen((char *)fname, "r+");
if (fd == NULL) {
break;
}
@ -5399,7 +5400,7 @@ spell_add_word (
}
if (!undo) {
fd = mch_fopen((char *)fname, "a");
fd = os_fopen((char *)fname, "a");
if (fd == NULL && new_spf) {
char_u *p;
@ -5415,7 +5416,7 @@ spell_add_word (
*p = NUL;
os_mkdir((char *)fname, 0755);
*p = c;
fd = mch_fopen((char *)fname, "a");
fd = os_fopen((char *)fname, "a");
}
}

View File

@ -1303,8 +1303,9 @@ find_tags (
}
}
if ((fp = mch_fopen((char *)tag_fname, "r")) == NULL)
if ((fp = os_fopen((char *)tag_fname, "r")) == NULL) {
continue;
}
if (p_verbose >= 5) {
verbose_enter();

View File

@ -1299,7 +1299,7 @@ void u_read_undo(char *name, char_u *hash, char_u *orig_name)
verbose_leave();
}
FILE *fp = mch_fopen(file_name, "r");
FILE *fp = os_fopen(file_name, "r");
if (fp == NULL) {
if (name != NULL || p_verbose > 0) {
EMSG2(_("E822: Cannot open undo file for reading: %s"), file_name);

View File

@ -22,6 +22,7 @@ describe('fileio', function()
os.remove('Xtest_startup_file1')
os.remove('Xtest_startup_file1~')
os.remove('Xtest_startup_file2')
os.remove('Xtest_тест.md')
rmdir('Xtest_startup_swapdir')
end)
@ -85,7 +86,22 @@ describe('fileio', function()
eq('foobar', foobar_contents);
eq('foo', bar_contents);
end)
it('readfile() on multibyte filename #10586', function()
clear()
local text = {
'line1',
' ...line2... ',
'',
'line3!',
'тест yay тест.',
'',
}
local fname = 'Xtest_тест.md'
funcs.writefile(text, fname, 's')
table.insert(text, '')
eq(text, funcs.readfile(fname, 'b'))
end)
end)