diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/buffer.c | 120 | ||||
-rw-r--r-- | src/nvim/buffer_defs.h | 8 | ||||
-rw-r--r-- | src/nvim/ex_cmds2.c | 24 | ||||
-rw-r--r-- | src/nvim/file_search.c | 28 | ||||
-rw-r--r-- | src/nvim/fileio.c | 9 | ||||
-rw-r--r-- | src/nvim/if_cscope.c | 15 | ||||
-rw-r--r-- | src/nvim/if_cscope_defs.h | 7 | ||||
-rw-r--r-- | src/nvim/memline.c | 42 | ||||
-rw-r--r-- | src/nvim/os/fs.c | 104 | ||||
-rw-r--r-- | src/nvim/os/fs_defs.h | 19 | ||||
-rw-r--r-- | src/nvim/os/os.h | 7 | ||||
-rw-r--r-- | src/nvim/os_unix.c | 11 | ||||
-rw-r--r-- | src/nvim/os_unix_defs.h | 3 | ||||
-rw-r--r-- | src/nvim/path.c | 14 |
14 files changed, 210 insertions, 201 deletions
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 67cd5a3094..2152502c95 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -70,21 +70,12 @@ #include "nvim/window.h" #include "nvim/os/os.h" -// Todo(stefan991): remove this macro -#define INVALID_DEVICE_ID UINT64_MAX - #define HAVE_BUFLIST_MATCH #ifdef INCLUDE_GENERATED_DECLARATIONS # include "buffer.c.generated.h" #endif -#ifdef UNIX -# define dev_T dev_t -#else -# define dev_T unsigned -#endif - static char *msg_loclist = N_("[Location List]"); static char *msg_qflist = N_("[Quickfix List]"); static char *e_auabort = N_("E855: Autocommands caused command to abort"); @@ -1300,12 +1291,12 @@ buflist_new ( */ /* We can use inode numbers when the file exists. Works better * for hard links. */ - FileInfo file_info; - if (sfname == NULL || !os_get_file_info((char *)sfname, &file_info)) { - file_info.stat.st_dev = INVALID_DEVICE_ID; - } + FileID file_id; + bool file_id_valid = (sfname != NULL && + os_get_file_id((char *)sfname, &file_id)); if (ffname != NULL && !(flags & BLN_DUMMY) - && (buf = buflist_findname_file_info(ffname, &file_info)) != NULL) { + && (buf = buflist_findname_file_id(ffname, &file_id, + file_id_valid)) != NULL) { free(ffname); if (lnum != 0) buflist_setfpos(buf, curwin, lnum, (colnr_T)0, FALSE); @@ -1432,12 +1423,11 @@ buflist_new ( hash_init(&buf->b_s.b_keywtab_ic); buf->b_fname = buf->b_sfname; - if (file_info.stat.st_dev == INVALID_DEVICE_ID) - buf->b_dev_valid = FALSE; - else { - buf->b_dev_valid = TRUE; - buf->b_dev = file_info.stat.st_dev; - buf->b_ino = file_info.stat.st_ino; + if (!file_id_valid) { + buf->file_id_valid = false; + } else { + buf->file_id_valid = true; + buf->file_id = file_id; } buf->b_u_synced = TRUE; buf->b_flags = BF_CHECK_RO | BF_NEVERLOADED; @@ -1658,25 +1648,24 @@ buf_T *buflist_findname_exp(char_u *fname) */ buf_T *buflist_findname(char_u *ffname) { - FileInfo file_info; - if (!os_get_file_info((char *)ffname, &file_info)) { - file_info.stat.st_dev = INVALID_DEVICE_ID; - } - return buflist_findname_file_info(ffname, &file_info); + FileID file_id; + bool file_id_valid = os_get_file_id((char *)ffname, &file_id); + return buflist_findname_file_id(ffname, &file_id, file_id_valid); } /* - * Same as buflist_findname(), but pass the FileInfo structure to avoid + * Same as buflist_findname(), but pass the FileID structure to avoid * getting it twice for the same file. * Returns NULL if not found. */ -static buf_T *buflist_findname_file_info(char_u *ffname, FileInfo *file_info) +static buf_T *buflist_findname_file_id(char_u *ffname, FileID *file_id, + bool file_id_valid) { buf_T *buf; for (buf = firstbuf; buf != NULL; buf = buf->b_next) { if ((buf->b_flags & BF_DUMMY) == 0 - && !otherfile_buf(buf, ffname, file_info)) { + && !otherfile_buf(buf, ffname, file_id, file_id_valid)) { return buf; } } @@ -2192,7 +2181,8 @@ setfname ( ) { buf_T *obuf = NULL; - FileInfo file_info; + FileID file_id; + bool file_id_valid = false; if (ffname == NULL || *ffname == NUL) { /* Removing the name. */ @@ -2200,7 +2190,6 @@ setfname ( free(buf->b_sfname); buf->b_ffname = NULL; buf->b_sfname = NULL; - file_info.stat.st_dev = INVALID_DEVICE_ID; } else { fname_expand(buf, &ffname, &sfname); /* will allocate ffname */ if (ffname == NULL) /* out of memory */ @@ -2211,11 +2200,9 @@ setfname ( * - if the buffer is loaded, fail * - if the buffer is not loaded, delete it from the list */ - if (!os_get_file_info((char *)ffname, &file_info)) { - file_info.stat.st_dev = INVALID_DEVICE_ID; - } + file_id_valid = os_get_file_id((char *)ffname, &file_id); if (!(buf->b_flags & BF_DUMMY)) { - obuf = buflist_findname_file_info(ffname, &file_info); + obuf = buflist_findname_file_id(ffname, &file_id, file_id_valid); } if (obuf != NULL && obuf != buf) { if (obuf->b_ml.ml_mfp != NULL) { /* it's loaded, fail */ @@ -2241,12 +2228,11 @@ setfname ( buf->b_sfname = sfname; } buf->b_fname = buf->b_sfname; - if (file_info.stat.st_dev == INVALID_DEVICE_ID) { - buf->b_dev_valid = FALSE; + if (!file_id_valid) { + buf->file_id_valid = false; } else { - buf->b_dev_valid = TRUE; - buf->b_dev = file_info.stat.st_dev; - buf->b_ino = file_info.stat.st_ino; + buf->file_id_valid = true; + buf->file_id = file_id; } buf_name_changed(buf); @@ -2380,10 +2366,11 @@ void buflist_altfpos(win_T *win) */ int otherfile(char_u *ffname) { - return otherfile_buf(curbuf, ffname, NULL); + return otherfile_buf(curbuf, ffname, NULL, false); } -static int otherfile_buf(buf_T *buf, char_u *ffname, FileInfo *file_info_p) +static int otherfile_buf(buf_T *buf, char_u *ffname, + FileID *file_id_p, bool file_id_valid) { /* no name is different */ if (ffname == NULL || *ffname == NUL || buf->b_ffname == NULL) { @@ -2393,14 +2380,15 @@ static int otherfile_buf(buf_T *buf, char_u *ffname, FileInfo *file_info_p) return FALSE; } { - FileInfo file_info; - + FileID file_id; /* If no struct stat given, get it now */ - if (file_info_p == NULL) { - if (!buf->b_dev_valid || !os_get_file_info((char *)ffname, &file_info)) { - file_info.stat.st_dev = INVALID_DEVICE_ID; - } - file_info_p = &file_info; + if (file_id_p == NULL) { + file_id_p = &file_id; + file_id_valid = os_get_file_id((char *)ffname, file_id_p); + } + if (!file_id_valid) { + // file_id not valid, assume files are different. + return TRUE; } /* 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 @@ -2411,40 +2399,34 @@ static int otherfile_buf(buf_T *buf, char_u *ffname, FileInfo *file_info_p) * 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 * file. */ - if (buf_same_ino(buf, file_info_p)) { - buf_setino(buf); - if (buf_same_ino(buf, file_info_p)) + if (buf_same_file_id(buf, file_id_p)) { + buf_set_file_id(buf); + if (buf_same_file_id(buf, file_id_p)) return FALSE; } } return TRUE; } -/* - * Set inode and device number for a buffer. - * Must always be called when b_fname is changed!. - */ -void buf_setino(buf_T *buf) +// Set file_id for a buffer. +// Must always be called when b_fname is changed! +void buf_set_file_id(buf_T *buf) { - FileInfo file_info; + FileID file_id; if (buf->b_fname != NULL - && os_get_file_info((char *)buf->b_fname, &file_info)) { - buf->b_dev_valid = TRUE; - buf->b_dev = file_info.stat.st_dev; - buf->b_ino = file_info.stat.st_ino; + && os_get_file_id((char *)buf->b_fname, &file_id)) { + buf->file_id_valid = true; + buf->file_id = file_id; } else { - buf->b_dev_valid = FALSE; + buf->file_id_valid = false; } } -/* - * Return TRUE if dev/ino in buffer "buf" matches with "stp". - */ -static int buf_same_ino(buf_T *buf, FileInfo *file_info) +// return TRUE if file_id in buffer "buf" matches with "file_id". +static bool buf_same_file_id(buf_T *buf, FileID *file_id) { - return buf->b_dev_valid - && file_info->stat.st_dev == buf->b_dev - && file_info->stat.st_ino == buf->b_ino; + return buf->file_id_valid + && os_file_id_equal(&(buf->file_id), file_id); } /* diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index a505df5e93..1f61c00325 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -88,6 +88,9 @@ typedef struct memfile memfile_T; // for signlist_T #include "nvim/sign_defs.h" +// for FileID +#include "nvim/os/fs_defs.h" + /* * The taggy struct is used to store the information about a :tag command. */ @@ -471,9 +474,8 @@ struct file_buffer { char_u *b_sfname; /* short file name */ char_u *b_fname; /* current file name */ - int b_dev_valid; /* TRUE when b_dev has a valid number */ - uint64_t b_dev; /* device number */ - uint64_t b_ino; /* inode number */ + bool file_id_valid; + FileID file_id; int b_fnum; /* buffer number for this file. */ diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index 17c0f3bf3e..93822ebcfe 100644 --- a/src/nvim/ex_cmds2.c +++ b/src/nvim/ex_cmds2.c @@ -45,6 +45,7 @@ #include "nvim/window.h" #include "nvim/os/os.h" #include "nvim/os/shell.h" +#include "nvim/os/fs_defs.h" /* Growarray to store info about already sourced scripts. @@ -52,9 +53,8 @@ * script when going through the list. */ typedef struct scriptitem_S { char_u *sn_name; - int sn_dev_valid; - uint64_t sn_dev; - uint64_t sn_ino; + bool file_id_valid; + FileID file_id; int sn_prof_on; /* TRUE when script is/was profiled */ int sn_pr_force; /* forceit: profile functions in this script */ proftime_T sn_pr_child; /* time set when going into first child */ @@ -2559,15 +2559,14 @@ do_source ( * If it's new, generate a new SID. */ save_current_SID = current_SID; - FileInfo file_info; - bool file_info_ok = os_get_file_info((char *)fname_exp, &file_info); + FileID file_id; + bool file_id_ok = os_get_file_id((char *)fname_exp, &file_id); for (current_SID = script_items.ga_len; current_SID > 0; --current_SID) { si = &SCRIPT_ITEM(current_SID); // Compare dev/ino when possible, it catches symbolic links. // Also compare file names, the inode may change when the file was edited. - bool file_id_equal = file_info_ok && si->sn_dev_valid - && si->sn_dev == file_info.stat.st_dev - && si->sn_ino == file_info.stat.st_ino; + bool file_id_equal = file_id_ok && si->file_id_valid + && os_file_id_equal(&(si->file_id), &file_id); if (si->sn_name != NULL && (file_id_equal || fnamecmp(si->sn_name, fname_exp) == 0)) { break; @@ -2584,12 +2583,11 @@ do_source ( si = &SCRIPT_ITEM(current_SID); si->sn_name = fname_exp; fname_exp = NULL; - if (file_info_ok) { - si->sn_dev_valid = TRUE; - si->sn_dev = file_info.stat.st_dev; - si->sn_ino = file_info.stat.st_ino; + if (file_id_ok) { + si->file_id_valid = true; + si->file_id = file_id; } else { - si->sn_dev_valid = FALSE; + si->file_id_valid = false; } /* Allocate the local script variables to use for this script. */ diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c index f6a052255b..6694630337 100644 --- a/src/nvim/file_search.c +++ b/src/nvim/file_search.c @@ -61,6 +61,7 @@ #include "nvim/ui.h" #include "nvim/window.h" #include "nvim/os/os.h" +#include "nvim/os/fs_defs.h" static char_u *ff_expand_buffer = NULL; /* used for expanding filenames */ @@ -108,12 +109,9 @@ typedef struct ff_visited { * different. So we have to save it. */ char_u *ffv_wc_path; - /* for unix use inode etc for comparison (needed because of links), else - * use filename. - */ - int ffv_dev_valid; /* ffv_dev and ffv_ino were set */ - uint64_t ffv_dev; /* device number */ - uint64_t ffv_ino; /* inode number */ + // use FileID for comparison (needed because of links), else use filename. + bool file_id_valid; + FileID file_id; /* The memory for this struct is allocated according to the length of * ffv_fname. */ @@ -1088,15 +1086,15 @@ static int ff_check_visited(ff_visited_T **visited_list, char_u *fname, char_u * ff_visited_T *vp; bool url = false; - FileInfo file_info; - // For a URL we only compare the name, otherwise we compare the + FileID file_id; + // For an URL we only compare the name, otherwise we compare the // device/inode. if (path_with_url(fname)) { STRLCPY(ff_expand_buffer, fname, MAXPATHL); url = true; } else { ff_expand_buffer[0] = NUL; - if (!os_get_file_info((char *)fname, &file_info)) { + if (!os_get_file_id((char *)fname, &file_id)) { return FAIL; } } @@ -1104,9 +1102,8 @@ static int ff_check_visited(ff_visited_T **visited_list, char_u *fname, char_u * /* check against list of already visited files */ for (vp = *visited_list; vp != NULL; vp = vp->ffv_next) { if ((url && fnamecmp(vp->ffv_fname, ff_expand_buffer) == 0) - || (!url && vp->ffv_dev_valid - && vp->ffv_dev == file_info.stat.st_dev - && vp->ffv_ino == file_info.stat.st_ino)) { + || (!url && vp->file_id_valid + && os_file_id_equal(&(vp->file_id), &file_id))) { /* are the wildcard parts equal */ if (ff_wc_equal(vp->ffv_wc_path, wc_path) == TRUE) /* already visited */ @@ -1120,12 +1117,11 @@ static int ff_check_visited(ff_visited_T **visited_list, char_u *fname, char_u * vp = xmalloc(sizeof(ff_visited_T) + STRLEN(ff_expand_buffer)); if (!url) { - vp->ffv_dev_valid = TRUE; - vp->ffv_ino = file_info.stat.st_ino; - vp->ffv_dev = file_info.stat.st_dev; + vp->file_id_valid = true; + vp->file_id = file_id; vp->ffv_fname[0] = NUL; } else { - vp->ffv_dev_valid = FALSE; + vp->file_id_valid = false; STRCPY(vp->ffv_fname, ff_expand_buffer); } diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 129f1a1de2..6f21679549 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -3433,10 +3433,11 @@ restore_backup: (void)os_setperm(wfname, perm); } # endif - buf_setino(buf); - } else if (!buf->b_dev_valid) - /* Set the inode when creating a new file. */ - buf_setino(buf); + buf_set_file_id(buf); + } else if (!buf->file_id_valid) { + // Set the file_id when creating a new file. + buf_set_file_id(buf); + } #endif if (close(fd) != 0) { diff --git a/src/nvim/if_cscope.c b/src/nvim/if_cscope.c index ffc00f060a..73dac908e9 100644 --- a/src/nvim/if_cscope.c +++ b/src/nvim/if_cscope.c @@ -1139,14 +1139,7 @@ static void clear_csinfo(int i) csinfo[i].fname = NULL; csinfo[i].ppath = NULL; csinfo[i].flags = NULL; -#if defined(UNIX) - csinfo[i].st_dev = (dev_t)0; - csinfo[i].st_ino = (ino_t)0; -#else - csinfo[i].nVolume = 0; - csinfo[i].nIndexHigh = 0; - csinfo[i].nIndexLow = 0; -#endif + csinfo[i].file_id = FILE_ID_EMPTY; csinfo[i].pid = 0; csinfo[i].fr_fp = NULL; csinfo[i].to_fp = NULL; @@ -1181,8 +1174,7 @@ static int cs_insert_filelist(char *fname, char *ppath, char *flags, i = -1; /* can be set to the index of an empty item in csinfo */ for (j = 0; j < csinfo_size; j++) { if (csinfo[j].fname != NULL - && csinfo[j].st_dev == file_info->stat.st_dev - && csinfo[j].st_ino == file_info->stat.st_ino) { + && os_file_id_equal_file_info(&(csinfo[j].file_id), file_info)) { if (p_csverbose) (void)EMSG(_("E568: duplicate cscope database not added")); return -1; @@ -1225,8 +1217,7 @@ static int cs_insert_filelist(char *fname, char *ppath, char *flags, } else csinfo[i].flags = NULL; - csinfo[i].st_dev = file_info->stat.st_dev; - csinfo[i].st_ino = file_info->stat.st_ino; + os_file_info_get_id(file_info, &(csinfo[i].file_id)); return i; } /* cs_insert_filelist */ diff --git a/src/nvim/if_cscope_defs.h b/src/nvim/if_cscope_defs.h index 0ec9e30516..a0c84e8ba1 100644 --- a/src/nvim/if_cscope_defs.h +++ b/src/nvim/if_cscope_defs.h @@ -14,10 +14,10 @@ #if defined(UNIX) # include <sys/types.h> /* pid_t */ -# include <sys/stat.h> /* dev_t, ino_t */ -#else #endif +#include "nvim/os/fs_defs.h" + #define CSCOPE_SUCCESS 0 #define CSCOPE_FAILURE -1 @@ -52,8 +52,7 @@ typedef struct csi { #if defined(UNIX) pid_t pid; /* PID of the connected cscope process. */ #endif - uint64_t st_dev; /* ID of dev containing cscope db */ - uint64_t st_ino; /* inode number of cscope db */ + FileID file_id; FILE * fr_fp; /* from cscope: FILE. */ FILE * to_fp; /* to cscope: FILE. */ diff --git a/src/nvim/memline.c b/src/nvim/memline.c index b3a8df598b..17b07bdede 100644 --- a/src/nvim/memline.c +++ b/src/nvim/memline.c @@ -686,16 +686,12 @@ static void set_b0_fname(ZERO_BL *b0p, buf_T *buf) FileInfo file_info; if (os_get_file_info((char *)buf->b_ffname, &file_info)) { long_to_char((long)file_info.stat.st_mtim.tv_sec, b0p->b0_mtime); -#ifdef CHECK_INODE - long_to_char((long)file_info.stat.st_ino, b0p->b0_ino); -#endif + long_to_char((long)os_file_info_get_inode(&file_info), b0p->b0_ino); buf_store_file_info(buf, &file_info); buf->b_mtime_read = buf->b_mtime; } else { long_to_char(0L, b0p->b0_mtime); -#ifdef CHECK_INODE long_to_char(0L, b0p->b0_ino); -#endif buf->b_mtime = 0; buf->b_mtime_read = 0; buf->b_orig_size = 0; @@ -3339,17 +3335,16 @@ findswapname ( */ if (b0.b0_flags & B0_SAME_DIR) { if (fnamecmp(path_tail(buf->b_ffname), - path_tail(b0.b0_fname)) != 0 + path_tail(b0.b0_fname)) != 0 || !same_directory(fname, buf->b_ffname)) { -#ifdef CHECK_INODE /* Symlinks may point to the same file even * when the name differs, need to check the * inode too. */ expand_env(b0.b0_fname, NameBuff, MAXPATHL); if (fnamecmp_ino(buf->b_ffname, NameBuff, - char_to_long(b0.b0_ino))) -#endif - differ = TRUE; + char_to_long(b0.b0_ino))) { + differ = TRUE; + } } } else { /* @@ -3357,14 +3352,10 @@ findswapname ( * "~user/path/file". Expand it first. */ expand_env(b0.b0_fname, NameBuff, MAXPATHL); -#ifdef CHECK_INODE if (fnamecmp_ino(buf->b_ffname, NameBuff, - char_to_long(b0.b0_ino))) + char_to_long(b0.b0_ino))) { differ = TRUE; -#else - if (fnamecmp(NameBuff, buf->b_ffname) != 0) - differ = TRUE; -#endif + } } } close(fd); @@ -3504,7 +3495,6 @@ static int b0_magic_wrong(ZERO_BL *b0p) || b0p->b0_magic_char != B0_MAGIC_CHAR; } -#ifdef CHECK_INODE /* * Compare current file name with file name from swap file. * Try to use inode numbers when possible. @@ -3549,20 +3539,19 @@ static int b0_magic_wrong(ZERO_BL *b0p) * available -> probably same file * == 0 == 0 FAIL FAIL FALSE * - * Note that when the ino_t is 64 bits, only the last 32 will be used. This - * can't be changed without making the block 0 incompatible with 32 bit - * versions. + * Only the last 32 bits of the inode will be used. This can't be changed + * without making the block 0 incompatible with 32 bit versions. */ -static int +static int fnamecmp_ino ( char_u *fname_c, /* current file name */ char_u *fname_s, /* file name from swap file */ long ino_block0 ) { - ino_t ino_c = 0; /* ino of current file */ - ino_t ino_s; /* ino of file from swap file */ + uint64_t ino_c = 0; /* ino of current file */ + uint64_t ino_s; /* ino of file from swap file */ char_u buf_c[MAXPATHL]; /* full path of fname_c */ char_u buf_s[MAXPATHL]; /* full path of fname_s */ int retval_c; /* flag: buf_c valid */ @@ -3570,7 +3559,7 @@ fnamecmp_ino ( FileInfo file_info; if (os_get_file_info((char *)fname_c, &file_info)) { - ino_c = (ino_t)file_info.stat.st_ino; + ino_c = os_file_info_get_inode(&file_info); } /* @@ -3579,9 +3568,9 @@ fnamecmp_ino ( * valid on this machine), use the inode from block 0. */ if (os_get_file_info((char *)fname_s, &file_info)) { - ino_s = (ino_t)file_info.stat.st_ino; + ino_s = os_file_info_get_inode(&file_info); } else { - ino_s = (ino_t)ino_block0; + ino_s = (uint64_t)ino_block0; } if (ino_c && ino_s) @@ -3604,7 +3593,6 @@ fnamecmp_ino ( return FALSE; return TRUE; } -#endif /* CHECK_INODE */ /* * Move a long integer into a four byte character array. diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index c8408d78e4..65b88c06f4 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -149,19 +149,13 @@ static bool is_executable_in_path(const char_u *name) /// Get stat information for a file. /// /// @return OK on success, FAIL if a failure occurred. -int os_stat(const char_u *name, uv_stat_t *statbuf) +static bool os_stat(const char *name, uv_stat_t *statbuf) { uv_fs_t request; - int result = uv_fs_stat(uv_default_loop(), &request, - (const char *)name, NULL); + int result = uv_fs_stat(uv_default_loop(), &request, name, NULL); *statbuf = request.statbuf; uv_fs_req_cleanup(&request); - - if (result == kLibuvSuccess) { - return OK; - } - - return FAIL; + return (result == kLibuvSuccess); } /// Get the file permissions for a given file. @@ -170,10 +164,10 @@ int os_stat(const char_u *name, uv_stat_t *statbuf) int32_t os_getperm(const char_u *name) { uv_stat_t statbuf; - if (os_stat(name, &statbuf) == FAIL) { - return -1; - } else { + if (os_stat((char *)name, &statbuf)) { return (int32_t)statbuf.st_mode; + } else { + return -1; } } @@ -200,11 +194,7 @@ int os_setperm(const char_u *name, int perm) bool os_file_exists(const char_u *name) { uv_stat_t statbuf; - if (os_stat(name, &statbuf) == OK) { - return true; - } - - return false; + return os_stat((char *)name, &statbuf); } /// Check if a file is readonly. @@ -238,7 +228,7 @@ int os_file_is_writable(const char *name) bool os_get_file_size(const char *name, off_t *size) { uv_stat_t statbuf; - if (os_stat((char_u *)name, &statbuf) == OK) { + if (os_stat(name, &statbuf)) { *size = statbuf.st_size; return true; } @@ -302,10 +292,7 @@ int os_remove(const char *path) /// @return `true` on success, `false` for failure. bool os_get_file_info(const char *path, FileInfo *file_info) { - if (os_stat((char_u *)path, &(file_info->stat)) == OK) { - return true; - } - return false; + return os_stat(path, &(file_info->stat)); } /// Get the file information for a given path without following links @@ -319,10 +306,7 @@ bool os_get_file_info_link(const char *path, FileInfo *file_info) int result = uv_fs_lstat(uv_default_loop(), &request, path, NULL); file_info->stat = request.statbuf; uv_fs_req_cleanup(&request); - if (result == kLibuvSuccess) { - return true; - } - return false; + return (result == kLibuvSuccess); } /// Get the file information for a given file descriptor @@ -336,17 +320,75 @@ bool os_get_file_info_fd(int file_descriptor, FileInfo *file_info) int result = uv_fs_fstat(uv_default_loop(), &request, file_descriptor, NULL); file_info->stat = request.statbuf; uv_fs_req_cleanup(&request); - if (result == kLibuvSuccess) { - return true; - } - return false; + return (result == kLibuvSuccess); } /// Compare the inodes of two FileInfos /// /// @return `true` if the two FileInfos represent the same file. -bool os_file_info_id_equal(FileInfo *file_info_1, FileInfo *file_info_2) +bool os_file_info_id_equal(const FileInfo *file_info_1, + const FileInfo *file_info_2) { return file_info_1->stat.st_ino == file_info_2->stat.st_ino && file_info_1->stat.st_dev == file_info_2->stat.st_dev; } + +/// Get the `FileID` of a `FileInfo` +/// +/// @param file_info Pointer to the `FileInfo` +/// @param[out] file_id Pointer to a `FileID` +void os_file_info_get_id(const FileInfo *file_info, FileID *file_id) +{ + file_id->inode = file_info->stat.st_ino; + file_id->device_id = file_info->stat.st_dev; +} + +/// Get the inode of a `FileInfo` +/// +/// @deprecated Use `FileID` instead, this function is only needed in memline.c +/// @param file_info Pointer to the `FileInfo` +/// @return the inode number +uint64_t os_file_info_get_inode(const FileInfo *file_info) +{ + return file_info->stat.st_ino; +} + +/// Get the `FileID` for a given path +/// +/// @param path Path to the file. +/// @param[out] file_info Pointer to a `FileID` to fill in. +/// @return `true` on sucess, `false` for failure. +bool os_get_file_id(const char *path, FileID *file_id) +{ + uv_stat_t statbuf; + if (os_stat(path, &statbuf)) { + file_id->inode = statbuf.st_ino; + file_id->device_id = statbuf.st_dev; + return true; + } + return false; +} + +/// Check if two `FileID`s are equal +/// +/// @param file_id_1 Pointer to first `FileID` +/// @param file_id_2 Pointer to second `FileID` +/// @return `true` if the two `FileID`s represent te same file. +bool os_file_id_equal(const FileID *file_id_1, const FileID *file_id_2) +{ + return file_id_1->inode == file_id_2->inode + && file_id_1->device_id == file_id_2->device_id; +} + +/// Check if a `FileID` is equal to a `FileInfo` +/// +/// @param file_id Pointer to a `FileID` +/// @param file_info Pointer to a `FileInfo` +/// @return `true` if the `FileID` and the `FileInfo` represent te same file. +bool os_file_id_equal_file_info(const FileID *file_id, + const FileInfo *file_info) +{ + return file_id->inode == file_info->stat.st_ino + && file_id->device_id == file_info->stat.st_dev; +} + diff --git a/src/nvim/os/fs_defs.h b/src/nvim/os/fs_defs.h new file mode 100644 index 0000000000..ab4c05b965 --- /dev/null +++ b/src/nvim/os/fs_defs.h @@ -0,0 +1,19 @@ +#ifndef NVIM_OS_FS_DEFS_H +#define NVIM_OS_FS_DEFS_H + +#include <uv.h> + +/// Struct which encapsulates stat information. +typedef struct { + uv_stat_t stat; ///< @private +} FileInfo; + +/// Struct which encapsulates inode/dev_id information. +typedef struct { + uint64_t inode; ///< @private The inode of the file + uint64_t device_id; ///< @private The id of the device containing the file +} FileID; + +#define FILE_ID_EMPTY (FileID){.inode = 0, .device_id = 0} + +#endif // NVIM_OS_FS_DEFS_H diff --git a/src/nvim/os/os.h b/src/nvim/os/os.h index 5dd498e3dc..ca8f7e8546 100644 --- a/src/nvim/os/os.h +++ b/src/nvim/os/os.h @@ -2,14 +2,9 @@ #define NVIM_OS_OS_H #include <uv.h> +#include "nvim/os/fs_defs.h" #include "nvim/vim.h" -/// Struct which encapsulates stat information. -typedef struct { - // TODO(stefan991): make stat private - uv_stat_t stat; -} FileInfo; - #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os/fs.h.generated.h" # include "os/mem.h.generated.h" diff --git a/src/nvim/os_unix.c b/src/nvim/os_unix.c index 946eaa62a2..6d1b06dbcf 100644 --- a/src/nvim/os_unix.c +++ b/src/nvim/os_unix.c @@ -381,12 +381,12 @@ char_u *name, int len /* buffer size, only used when name gets longer */ ) { - struct stat st; char_u *slash, *tail; DIR *dirp; struct dirent *dp; - if (lstat((char *)name, &st) >= 0) { + FileInfo file_info; + if (os_get_file_info_link((char *)name, &file_info)) { /* Open the directory where the file is located. */ slash = vim_strrchr(name, '/'); if (slash == NULL) { @@ -406,15 +406,14 @@ int len /* buffer size, only used when name gets longer */ if (STRICMP(tail, dp->d_name) == 0 && STRLEN(tail) == STRLEN(dp->d_name)) { char_u newname[MAXPATHL + 1]; - struct stat st2; /* Verify the inode is equal. */ STRLCPY(newname, name, MAXPATHL + 1); STRLCPY(newname + (tail - name), dp->d_name, MAXPATHL - (tail - name) + 1); - if (lstat((char *)newname, &st2) >= 0 - && st.st_ino == st2.st_ino - && st.st_dev == st2.st_dev) { + FileInfo file_info_new; + if (os_get_file_info_link((char *)newname, &file_info_new) + && os_file_info_id_equal(&file_info, &file_info_new)) { STRCPY(tail, dp->d_name); break; } diff --git a/src/nvim/os_unix_defs.h b/src/nvim/os_unix_defs.h index a4bb1ef296..ebecca3aae 100644 --- a/src/nvim/os_unix_defs.h +++ b/src/nvim/os_unix_defs.h @@ -229,9 +229,6 @@ # define MAXPATHL 1024 #endif -// TODO(stefan991): remove macro -#define CHECK_INODE /* used when checking if a swap file already - exists for a file */ # ifndef DFLT_MAXMEM # define DFLT_MAXMEM (5*1024) /* use up to 5 Mbyte for a buffer */ # endif diff --git a/src/nvim/path.c b/src/nvim/path.c index a0859180c9..093a13db7b 100644 --- a/src/nvim/path.c +++ b/src/nvim/path.c @@ -52,13 +52,13 @@ FileComparison path_full_compare(char_u *s1, char_u *s2, int checkname) char_u exp1[MAXPATHL]; char_u full1[MAXPATHL]; char_u full2[MAXPATHL]; - uv_stat_t st1, st2; + FileID file_id_1, file_id_2; expand_env(s1, exp1, MAXPATHL); - int r1 = os_stat(exp1, &st1); - int r2 = os_stat(s2, &st2); - if (r1 != OK && r2 != OK) { - // If os_stat() doesn't work, may compare the names. + bool id_ok_1 = os_get_file_id((char *)exp1, &file_id_1); + bool id_ok_2 = os_get_file_id((char *)s2, &file_id_2); + if (!id_ok_1 && !id_ok_2) { + // If os_get_file_id() doesn't work, may compare the names. if (checkname) { vim_FullName(exp1, full1, MAXPATHL, FALSE); vim_FullName(s2, full2, MAXPATHL, FALSE); @@ -68,10 +68,10 @@ FileComparison path_full_compare(char_u *s1, char_u *s2, int checkname) } return kBothFilesMissing; } - if (r1 != OK || r2 != OK) { + if (!id_ok_1 || !id_ok_2) { return kOneFileMissing; } - if (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino) { + if (os_file_id_equal(&file_id_1, &file_id_2)) { return kEqualFiles; } return kDifferentFiles; |