/* vi:set ts=8 sts=4 sw=4: * * VIM - Vi IMproved by Bram Moolenaar * * Do ":help uganda" in Vim to read copying and usage conditions. * Do ":help credits" in Vim to see a list of people who contributed. * See README.txt for an overview of the Vim source code. */ /* * fileio.c: read from and write to a file */ #if defined(MSDOS) || defined(WIN16) || defined(WIN32) || defined(_WIN64)# include "vimio.h" /* for lseek(), must be before vim.h */#endif #if defined __EMX__# include "vimio.h" /* for mktemp(), CJW 1997-12-03 */#endif #include "vim.h" #ifdef HAVE_FCNTL_H# include <fcntl.h>#endif #ifdef __TANDEM# include <limits.h> /* for SSIZE_MAX */#endif #if defined(HAVE_UTIME) && defined(HAVE_UTIME_H)# include <utime.h> /* for struct utimbuf */#endif #define BUFSIZE 8192 /* size of normal write buffer */#define SMBUFSIZE 256 /* size of emergency write buffer */ #ifdef FEAT_CRYPT# define CRYPT_MAGIC "VimCrypt~01!" /* "01" is the version nr */# define CRYPT_MAGIC_LEN 12 /* must be multiple of 4! */#endif /* Is there any system that doesn't have access()? */#define USE_MCH_ACCESS #ifdef FEAT_MBYTEstatic char_u *next_fenc __ARGS((char_u **pp));# ifdef FEAT_EVALstatic char_u *readfile_charconvert __ARGS((char_u *fname, char_u *fenc, int *fdp));# endif#endif#ifdef FEAT_VIMINFOstatic void check_marks_read __ARGS((void));#endif#ifdef FEAT_CRYPTstatic char_u *check_for_cryptkey __ARGS((char_u *cryptkey, char_u *ptr, long *sizep, long *filesizep, int newfile));#endif#ifdef UNIXstatic void set_file_time __ARGS((char_u *fname, time_t atime, time_t mtime));#endifstatic int set_rw_fname __ARGS((char_u *fname, char_u *sfname));static int msg_add_fileformat __ARGS((int eol_type));static void msg_add_eol __ARGS((void));static int check_mtime __ARGS((buf_T *buf, struct stat *s));static int time_differs __ARGS((long t1, long t2));#ifdef FEAT_AUTOCMDstatic int apply_autocmds_exarg __ARGS((event_T event, char_u *fname, char_u *fname_io, int force, buf_T *buf, exarg_T *eap));static int au_find_group __ARGS((char_u *name)); # define AUGROUP_DEFAULT -1 /* default autocmd group */# define AUGROUP_ERROR -2 /* errornouse autocmd group */# define AUGROUP_ALL -3 /* all autocmd groups */#endif #if defined(FEAT_CRYPT) || defined(FEAT_MBYTE)# define HAS_BW_FLAGS# define FIO_LATIN1 0x01 /* convert Latin1 */# define FIO_UTF8 0x02 /* convert UTF-8 */# define FIO_UCS2 0x04 /* convert UCS-2 */# define FIO_UCS4 0x08 /* convert UCS-4 */# define FIO_UTF16 0x10 /* convert UTF-16 */# ifdef WIN3264# define FIO_CODEPAGE 0x20 /* convert MS-Windows codepage */# define FIO_PUT_CP(x) (((x) & 0xffff) << 16) /* put codepage in top word */# define FIO_GET_CP(x) (((x)>>16) & 0xffff) /* get codepage from top word */# endif# ifdef MACOS_X# define FIO_MACROMAN 0x20 /* convert MacRoman */# endif# define FIO_ENDIAN_L 0x80 /* little endian */# define FIO_ENCRYPTED 0x1000 /* encrypt written bytes */# define FIO_NOCONVERT 0x2000 /* skip encoding conversion */# define FIO_UCSBOM 0x4000 /* check for BOM at start of file */# define FIO_ALL -1 /* allow all formats */#endif /* When converting, a read() or write() may leave some bytes to be converted * for the next call. The value is guessed... */#define CONV_RESTLEN 30 /* We have to guess how much a sequence of bytes may expand when converting * with iconv() to be able to allocate a buffer. */#define ICONV_MULT 8 /* * Structure to pass arguments from buf_write() to buf_write_bytes(). */struct bw_info{ int bw_fd; /* file descriptor */ char_u *bw_buf; /* buffer with data to be written */ int bw_len; /* lenght of data */#ifdef HAS_BW_FLAGS int bw_flags; /* FIO_ flags */#endif#ifdef FEAT_MBYTE char_u bw_rest[CONV_RESTLEN]; /* not converted bytes */ int bw_restlen; /* nr of bytes in bw_rest[] */ int bw_first; /* first write call */ char_u *bw_conv_buf; /* buffer for writing converted chars */ int bw_conv_buflen; /* size of bw_conv_buf */ int bw_conv_error; /* set for conversion error */# ifdef USE_ICONV iconv_t bw_iconv_fd; /* descriptor for iconv() or -1 */# endif#endif}; static int buf_write_bytes __ARGS((struct bw_info *ip)); #ifdef FEAT_MBYTEstatic linenr_T readfile_linenr __ARGS((linenr_T linecnt, char_u *p, char_u *endp));static int ucs2bytes __ARGS((unsigned c, char_u **pp, int flags));static int same_encoding __ARGS((char_u *a, char_u *b));static int get_fio_flags __ARGS((char_u *ptr));static char_u *check_for_bom __ARGS((char_u *p, long size, int *lenp, int flags));static int make_bom __ARGS((char_u *buf, char_u *name));# ifdef WIN3264static int get_win_fio_flags __ARGS((char_u *ptr));# endif# ifdef MACOS_Xstatic int get_mac_fio_flags __ARGS((char_u *ptr));# endif#endifstatic int move_lines __ARGS((buf_T *frombuf, buf_T *tobuf)); voidfilemess(buf, name, s, attr) buf_T *buf; char_u *name; char_u *s; int attr;{ int msg_scroll_save; if (msg_silent != 0) return; msg_add_fname(buf, name); /* put file name in IObuff with quotes */ /* If it's extremely long, truncate it. */ if (STRLEN(IObuff) > IOSIZE - 80) IObuff[IOSIZE - 80] = NUL; STRCAT(IObuff, s); /* * For the first message may have to start a new line. * For further ones overwrite the previous one, reset msg_scroll before * calling filemess(). */ msg_scroll_save = msg_scroll; if (shortmess(SHM_OVERALL) && !exiting && p_verbose == 0) msg_scroll = FALSE; if (!msg_scroll) /* wait a bit when overwriting an error msg */ check_for_delay(FALSE); msg_start(); msg_scroll = msg_scroll_save; msg_scrolled_ign = TRUE; /* may truncate the message to avoid a hit-return prompt */ msg_outtrans_attr(msg_may_trunc(FALSE, IObuff), attr); msg_clr_eos(); out_flush(); msg_scrolled_ign = FALSE;} /* * Read lines from file "fname" into the buffer after line "from". * * 1. We allocate blocks with lalloc, as big as possible. * 2. Each block is filled with characters from the file with a single read(). * 3. The lines are inserted in the buffer with ml_append(). * * (caller must check that fname != NULL, unless READ_STDIN is used) * * "lines_to_skip" is the number of lines that must be skipped * "lines_to_read" is the number of lines that are appended * When not recovering lines_to_skip is 0 and lines_to_read MAXLNUM. * * flags: * READ_NEW starting to edit a new buffer * READ_FILTER reading filter output * READ_STDIN read from stdin instead of a file * READ_BUFFER read from curbuf instead of a file (converting after reading * stdin) * READ_DUMMY read into a dummy buffer (to check if file contents changed) * * return FAIL for failure, OK otherwise */ intreadfile(fname, sfname, from, lines_to_skip, lines_to_read, eap, flags) char_u *fname; char_u *sfname; linenr_T from; linenr_T lines_to_skip; linenr_T lines_to_read; exarg_T *eap; /* can be NULL! */ int flags;{ int fd = 0; int newfile = (flags & READ_NEW); int set_options = newfile || (eap != NULL && eap->read_edit); int check_readonly; int filtering = (flags & READ_FILTER); int read_stdin = (flags & READ_STDIN); int read_buffer = (flags & READ_BUFFER); linenr_T read_buf_lnum = 1; /* next line to read from curbuf */ colnr_T read_buf_col = 0; /* next char to read from this line */ char_u c; linenr_T lnum = from; char_u *ptr = NULL; /* pointer into read buffer */ char_u *buffer = NULL; /* read buffer */ char_u *new_buffer = NULL; /* init to shut up gcc */ char_u *line_start = NULL; /* init to shut up gcc */ int wasempty; /* buffer was empty before reading */ colnr_T len; long size = 0; char_u *p; long filesize = 0; int skip_read = FALSE;#ifdef FEAT_CRYPT char_u *cryptkey = NULL;#endif int split = 0; /* number of split lines */#define UNKNOWN 0x0fffffff /* file size is unknown */ linenr_T linecnt; int error = FALSE; /* errors encountered */ int ff_error = EOL_UNKNOWN; /* file format with errors */ long linerest = 0; /* remaining chars in line */#ifdef UNIX int perm = 0; int swap_mode = -1; /* protection bits for swap file */#else int perm;#endif int fileformat = 0; /* end-of-line format */ int keep_fileformat = FALSE; struct stat st; int file_readonly; linenr_T skip_count = 0; linenr_T read_count = 0; int msg_save = msg_scroll; linenr_T read_no_eol_lnum = 0; /* non-zero lnum when last line of * last read was missing the eol */ int try_mac = (vim_strchr(p_ffs, 'm') != NULL); int try_dos = (vim_strchr(p_ffs, 'd') != NULL); int try_unix = (vim_strchr(p_ffs, 'x') != NULL); int file_rewind = FALSE;#ifdef FEAT_MBYTE int can_retry; linenr_T conv_error = 0; /* line nr with conversion error */ linenr_T illegal_byte = 0; /* line nr with illegal byte */ int keep_dest_enc = FALSE; /* don't retry when char doesn't fit in destination encoding */ int bad_char_behavior = BAD_REPLACE; /* BAD_KEEP, BAD_DROP or character to * replace with */ char_u *tmpname = NULL; /* name of 'charconvert' output file */ int fio_flags = 0; char_u *fenc; /* fileencoding to use */ int fenc_alloced; /* fenc_next is in allocated memory */ char_u *fenc_next = NULL; /* next item in 'fencs' or NULL */ int advance_fenc = FALSE; long real_size = 0;# ifdef USE_ICONV iconv_t iconv_fd = (iconv_t)-1; /* descriptor for iconv() or -1 */# ifdef FEAT_EVAL int did_iconv = FALSE; /* TRUE when iconv() failed and trying 'charconvert' next */# endif# endif int converted = FALSE; /* TRUE if conversion done */ int notconverted = FALSE; /* TRUE if conversion wanted but it wasn't possible */ char_u conv_rest[CONV_RESTLEN]; int conv_restlen = 0; /* nr of bytes in conv_rest[] */#endif write_no_eol_lnum = 0; /* in case it was set by the previous read */ /* * If there is no file name yet, use the one for the read file. * BF_NOTEDITED is set to reflect this. * Don't do this for a read from a filter. * Only do this when 'cpoptions' contains the 'f' flag. */ if (curbuf->b_ffname == NULL && !filtering && fname != NULL && vim_strchr(p_cpo, CPO_FNAMER) != NULL && !(flags & READ_DUMMY)) { if (set_rw_fname(fname, sfname) == FAIL) return FAIL; } /* After reading a file the cursor line changes but we don't want to * display the line. */ ex_no_reprint = TRUE; /* don't display the file info for another buffer now */ need_fileinfo = FALSE; /* * For Unix: Use the short file name whenever possible. * Avoids problems with networks and when directory names are changed. * Don't do this for MS-DOS, a "cd" in a sub-shell may have moved us to * another directory, which we don't detect. */ if (sfname == NULL) sfname = fname;#if defined(UNIX) || defined(__EMX__) fname = sfname;#endif #ifdef FEAT_AUTOCMD /* * The BufReadCmd and FileReadCmd events intercept the reading process by * executing the associated commands instead. */ if (!filtering && !read_stdin && !read_buffer) { pos_T pos; pos = curbuf->b_op_start; /* Set '[ mark to the line above where the lines go (line 1 if zero). */ curbuf->b_op_start.lnum = ((from == 0) ? 1 : from); curbuf->b_op_start.col = 0; if (newfile) { if (apply_autocmds_exarg(EVENT_BUFREADCMD, NULL, sfname, FALSE, curbuf, eap))#ifdef FEAT_EVAL return aborting() ? FAIL : OK;#else return OK;#endif } else if (apply_autocmds_exarg(EVENT_FILEREADCMD, sfname, sfname, FALSE, NULL, eap))#ifdef FEAT_EVAL return aborting() ? FAIL : OK;#else return OK;#endif curbuf->b_op_start = pos; }#endif if ((shortmess(SHM_OVER) || curbuf->b_help) && p_verbose == 0) msg_scroll = FALSE; /* overwrite previous file message */ else msg_scroll = TRUE; /* don't overwrite previous file message */ /* * If the name ends in a path separator, we can't open it. Check here, * because reading the file may actually work, but then creating the swap * file may destroy it! Reported on MS-DOS and Win 95. * If the name is too long we might crash further on, quit here. */ if (fname != NULL && *fname != NUL) { p = fname + STRLEN(fname); if (after_pathsep(fname, p) || STRLEN(fname) >= MAXPATHL) { filemess(curbuf, fname, (char_u *)_("Illegal file name"), 0); msg_end(); msg_scroll = msg_save; return FAIL; } } #ifdef UNIX /* * On Unix it is possible to read a directory, so we have to * check for it before the mch_open(). */ if (!read_stdin && !read_buffer) { perm = mch_getperm(fname); if (perm >= 0 && !S_ISREG(perm) /* not a regular file ... */# ifdef S_ISFIFO && !S_ISFIFO(perm) /* ... or fifo */# endif# ifdef S_ISSOCK && !S_ISSOCK(perm) /* ... or socket */# endif ) { if (S_ISDIR(perm)) filemess(curbuf, fname, (char_u *)_("is a directory"), 0); else filemess(curbuf, fname, (char_u *)_("is not a file"), 0); msg_end(); msg_scroll = msg_save; return FAIL; } # if defined(MSDOS) || defined(MSWIN) || defined(OS2) /* * MS-Windows allows opening a device, but we will probably get stuck * trying to read it. */ if (!p_odev && mch_nodetype(fname) == NODE_WRITABLE) { filemess(curbuf, fname, (char_u *)_("is a device (disabled with 'opendevice' option"), 0); msg_end(); msg_scroll = msg_save; return FAIL; }# endif }#endif /* set default 'fileformat' */ if (set_options) { if (eap != NULL && eap->force_ff != 0) set_fileformat(get_fileformat_force(curbuf, eap), OPT_LOCAL); else if (*p_ffs != NUL) set_fileformat(default_fileformat(), OPT_LOCAL); } /* set or reset 'binary' */ if (eap != NULL && eap->force_bin != 0) { int oldval = curbuf->b_p_bin; curbuf->b_p_bin = (eap->force_bin == FORCE_BIN); set_options_bin(oldval, curbuf->b_p_bin, OPT_LOCAL); } /* * When opening a new file we take the readonly flag from the file. * Default is r/w, can be set to r/o below. * Don't reset it when in readonly mode * Only set/reset b_p_ro when BF_CHECK_RO is set. */ check_readonly = (newfile && (curbuf->b_flags & BF_CHECK_RO)); if (check_readonly && !readonlymode) curbuf->b_p_ro = FALSE; if (newfile && !read_stdin && !read_buffer) { /* Remember time of file. * For RISCOS, also remember the filetype. */ if (mch_stat((char *)fname, &st) >= 0) { buf_store_time(curbuf, &st, fname); curbuf->b_mtime_read = curbuf->b_mtime; #if defined(RISCOS) && defined(FEAT_OSFILETYPE) /* Read the filetype into the buffer local filetype option. */ mch_read_filetype(fname);#endif#ifdef UNIX /* * Use the protection bits of the original file for the swap file. * This makes it possible for others to read the name of the * edited file from the swapfile, but only if they can read the * edited file. * Remove the "write" and "execute" bits for group and others * (they must not write the swapfile). * Add the "read" and "write" bits for the user, otherwise we may * not be able to write to the file ourselves. * Setting the bits is done below, after creating the swap file. */ swap_mode = (st.st_mode & 0644) | 0600;#endif#ifdef FEAT_CW_EDITOR /* Get the FSSpec on MacOS * TODO: Update it properly when the buffer name changes */ (void)GetFSSpecFromPath(curbuf->b_ffname, &curbuf->b_FSSpec);#endif#ifdef VMS curbuf->b_fab_rfm = st.st_fab_rfm; curbuf->b_fab_rat = st.st_fab_rat;Lines 1–500 of 9519. Load more
/* vi:set ts=8 sts=4 sw=4: * * VIM - Vi IMproved by Bram Moolenaar * * Do ":help uganda" in Vim to read copying and usage conditions. * Do ":help credits" in Vim to see a list of people who contributed. * See README.txt for an overview of the Vim source code. */ /* * fileio.c: read from and write to a file */ #if defined(MSDOS) || defined(WIN16) || defined(WIN32) || defined(_WIN64) # include "vimio.h" /* for lseek(), must be before vim.h */ #endif #if defined __EMX__ # include "vimio.h" /* for mktemp(), CJW 1997-12-03 */ #endif #include "vim.h" #ifdef HAVE_FCNTL_H # include <fcntl.h> #endif #ifdef __TANDEM # include <limits.h> /* for SSIZE_MAX */ #endif #if defined(HAVE_UTIME) && defined(HAVE_UTIME_H) # include <utime.h> /* for struct utimbuf */ #endif #define BUFSIZE 8192 /* size of normal write buffer */ #define SMBUFSIZE 256 /* size of emergency write buffer */ #ifdef FEAT_CRYPT # define CRYPT_MAGIC "VimCrypt~01!" /* "01" is the version nr */ # define CRYPT_MAGIC_LEN 12 /* must be multiple of 4! */ #endif /* Is there any system that doesn't have access()? */ #define USE_MCH_ACCESS #ifdef FEAT_MBYTE static char_u *next_fenc __ARGS((char_u **pp)); # ifdef FEAT_EVAL static char_u *readfile_charconvert __ARGS((char_u *fname, char_u *fenc, int *fdp)); # endif #endif #ifdef FEAT_VIMINFO static void check_marks_read __ARGS((void)); #endif #ifdef FEAT_CRYPT static char_u *check_for_cryptkey __ARGS((char_u *cryptkey, char_u *ptr, long *sizep, long *filesizep, int newfile)); #endif #ifdef UNIX static void set_file_time __ARGS((char_u *fname, time_t atime, time_t mtime)); #endif static int set_rw_fname __ARGS((char_u *fname, char_u *sfname)); static int msg_add_fileformat __ARGS((int eol_type)); static void msg_add_eol __ARGS((void)); static int check_mtime __ARGS((buf_T *buf, struct stat *s)); static int time_differs __ARGS((long t1, long t2)); #ifdef FEAT_AUTOCMD static int apply_autocmds_exarg __ARGS((event_T event, char_u *fname, char_u *fname_io, int force, buf_T *buf, exarg_T *eap)); static int au_find_group __ARGS((char_u *name)); # define AUGROUP_DEFAULT -1 /* default autocmd group */ # define AUGROUP_ERROR -2 /* errornouse autocmd group */ # define AUGROUP_ALL -3 /* all autocmd groups */ #endif #if defined(FEAT_CRYPT) || defined(FEAT_MBYTE) # define HAS_BW_FLAGS # define FIO_LATIN1 0x01 /* convert Latin1 */ # define FIO_UTF8 0x02 /* convert UTF-8 */ # define FIO_UCS2 0x04 /* convert UCS-2 */ # define FIO_UCS4 0x08 /* convert UCS-4 */ # define FIO_UTF16 0x10 /* convert UTF-16 */ # ifdef WIN3264 # define FIO_CODEPAGE 0x20 /* convert MS-Windows codepage */ # define FIO_PUT_CP(x) (((x) & 0xffff) << 16) /* put codepage in top word */ # define FIO_GET_CP(x) (((x)>>16) & 0xffff) /* get codepage from top word */ # endif # ifdef MACOS_X # define FIO_MACROMAN 0x20 /* convert MacRoman */ # endif # define FIO_ENDIAN_L 0x80 /* little endian */ # define FIO_ENCRYPTED 0x1000 /* encrypt written bytes */ # define FIO_NOCONVERT 0x2000 /* skip encoding conversion */ # define FIO_UCSBOM 0x4000 /* check for BOM at start of file */ # define FIO_ALL -1 /* allow all formats */ #endif /* When converting, a read() or write() may leave some bytes to be converted * for the next call. The value is guessed... */ #define CONV_RESTLEN 30 /* We have to guess how much a sequence of bytes may expand when converting * with iconv() to be able to allocate a buffer. */ #define ICONV_MULT 8 /* * Structure to pass arguments from buf_write() to buf_write_bytes(). */ struct bw_info { int bw_fd; /* file descriptor */ char_u *bw_buf; /* buffer with data to be written */ int bw_len; /* lenght of data */ #ifdef HAS_BW_FLAGS int bw_flags; /* FIO_ flags */ #endif #ifdef FEAT_MBYTE char_u bw_rest[CONV_RESTLEN]; /* not converted bytes */ int bw_restlen; /* nr of bytes in bw_rest[] */ int bw_first; /* first write call */ char_u *bw_conv_buf; /* buffer for writing converted chars */ int bw_conv_buflen; /* size of bw_conv_buf */ int bw_conv_error; /* set for conversion error */ # ifdef USE_ICONV iconv_t bw_iconv_fd; /* descriptor for iconv() or -1 */ # endif #endif }; static int buf_write_bytes __ARGS((struct bw_info *ip)); #ifdef FEAT_MBYTE static linenr_T readfile_linenr __ARGS((linenr_T linecnt, char_u *p, char_u *endp)); static int ucs2bytes __ARGS((unsigned c, char_u **pp, int flags)); static int same_encoding __ARGS((char_u *a, char_u *b)); static int get_fio_flags __ARGS((char_u *ptr)); static char_u *check_for_bom __ARGS((char_u *p, long size, int *lenp, int flags)); static int make_bom __ARGS((char_u *buf, char_u *name)); # ifdef WIN3264 static int get_win_fio_flags __ARGS((char_u *ptr)); # endif # ifdef MACOS_X static int get_mac_fio_flags __ARGS((char_u *ptr)); # endif #endif static int move_lines __ARGS((buf_T *frombuf, buf_T *tobuf)); void filemess(buf, name, s, attr) buf_T *buf; char_u *name; char_u *s; int attr; { int msg_scroll_save; if (msg_silent != 0) return; msg_add_fname(buf, name); /* put file name in IObuff with quotes */ /* If it's extremely long, truncate it. */ if (STRLEN(IObuff) > IOSIZE - 80) IObuff[IOSIZE - 80] = NUL; STRCAT(IObuff, s); /* * For the first message may have to start a new line. * For further ones overwrite the previous one, reset msg_scroll before * calling filemess(). */ msg_scroll_save = msg_scroll; if (shortmess(SHM_OVERALL) && !exiting && p_verbose == 0) msg_scroll = FALSE; if (!msg_scroll) /* wait a bit when overwriting an error msg */ check_for_delay(FALSE); msg_start(); msg_scroll = msg_scroll_save; msg_scrolled_ign = TRUE; /* may truncate the message to avoid a hit-return prompt */ msg_outtrans_attr(msg_may_trunc(FALSE, IObuff), attr); msg_clr_eos(); out_flush(); msg_scrolled_ign = FALSE; } /* * Read lines from file "fname" into the buffer after line "from". * * 1. We allocate blocks with lalloc, as big as possible. * 2. Each block is filled with characters from the file with a single read(). * 3. The lines are inserted in the buffer with ml_append(). * * (caller must check that fname != NULL, unless READ_STDIN is used) * * "lines_to_skip" is the number of lines that must be skipped * "lines_to_read" is the number of lines that are appended * When not recovering lines_to_skip is 0 and lines_to_read MAXLNUM. * * flags: * READ_NEW starting to edit a new buffer * READ_FILTER reading filter output * READ_STDIN read from stdin instead of a file * READ_BUFFER read from curbuf instead of a file (converting after reading * stdin) * READ_DUMMY read into a dummy buffer (to check if file contents changed) * * return FAIL for failure, OK otherwise */ int readfile(fname, sfname, from, lines_to_skip, lines_to_read, eap, flags) char_u *fname; char_u *sfname; linenr_T from; linenr_T lines_to_skip; linenr_T lines_to_read; exarg_T *eap; /* can be NULL! */ int flags; { int fd = 0; int newfile = (flags & READ_NEW); int set_options = newfile || (eap != NULL && eap->read_edit); int check_readonly; int filtering = (flags & READ_FILTER); int read_stdin = (flags & READ_STDIN); int read_buffer = (flags & READ_BUFFER); linenr_T read_buf_lnum = 1; /* next line to read from curbuf */ colnr_T read_buf_col = 0; /* next char to read from this line */ char_u c; linenr_T lnum = from; char_u *ptr = NULL; /* pointer into read buffer */ char_u *buffer = NULL; /* read buffer */ char_u *new_buffer = NULL; /* init to shut up gcc */ char_u *line_start = NULL; /* init to shut up gcc */ int wasempty; /* buffer was empty before reading */ colnr_T len; long size = 0; char_u *p; long filesize = 0; int skip_read = FALSE; #ifdef FEAT_CRYPT char_u *cryptkey = NULL; #endif int split = 0; /* number of split lines */ #define UNKNOWN 0x0fffffff /* file size is unknown */ linenr_T linecnt; int error = FALSE; /* errors encountered */ int ff_error = EOL_UNKNOWN; /* file format with errors */ long linerest = 0; /* remaining chars in line */ #ifdef UNIX int perm = 0; int swap_mode = -1; /* protection bits for swap file */ #else int perm; #endif int fileformat = 0; /* end-of-line format */ int keep_fileformat = FALSE; struct stat st; int file_readonly; linenr_T skip_count = 0; linenr_T read_count = 0; int msg_save = msg_scroll; linenr_T read_no_eol_lnum = 0; /* non-zero lnum when last line of * last read was missing the eol */ int try_mac = (vim_strchr(p_ffs, 'm') != NULL); int try_dos = (vim_strchr(p_ffs, 'd') != NULL); int try_unix = (vim_strchr(p_ffs, 'x') != NULL); int file_rewind = FALSE; #ifdef FEAT_MBYTE int can_retry; linenr_T conv_error = 0; /* line nr with conversion error */ linenr_T illegal_byte = 0; /* line nr with illegal byte */ int keep_dest_enc = FALSE; /* don't retry when char doesn't fit in destination encoding */ int bad_char_behavior = BAD_REPLACE; /* BAD_KEEP, BAD_DROP or character to * replace with */ char_u *tmpname = NULL; /* name of 'charconvert' output file */ int fio_flags = 0; char_u *fenc; /* fileencoding to use */ int fenc_alloced; /* fenc_next is in allocated memory */ char_u *fenc_next = NULL; /* next item in 'fencs' or NULL */ int advance_fenc = FALSE; long real_size = 0; # ifdef USE_ICONV iconv_t iconv_fd = (iconv_t)-1; /* descriptor for iconv() or -1 */ # ifdef FEAT_EVAL int did_iconv = FALSE; /* TRUE when iconv() failed and trying 'charconvert' next */ # endif # endif int converted = FALSE; /* TRUE if conversion done */ int notconverted = FALSE; /* TRUE if conversion wanted but it wasn't possible */ char_u conv_rest[CONV_RESTLEN]; int conv_restlen = 0; /* nr of bytes in conv_rest[] */ #endif write_no_eol_lnum = 0; /* in case it was set by the previous read */ /* * If there is no file name yet, use the one for the read file. * BF_NOTEDITED is set to reflect this. * Don't do this for a read from a filter. * Only do this when 'cpoptions' contains the 'f' flag. */ if (curbuf->b_ffname == NULL && !filtering && fname != NULL && vim_strchr(p_cpo, CPO_FNAMER) != NULL && !(flags & READ_DUMMY)) { if (set_rw_fname(fname, sfname) == FAIL) return FAIL; } /* After reading a file the cursor line changes but we don't want to * display the line. */ ex_no_reprint = TRUE; /* don't display the file info for another buffer now */ need_fileinfo = FALSE; /* * For Unix: Use the short file name whenever possible. * Avoids problems with networks and when directory names are changed. * Don't do this for MS-DOS, a "cd" in a sub-shell may have moved us to * another directory, which we don't detect. */ if (sfname == NULL) sfname = fname; #if defined(UNIX) || defined(__EMX__) fname = sfname; #endif #ifdef FEAT_AUTOCMD /* * The BufReadCmd and FileReadCmd events intercept the reading process by * executing the associated commands instead. */ if (!filtering && !read_stdin && !read_buffer) { pos_T pos; pos = curbuf->b_op_start; /* Set '[ mark to the line above where the lines go (line 1 if zero). */ curbuf->b_op_start.lnum = ((from == 0) ? 1 : from); curbuf->b_op_start.col = 0; if (newfile) { if (apply_autocmds_exarg(EVENT_BUFREADCMD, NULL, sfname, FALSE, curbuf, eap)) #ifdef FEAT_EVAL return aborting() ? FAIL : OK; #else return OK; #endif } else if (apply_autocmds_exarg(EVENT_FILEREADCMD, sfname, sfname, FALSE, NULL, eap)) #ifdef FEAT_EVAL return aborting() ? FAIL : OK; #else return OK; #endif curbuf->b_op_start = pos; } #endif if ((shortmess(SHM_OVER) || curbuf->b_help) && p_verbose == 0) msg_scroll = FALSE; /* overwrite previous file message */ else msg_scroll = TRUE; /* don't overwrite previous file message */ /* * If the name ends in a path separator, we can't open it. Check here, * because reading the file may actually work, but then creating the swap * file may destroy it! Reported on MS-DOS and Win 95. * If the name is too long we might crash further on, quit here. */ if (fname != NULL && *fname != NUL) { p = fname + STRLEN(fname); if (after_pathsep(fname, p) || STRLEN(fname) >= MAXPATHL) { filemess(curbuf, fname, (char_u *)_("Illegal file name"), 0); msg_end(); msg_scroll = msg_save; return FAIL; } } #ifdef UNIX /* * On Unix it is possible to read a directory, so we have to * check for it before the mch_open(). */ if (!read_stdin && !read_buffer) { perm = mch_getperm(fname); if (perm >= 0 && !S_ISREG(perm) /* not a regular file ... */ # ifdef S_ISFIFO && !S_ISFIFO(perm) /* ... or fifo */ # endif # ifdef S_ISSOCK && !S_ISSOCK(perm) /* ... or socket */ # endif ) { if (S_ISDIR(perm)) filemess(curbuf, fname, (char_u *)_("is a directory"), 0); else filemess(curbuf, fname, (char_u *)_("is not a file"), 0); msg_end(); msg_scroll = msg_save; return FAIL; } # if defined(MSDOS) || defined(MSWIN) || defined(OS2) /* * MS-Windows allows opening a device, but we will probably get stuck * trying to read it. */ if (!p_odev && mch_nodetype(fname) == NODE_WRITABLE) { filemess(curbuf, fname, (char_u *)_("is a device (disabled with 'opendevice' option"), 0); msg_end(); msg_scroll = msg_save; return FAIL; } # endif } #endif /* set default 'fileformat' */ if (set_options) { if (eap != NULL && eap->force_ff != 0) set_fileformat(get_fileformat_force(curbuf, eap), OPT_LOCAL); else if (*p_ffs != NUL) set_fileformat(default_fileformat(), OPT_LOCAL); } /* set or reset 'binary' */ if (eap != NULL && eap->force_bin != 0) { int oldval = curbuf->b_p_bin; curbuf->b_p_bin = (eap->force_bin == FORCE_BIN); set_options_bin(oldval, curbuf->b_p_bin, OPT_LOCAL); } /* * When opening a new file we take the readonly flag from the file. * Default is r/w, can be set to r/o below. * Don't reset it when in readonly mode * Only set/reset b_p_ro when BF_CHECK_RO is set. */ check_readonly = (newfile && (curbuf->b_flags & BF_CHECK_RO)); if (check_readonly && !readonlymode) curbuf->b_p_ro = FALSE; if (newfile && !read_stdin && !read_buffer) { /* Remember time of file. * For RISCOS, also remember the filetype. */ if (mch_stat((char *)fname, &st) >= 0) { buf_store_time(curbuf, &st, fname); curbuf->b_mtime_read = curbuf->b_mtime; #if defined(RISCOS) && defined(FEAT_OSFILETYPE) /* Read the filetype into the buffer local filetype option. */ mch_read_filetype(fname); #endif #ifdef UNIX /* * Use the protection bits of the original file for the swap file. * This makes it possible for others to read the name of the * edited file from the swapfile, but only if they can read the * edited file. * Remove the "write" and "execute" bits for group and others * (they must not write the swapfile). * Add the "read" and "write" bits for the user, otherwise we may * not be able to write to the file ourselves. * Setting the bits is done below, after creating the swap file. */ swap_mode = (st.st_mode & 0644) | 0600; #endif #ifdef FEAT_CW_EDITOR /* Get the FSSpec on MacOS * TODO: Update it properly when the buffer name changes */ (void)GetFSSpecFromPath(curbuf->b_ffname, &curbuf->b_FSSpec); #endif #ifdef VMS curbuf->b_fab_rfm = st.st_fab_rfm; curbuf->b_fab_rat = st.st_fab_rat;