replaced mch_stat() in buffer.c

This commit is contained in:
Stefan Hoffmann
2014-05-02 22:04:20 +02:00
parent 8e8dae71da
commit c41535d69d
2 changed files with 69 additions and 109 deletions

View File

@@ -65,6 +65,10 @@
#include "ui.h" #include "ui.h"
#include "undo.h" #include "undo.h"
#include "window.h" #include "window.h"
#include "os/os.h"
// Todo(stefan991): remove this macro
#define INVALID_DEVICE_ID UINT64_MAX
static char_u *buflist_match(regprog_T *prog, buf_T *buf); static char_u *buflist_match(regprog_T *prog, buf_T *buf);
# define HAVE_BUFLIST_MATCH # define HAVE_BUFLIST_MATCH
@@ -72,25 +76,15 @@ static char_u *fname_match(regprog_T *prog, char_u *name);
static void buflist_setfpos(buf_T *buf, win_T *win, linenr_T lnum, static void buflist_setfpos(buf_T *buf, win_T *win, linenr_T lnum,
colnr_T col, int copy_options); colnr_T col, int copy_options);
static wininfo_T *find_wininfo(buf_T *buf, int skip_diff_buffer); static wininfo_T *find_wininfo(buf_T *buf, int skip_diff_buffer);
#ifdef UNIX static buf_T *buflist_findname_file_info(char_u *ffname, FileInfo *file_info);
static buf_T *buflist_findname_stat(char_u *ffname, struct stat *st); static int otherfile_buf(buf_T *buf, char_u *ffname, FileInfo *file_info);
static int otherfile_buf(buf_T *buf, char_u *ffname, struct stat *stp); static int buf_same_ino(buf_T *buf, FileInfo *file_info);
static int buf_same_ino(buf_T *buf, struct stat *stp);
#else
static int otherfile_buf(buf_T *buf, char_u *ffname);
#endif
static int ti_change(char_u *str, char_u **last); static int ti_change(char_u *str, char_u **last);
static int append_arg_number(win_T *wp, char_u *buf, int buflen, int add_file); static int append_arg_number(win_T *wp, char_u *buf, int buflen, int add_file);
static void free_buffer(buf_T *); static void free_buffer(buf_T *);
static void free_buffer_stuff(buf_T *buf, int free_options); static void free_buffer_stuff(buf_T *buf, int free_options);
static void clear_wininfo(buf_T *buf); static void clear_wininfo(buf_T *buf);
#ifdef UNIX
# define dev_T dev_t
#else
# define dev_T unsigned
#endif
static void insert_sign(buf_T *buf, signlist_T *prev, signlist_T *next, int id, linenr_T lnum, int typenr); static void insert_sign(buf_T *buf, signlist_T *prev, signlist_T *next, int id, linenr_T lnum, int typenr);
static char *msg_loclist = N_("[Location List]"); static char *msg_loclist = N_("[Location List]");
@@ -1304,29 +1298,20 @@ buflist_new (
) )
{ {
buf_T *buf; buf_T *buf;
#ifdef UNIX
struct stat st;
#endif
fname_expand(curbuf, &ffname, &sfname); /* will allocate ffname */ fname_expand(curbuf, &ffname, &sfname); /* will allocate ffname */
/* /*
* If file name already exists in the list, update the entry. * If file name already exists in the list, update the entry.
*/ */
#ifdef UNIX /* We can use inode numbers when the file exists. Works better
/* On Unix we can use inode numbers when the file exists. Works better
* for hard links. */ * for hard links. */
if (sfname == NULL || mch_stat((char *)sfname, &st) < 0) FileInfo file_info;
st.st_dev = (dev_T)-1; if (sfname == NULL || !os_get_file_info((char *)sfname, &file_info)) {
#endif file_info.stat.st_dev = INVALID_DEVICE_ID;
if (ffname != NULL && !(flags & BLN_DUMMY) && (buf = }
#ifdef UNIX if (ffname != NULL && !(flags & BLN_DUMMY)
buflist_findname_stat(ffname, && (buf = buflist_findname_file_info(ffname, &file_info)) != NULL) {
&st)
#else
buflist_findname(ffname)
#endif
) != NULL) {
free(ffname); free(ffname);
if (lnum != 0) if (lnum != 0)
buflist_setfpos(buf, curwin, lnum, (colnr_T)0, FALSE); buflist_setfpos(buf, curwin, lnum, (colnr_T)0, FALSE);
@@ -1452,15 +1437,13 @@ buflist_new (
hash_init(&buf->b_s.b_keywtab_ic); hash_init(&buf->b_s.b_keywtab_ic);
buf->b_fname = buf->b_sfname; buf->b_fname = buf->b_sfname;
#ifdef UNIX if (file_info.stat.st_dev == INVALID_DEVICE_ID)
if (st.st_dev == (dev_T)-1)
buf->b_dev_valid = FALSE; buf->b_dev_valid = FALSE;
else { else {
buf->b_dev_valid = TRUE; buf->b_dev_valid = TRUE;
buf->b_dev = st.st_dev; buf->b_dev = file_info.stat.st_dev;
buf->b_ino = st.st_ino; buf->b_ino = file_info.stat.st_ino;
} }
#endif
buf->b_u_synced = TRUE; buf->b_u_synced = TRUE;
buf->b_flags = BF_CHECK_RO | BF_NEVERLOADED; buf->b_flags = BF_CHECK_RO | BF_NEVERLOADED;
if (flags & BLN_DUMMY) if (flags & BLN_DUMMY)
@@ -1682,31 +1665,28 @@ buf_T *buflist_findname_exp(char_u *fname)
*/ */
buf_T *buflist_findname(char_u *ffname) buf_T *buflist_findname(char_u *ffname)
{ {
#ifdef UNIX FileInfo file_info;
struct stat st; if (!os_get_file_info((char *)ffname, &file_info)) {
file_info.stat.st_dev = INVALID_DEVICE_ID;
if (mch_stat((char *)ffname, &st) < 0) }
st.st_dev = (dev_T)-1; return buflist_findname_file_info(ffname, &file_info);
return buflist_findname_stat(ffname, &st);
} }
/* /*
* Same as buflist_findname(), but pass the stat structure to avoid getting it * Same as buflist_findname(), but pass the FileInfo structure to avoid
* twice for the same file. * getting it twice for the same file.
* Returns NULL if not found. * Returns NULL if not found.
*/ */
static buf_T *buflist_findname_stat(char_u *ffname, struct stat *stp) static buf_T *buflist_findname_file_info(char_u *ffname, FileInfo *file_info)
{ {
#endif
buf_T *buf; buf_T *buf;
for (buf = firstbuf; buf != NULL; buf = buf->b_next) for (buf = firstbuf; buf != NULL; buf = buf->b_next) {
if ((buf->b_flags & BF_DUMMY) == 0 && !otherfile_buf(buf, ffname if ((buf->b_flags & BF_DUMMY) == 0
#ifdef UNIX && !otherfile_buf(buf, ffname, file_info)) {
, stp
#endif
))
return buf; return buf;
}
}
return NULL; return NULL;
} }
@@ -2220,9 +2200,7 @@ setfname (
) )
{ {
buf_T *obuf = NULL; buf_T *obuf = NULL;
#ifdef UNIX FileInfo file_info;
struct stat st;
#endif
if (ffname == NULL || *ffname == NUL) { if (ffname == NULL || *ffname == NUL) {
/* Removing the name. */ /* Removing the name. */
@@ -2230,9 +2208,7 @@ setfname (
free(buf->b_sfname); free(buf->b_sfname);
buf->b_ffname = NULL; buf->b_ffname = NULL;
buf->b_sfname = NULL; buf->b_sfname = NULL;
#ifdef UNIX file_info.stat.st_dev = INVALID_DEVICE_ID;
st.st_dev = (dev_T)-1;
#endif
} else { } else {
fname_expand(buf, &ffname, &sfname); /* will allocate ffname */ fname_expand(buf, &ffname, &sfname); /* will allocate ffname */
if (ffname == NULL) /* out of memory */ if (ffname == NULL) /* out of memory */
@@ -2243,16 +2219,12 @@ setfname (
* - if the buffer is loaded, fail * - if the buffer is loaded, fail
* - if the buffer is not loaded, delete it from the list * - if the buffer is not loaded, delete it from the list
*/ */
#ifdef UNIX if (!os_get_file_info((char *)ffname, &file_info)) {
if (mch_stat((char *)ffname, &st) < 0) file_info.stat.st_dev = INVALID_DEVICE_ID;
st.st_dev = (dev_T)-1; }
#endif if (!(buf->b_flags & BF_DUMMY)) {
if (!(buf->b_flags & BF_DUMMY)) obuf = buflist_findname_file_info(ffname, &file_info);
#ifdef UNIX }
obuf = buflist_findname_stat(ffname, &st);
#else
obuf = buflist_findname(ffname);
#endif
if (obuf != NULL && obuf != buf) { if (obuf != NULL && obuf != buf) {
if (obuf->b_ml.ml_mfp != NULL) { /* it's loaded, fail */ if (obuf->b_ml.ml_mfp != NULL) { /* it's loaded, fail */
if (message) if (message)
@@ -2278,15 +2250,13 @@ setfname (
buf->b_sfname = sfname; buf->b_sfname = sfname;
} }
buf->b_fname = buf->b_sfname; buf->b_fname = buf->b_sfname;
#ifdef UNIX if (file_info.stat.st_dev == INVALID_DEVICE_ID) {
if (st.st_dev == (dev_T)-1)
buf->b_dev_valid = FALSE; buf->b_dev_valid = FALSE;
else { } else {
buf->b_dev_valid = TRUE; buf->b_dev_valid = TRUE;
buf->b_dev = st.st_dev; buf->b_dev = file_info.stat.st_dev;
buf->b_ino = st.st_ino; buf->b_ino = file_info.stat.st_ino;
} }
#endif
buf_name_changed(buf); buf_name_changed(buf);
return OK; return OK;
@@ -2419,80 +2389,72 @@ void buflist_altfpos(win_T *win)
*/ */
int otherfile(char_u *ffname) int otherfile(char_u *ffname)
{ {
return otherfile_buf(curbuf, ffname return otherfile_buf(curbuf, ffname, NULL);
#ifdef UNIX
, NULL
#endif
);
} }
static int otherfile_buf(buf_T *buf, char_u *ffname static int otherfile_buf(buf_T *buf, char_u *ffname, FileInfo *file_info_p)
#ifdef UNIX
, struct stat *stp
#endif
)
{ {
/* no name is different */ /* no name is different */
if (ffname == NULL || *ffname == NUL || buf->b_ffname == NULL) if (ffname == NULL || *ffname == NUL || buf->b_ffname == NULL) {
return TRUE; return TRUE;
if (fnamecmp(ffname, buf->b_ffname) == 0) }
if (fnamecmp(ffname, buf->b_ffname) == 0) {
return FALSE; return FALSE;
#ifdef UNIX }
{ {
struct stat st; FileInfo file_info;
/* If no struct stat given, get it now */ /* If no struct stat given, get it now */
if (stp == NULL) { if (file_info_p == NULL) {
if (!buf->b_dev_valid || mch_stat((char *)ffname, &st) < 0) if (!buf->b_dev_valid || !os_get_file_info((char *)ffname, &file_info)) {
st.st_dev = (dev_T)-1; file_info.stat.st_dev = INVALID_DEVICE_ID;
stp = &st; }
file_info_p = &file_info;
} }
/* Use dev/ino to check if the files are the same, even when the names /* Use dev/ino to check if the files are the same, even when the names
* are different (possible with links). Still need to compare the * are different (possible with links). Still need to compare the
* name above, for when the file doesn't exist yet. * name above, for when the file doesn't exist yet.
* Problem: The dev/ino changes when a file is deleted (and created * Problem: The dev/ino changes when a file is deleted (and created
* again) and remains the same when renamed/moved. We don't want to * again) and remains the same when renamed/moved. We don't want to
* mch_stat() each buffer each time, that would be too slow. Get the * stat() each buffer each time, that would be too slow. Get the
* dev/ino again when they appear to match, but not when they appear * dev/ino again when they appear to match, but not when they appear
* to be different: Could skip a buffer when it's actually the same * to be different: Could skip a buffer when it's actually the same
* file. */ * file. */
if (buf_same_ino(buf, stp)) { if (buf_same_ino(buf, file_info_p)) {
buf_setino(buf); buf_setino(buf);
if (buf_same_ino(buf, stp)) if (buf_same_ino(buf, file_info_p))
return FALSE; return FALSE;
} }
} }
#endif
return TRUE; return TRUE;
} }
#if defined(UNIX) || defined(PROTO)
/* /*
* Set inode and device number for a buffer. * Set inode and device number for a buffer.
* Must always be called when b_fname is changed!. * Must always be called when b_fname is changed!.
*/ */
void buf_setino(buf_T *buf) void buf_setino(buf_T *buf)
{ {
struct stat st; FileInfo file_info;
if (buf->b_fname != NULL
if (buf->b_fname != NULL && mch_stat((char *)buf->b_fname, &st) >= 0) { && os_get_file_info((char *)buf->b_fname, &file_info)) {
buf->b_dev_valid = TRUE; buf->b_dev_valid = TRUE;
buf->b_dev = st.st_dev; buf->b_dev = file_info.stat.st_dev;
buf->b_ino = st.st_ino; buf->b_ino = file_info.stat.st_ino;
} else } else {
buf->b_dev_valid = FALSE; buf->b_dev_valid = FALSE;
}
} }
/* /*
* Return TRUE if dev/ino in buffer "buf" matches with "stp". * Return TRUE if dev/ino in buffer "buf" matches with "stp".
*/ */
static int buf_same_ino(buf_T *buf, struct stat *stp) static int buf_same_ino(buf_T *buf, FileInfo *file_info)
{ {
return buf->b_dev_valid return buf->b_dev_valid
&& stp->st_dev == buf->b_dev && file_info->stat.st_dev == buf->b_dev
&& stp->st_ino == buf->b_ino; && file_info->stat.st_ino == buf->b_ino;
} }
#endif
/* /*
* Print info about the current buffer. * Print info about the current buffer.

View File

@@ -423,11 +423,9 @@ struct file_buffer {
char_u *b_sfname; /* short file name */ char_u *b_sfname; /* short file name */
char_u *b_fname; /* current file name */ char_u *b_fname; /* current file name */
#ifdef UNIX
int b_dev_valid; /* TRUE when b_dev has a valid number */ int b_dev_valid; /* TRUE when b_dev has a valid number */
dev_t b_dev; /* device number */ uint64_t b_dev; /* device number */
ino_t b_ino; /* inode number */ uint64_t b_ino; /* inode number */
#endif
int b_fnum; /* buffer number for this file. */ int b_fnum; /* buffer number for this file. */