aboutsummaryrefslogtreecommitdiff
path: root/src/fileio.c
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2014-05-09 15:33:00 -0400
committerJustin M. Keyes <justinkz@gmail.com>2014-05-09 15:33:00 -0400
commit1a3ee71de258b416ca6b80f0a9e3b91460df8dc7 (patch)
treea59167e50add55b51ed31c65944cfa78ddd1c290 /src/fileio.c
parentf3dda65de157f2d7c35286018c20cbc7597ed748 (diff)
parenteae498c4c5d34c1d0af40ecb430cbbc23b0a8e97 (diff)
downloadrneovim-1a3ee71de258b416ca6b80f0a9e3b91460df8dc7.tar.gz
rneovim-1a3ee71de258b416ca6b80f0a9e3b91460df8dc7.tar.bz2
rneovim-1a3ee71de258b416ca6b80f0a9e3b91460df8dc7.zip
Merge pull request #619 from stefan991/mch_stat-cleanup
Replace `struct stat` with `FileInfo`
Diffstat (limited to 'src/fileio.c')
-rw-r--r--src/fileio.c259
1 files changed, 118 insertions, 141 deletions
diff --git a/src/fileio.c b/src/fileio.c
index 8f2639064a..fc23d3765c 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -86,7 +86,7 @@ static void set_file_time(char_u *fname, time_t atime, time_t mtime);
static int set_rw_fname(char_u *fname, char_u *sfname);
static int msg_add_fileformat(int eol_type);
static void msg_add_eol(void);
-static int check_mtime(buf_T *buf, struct stat *s);
+static int check_mtime(buf_T *buf, FileInfo *file_info);
static int time_differs(long t1, long t2);
static int apply_autocmds_exarg(event_T event, char_u *fname, char_u *fname_io,
int force, buf_T *buf,
@@ -262,7 +262,6 @@ readfile (
#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;
@@ -441,8 +440,9 @@ readfile (
if (newfile && !read_stdin && !read_buffer) {
/* Remember time of file. */
- if (mch_stat((char *)fname, &st) >= 0) {
- buf_store_time(curbuf, &st, fname);
+ FileInfo file_info;
+ if (os_get_file_info((char *)fname, &file_info)) {
+ buf_store_file_info(curbuf, &file_info, fname);
curbuf->b_mtime_read = curbuf->b_mtime;
#ifdef UNIX
/*
@@ -456,7 +456,7 @@ readfile (
* 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;
+ swap_mode = (file_info.stat.st_mode & 0644) | 0600;
#endif
} else {
curbuf->b_mtime = 0;
@@ -2473,7 +2473,6 @@ buf_write (
int overwriting; /* TRUE if writing over original */
int no_eol = FALSE; /* no end-of-line written */
int device = FALSE; /* writing to a device */
- struct stat st_old;
int prev_got_int = got_int;
bool file_readonly = false; /* overwritten file is read-only */
static char *err_readonly =
@@ -2774,15 +2773,14 @@ buf_write (
* Get information about original file (if there is one).
*/
#if defined(UNIX)
- st_old.st_dev = 0;
- st_old.st_ino = 0;
perm = -1;
- if (mch_stat((char *)fname, &st_old) < 0)
+ FileInfo file_info_old;
+ if (!os_get_file_info((char *)fname, &file_info_old)) {
newfile = TRUE;
- else {
- perm = st_old.st_mode;
- if (!S_ISREG(st_old.st_mode)) { /* not a file */
- if (S_ISDIR(st_old.st_mode)) {
+ } else {
+ perm = file_info_old.stat.st_mode;
+ if (!S_ISREG(file_info_old.stat.st_mode)) { /* not a file */
+ if (S_ISDIR(file_info_old.stat.st_mode)) {
errnum = (char_u *)"E502: ";
errmsg = (char_u *)_("is a directory");
goto fail;
@@ -2822,8 +2820,10 @@ buf_write (
errmsg = (char_u *)_("is a directory");
goto fail;
}
- if (overwriting)
- (void)mch_stat((char *)fname, &st_old);
+ if (overwriting) {
+ os_get_file_info((char *)fname, &file_info_old);
+ }
+
}
#endif /* !UNIX */
@@ -2849,7 +2849,7 @@ buf_write (
* Check if the timestamp hasn't changed since reading the file.
*/
if (overwriting) {
- retval = check_mtime(buf, &st_old);
+ retval = check_mtime(buf, &file_info_old);
if (retval == FAIL)
goto fail;
}
@@ -2890,14 +2890,11 @@ buf_write (
* off. This helps when editing large files on almost-full disks.
*/
if (!(append && *p_pm == NUL) && !filtering && perm >= 0 && dobackup) {
-#if defined(UNIX) || defined(WIN32)
- struct stat st;
-#endif
+ FileInfo file_info;
- if ((bkc_flags & BKC_YES) || append) /* "yes" */
+ if ((bkc_flags & BKC_YES) || append) { /* "yes" */
backup_copy = TRUE;
-#if defined(UNIX) || defined(WIN32)
- else if ((bkc_flags & BKC_AUTO)) { /* "auto" */
+ } else if ((bkc_flags & BKC_AUTO)) { /* "auto" */
int i;
# ifdef UNIX
@@ -2908,18 +2905,16 @@ buf_write (
* - we don't have write permission in the directory
* - we can't set the owner/group of the new file
*/
- if (st_old.st_nlink > 1
- || mch_lstat((char *)fname, &st) < 0
- || st.st_dev != st_old.st_dev
- || st.st_ino != st_old.st_ino
+ if (file_info_old.stat.st_nlink > 1
+ || !os_get_file_info_link((char *)fname, &file_info)
+ || !os_file_info_id_equal(&file_info, &file_info_old)
# ifndef HAVE_FCHOWN
- || st.st_uid != st_old.st_uid
- || st.st_gid != st_old.st_gid
+ || file_info.stat.st_uid != file_info_old.stat.st_uid
+ || file_info.stat.st_gid != file_info_old.stat.st_gid
# endif
- )
+ ) {
backup_copy = TRUE;
- else
-# else
+ } else
# endif
{
/*
@@ -2931,8 +2926,9 @@ buf_write (
STRCPY(IObuff, fname);
for (i = 4913;; i += 123) {
sprintf((char *)path_tail(IObuff), "%d", i);
- if (mch_lstat((char *)IObuff, &st) < 0)
+ if (!os_get_file_info_link((char *)IObuff, &file_info)) {
break;
+ }
}
fd = mch_open((char *)IObuff,
O_CREAT|O_WRONLY|O_EXCL|O_NOFOLLOW, perm);
@@ -2941,13 +2937,14 @@ buf_write (
else {
# ifdef UNIX
# ifdef HAVE_FCHOWN
- ignored = fchown(fd, st_old.st_uid, st_old.st_gid);
+ fchown(fd, file_info_old.stat.st_uid, file_info_old.stat.st_gid);
# endif
- if (mch_stat((char *)IObuff, &st) < 0
- || st.st_uid != st_old.st_uid
- || st.st_gid != st_old.st_gid
- || (long)st.st_mode != perm)
+ if (!os_get_file_info((char *)IObuff, &file_info)
+ || file_info.stat.st_uid != file_info_old.stat.st_uid
+ || file_info.stat.st_gid != file_info_old.stat.st_gid
+ || (long)file_info.stat.st_mode != perm) {
backup_copy = TRUE;
+ }
# endif
/* Close the file before removing it, on MS-Windows we
* can't delete an open file. */
@@ -2962,27 +2959,25 @@ buf_write (
*/
if ((bkc_flags & BKC_BREAKSYMLINK) || (bkc_flags & BKC_BREAKHARDLINK)) {
# ifdef UNIX
- int lstat_res;
-
- lstat_res = mch_lstat((char *)fname, &st);
+ bool file_info_link_ok = os_get_file_info_link((char *)fname, &file_info);
/* Symlinks. */
if ((bkc_flags & BKC_BREAKSYMLINK)
- && lstat_res == 0
- && st.st_ino != st_old.st_ino)
+ && file_info_link_ok
+ && !os_file_info_id_equal(&file_info, &file_info_old)) {
backup_copy = FALSE;
+ }
/* Hardlinks. */
if ((bkc_flags & BKC_BREAKHARDLINK)
- && st_old.st_nlink > 1
- && (lstat_res != 0 || st.st_ino == st_old.st_ino))
+ && file_info_old.stat.st_nlink > 1
+ && (!file_info_link_ok
+ || os_file_info_id_equal(&file_info, &file_info_old))) {
backup_copy = FALSE;
-# else
+ }
# endif
}
-#endif
-
/* make sure we have a valid backup extension to use */
if (*p_bex == NUL)
backup_ext = (char_u *)".bak";
@@ -2994,7 +2989,6 @@ buf_write (
int bfd;
char_u *copybuf, *wp;
int some_error = FALSE;
- struct stat st_new;
char_u *dirp;
char_u *rootname;
@@ -3019,12 +3013,6 @@ buf_write (
*/
dirp = p_bdir;
while (*dirp) {
-#ifdef UNIX
- st_new.st_ino = 0;
- st_new.st_dev = 0;
- st_new.st_gid = 0;
-#endif
-
/*
* Isolate one directory name, using an entry in 'bdir'.
*/
@@ -3035,6 +3023,7 @@ buf_write (
goto nobackup;
}
+ FileInfo file_info_new;
{
/*
* Make backup file name.
@@ -3049,20 +3038,17 @@ buf_write (
/*
* Check if backup file already exists.
*/
- if (mch_stat((char *)backup, &st_new) >= 0) {
-#ifdef UNIX
+ if (os_get_file_info((char *)backup, &file_info_new)) {
/*
* Check if backup file is same as original file.
* May happen when modname() gave the same file back (e.g. silly
* link). If we don't check here, we either ruin the file when
* copying or erase it after writing.
*/
- if (st_new.st_dev == st_old.st_dev
- && st_new.st_ino == st_old.st_ino) {
+ if (os_file_info_id_equal(&file_info_new, &file_info_old)) {
free(backup);
backup = NULL; /* no backup file to delete */
}
-#endif
/*
* If we are not going to keep the backup file, don't
@@ -3076,8 +3062,9 @@ buf_write (
wp = backup;
*wp = 'z';
while (*wp > 'a'
- && mch_stat((char *)backup, &st_new) >= 0)
+ && os_get_file_info((char *)backup, &file_info_new)) {
--*wp;
+ }
/* They all exist??? Must be something wrong. */
if (*wp == 'a') {
free(backup);
@@ -3114,13 +3101,13 @@ buf_write (
* bits for the group same as the protection bits for
* others.
*/
- if (st_new.st_gid != st_old.st_gid
+ if (file_info_new.stat.st_gid != file_info_old.stat.st_gid
# ifdef HAVE_FCHOWN /* sequent-ptx lacks fchown() */
- && fchown(bfd, (uid_t)-1, st_old.st_gid) != 0
+ && fchown(bfd, (uid_t)-1, file_info_old.stat.st_gid) != 0
# endif
- )
- os_setperm(backup,
- (perm & 0707) | ((perm & 07) << 3));
+ ) {
+ os_setperm(backup, (perm & 0707) | ((perm & 07) << 3));
+ }
# ifdef HAVE_SELINUX
mch_copy_sec(fname, backup);
# endif
@@ -3155,7 +3142,9 @@ buf_write (
errmsg = (char_u *)_(
"E508: Can't read file for backup (add ! to override)");
#ifdef UNIX
- set_file_time(backup, st_old.st_atime, st_old.st_mtime);
+ set_file_time(backup,
+ file_info_old.stat.st_atim.tv_sec,
+ file_info_old.stat.st_mtim.tv_sec);
#endif
#ifdef HAVE_ACL
mch_set_acl(backup, acl);
@@ -3266,7 +3255,8 @@ nobackup:
#if defined(UNIX)
/* When using ":w!" and the file was read-only: make it writable */
- if (forceit && perm >= 0 && !(perm & 0200) && st_old.st_uid == getuid()
+ if (forceit && perm >= 0 && !(perm & 0200)
+ && file_info_old.stat.st_uid == getuid()
&& vim_strchr(p_cpo, CPO_FWRITE) == NULL) {
perm |= 0200;
(void)os_setperm(fname, perm);
@@ -3412,15 +3402,14 @@ nobackup:
*/
if (errmsg == NULL) {
#ifdef UNIX
- struct stat st;
+ FileInfo file_info;
/* Don't delete the file when it's a hard or symbolic link. */
- if ((!newfile && st_old.st_nlink > 1)
- || (mch_lstat((char *)fname, &st) == 0
- && (st.st_dev != st_old.st_dev
- || st.st_ino != st_old.st_ino)))
+ if ((!newfile && file_info_old.stat.st_nlink > 1)
+ || (os_get_file_info_link((char *)fname, &file_info)
+ && !os_file_info_id_equal(&file_info, &file_info_old))) {
errmsg = (char_u *)_("E166: Can't open linked file for writing");
- else
+ } else
#endif
{
errmsg = (char_u *)_("E212: Can't open file for writing");
@@ -3432,8 +3421,10 @@ nobackup:
if (!(perm & 0200))
made_writable = TRUE;
perm |= 0200;
- if (st_old.st_uid != getuid() || st_old.st_gid != getgid())
+ if (file_info_old.stat.st_uid != getuid()
+ || file_info_old.stat.st_gid != getgid()) {
perm &= 0777;
+ }
#endif
if (!append) /* don't remove when appending */
os_remove((char *)wfname);
@@ -3444,8 +3435,6 @@ nobackup:
restore_backup:
{
- struct stat st;
-
/*
* If we failed to open the file, we don't need a backup. Throw it
* away. If we moved or removed the original file try to put the
@@ -3460,11 +3449,13 @@ restore_backup:
* In that case we leave the copy around.
*/
/* If file does not exist, put the copy in its place */
- if (mch_stat((char *)fname, &st) < 0)
+ if (!os_file_exists(fname)) {
vim_rename(backup, fname);
+ }
/* if original file does exist throw away the copy */
- if (mch_stat((char *)fname, &st) >= 0)
+ if (os_file_exists(fname)) {
os_remove((char *)backup);
+ }
} else {
/* try to put the original file back */
vim_rename(backup, fname);
@@ -3472,8 +3463,9 @@ restore_backup:
}
/* if original file no longer exists give an extra warning */
- if (!newfile && mch_stat((char *)fname, &st) < 0)
+ if (!newfile && !os_file_exists(fname)) {
end = 0;
+ }
}
if (wfname != fname)
@@ -3649,14 +3641,14 @@ restore_backup:
* file. Get the new device and inode number. */
if (backup != NULL && !backup_copy) {
# ifdef HAVE_FCHOWN
- struct stat st;
/* don't change the owner when it's already OK, some systems remove
* permission or ACL stuff */
- if (mch_stat((char *)wfname, &st) < 0
- || st.st_uid != st_old.st_uid
- || st.st_gid != st_old.st_gid) {
- ignored = fchown(fd, st_old.st_uid, st_old.st_gid);
+ FileInfo file_info;
+ if (!os_get_file_info((char *)wfname, &file_info)
+ || file_info.stat.st_uid != file_info_old.stat.st_uid
+ || file_info.stat.st_gid != file_info_old.stat.st_gid) {
+ fchown(fd, file_info_old.stat.st_uid, file_info_old.stat.st_gid);
if (perm >= 0) /* set permission again, may have changed */
(void)os_setperm(wfname, perm);
}
@@ -3855,20 +3847,20 @@ restore_backup:
char *org = (char *)modname(fname, p_pm, FALSE);
if (backup != NULL) {
- struct stat st;
-
/*
* If the original file does not exist yet
* the current backup file becomes the original file
*/
if (org == NULL)
EMSG(_("E205: Patchmode: can't save original file"));
- else if (mch_stat(org, &st) < 0) {
+ else if (!os_file_exists((char_u *)org)) {
vim_rename(backup, (char_u *)org);
free(backup); /* don't delete the file */
backup = NULL;
#ifdef UNIX
- set_file_time((char_u *)org, st_old.st_atime, st_old.st_mtime);
+ set_file_time((char_u *)org,
+ file_info_old.stat.st_atim.tv_sec,
+ file_info_old.stat.st_mtim.tv_sec);
#endif
}
}
@@ -3961,8 +3953,8 @@ nofail:
/* Update the timestamp to avoid an "overwrite changed file"
* prompt when writing again. */
- if (mch_stat((char *)fname, &st_old) >= 0) {
- buf_store_time(buf, &st_old, fname);
+ if (os_get_file_info((char *)fname, &file_info_old)) {
+ buf_store_file_info(buf, &file_info_old, fname);
buf->b_mtime_read = buf->b_mtime;
}
}
@@ -4138,10 +4130,11 @@ static void msg_add_eol(void)
* The size isn't checked, because using a tool like "gzip" takes care of
* using the same timestamp but can't set the size.
*/
-static int check_mtime(buf_T *buf, struct stat *st)
+static int check_mtime(buf_T *buf, FileInfo *file_info)
{
if (buf->b_mtime_read != 0
- && time_differs((long)st->st_mtime, buf->b_mtime_read)) {
+ && time_differs((long)file_info->stat.st_mtim.tv_sec,
+ buf->b_mtime_read)) {
msg_scroll = TRUE; /* don't overwrite messages here */
msg_silent = 0; /* must give this prompt */
/* don't use emsg() here, don't want to flush the buffers */
@@ -4814,12 +4807,11 @@ int vim_rename(char_u *from, char_u *to)
int n;
char *errmsg = NULL;
char *buffer;
- struct stat st;
long perm;
#ifdef HAVE_ACL
vim_acl_T acl; /* ACL from original file */
#endif
- int use_tmp_file = FALSE;
+ bool use_tmp_file = false;
/*
* When the names are identical, there is nothing to do. When they refer
@@ -4828,30 +4820,25 @@ int vim_rename(char_u *from, char_u *to)
*/
if (fnamecmp(from, to) == 0) {
if (p_fic && STRCMP(path_tail(from), path_tail(to)) != 0)
- use_tmp_file = TRUE;
+ use_tmp_file = true;
else
return 0;
}
- /*
- * Fail if the "from" file doesn't exist. Avoids that "to" is deleted.
- */
- if (mch_stat((char *)from, &st) < 0)
+ // Fail if the "from" file doesn't exist. Avoids that "to" is deleted.
+ FileInfo from_info;
+ if (!os_get_file_info((char *)from, &from_info)) {
return -1;
+ }
-#ifdef UNIX
- {
- struct stat st_to;
-
- /* It's possible for the source and destination to be the same file.
- * This happens when "from" and "to" differ in case and are on a FAT32
- * filesystem. In that case go through a temp file name. */
- if (mch_stat((char *)to, &st_to) >= 0
- && st.st_dev == st_to.st_dev
- && st.st_ino == st_to.st_ino)
- use_tmp_file = TRUE;
+ // It's possible for the source and destination to be the same file.
+ // This happens when "from" and "to" differ in case and are on a FAT32
+ // filesystem. In that case go through a temp file name.
+ FileInfo to_info;
+ if (os_get_file_info((char *)to, &to_info)
+ && os_file_info_id_equal(&from_info, &to_info)) {
+ use_tmp_file = true;
}
-#endif
if (use_tmp_file) {
char_u tempname[MAXPATHL + 1];
@@ -5086,8 +5073,6 @@ buf_check_timestamp (
int focus /* called for GUI focus event */
)
{
- struct stat st;
- int stat_res;
int retval = 0;
char_u *path;
char_u *tbuf;
@@ -5114,27 +5099,25 @@ buf_check_timestamp (
)
return 0;
- if ( !(buf->b_flags & BF_NOTEDITED)
- && buf->b_mtime != 0
- && ((stat_res = mch_stat((char *)buf->b_ffname, &st)) < 0
- || time_differs((long)st.st_mtime, buf->b_mtime)
- || st.st_size != buf->b_orig_size
-#ifdef HAVE_ST_MODE
- || (int)st.st_mode != buf->b_orig_mode
-#else
- || os_getperm(buf->b_ffname) != buf->b_orig_mode
-#endif
- )) {
+ FileInfo file_info;
+ bool file_info_ok;
+ if (!(buf->b_flags & BF_NOTEDITED)
+ && buf->b_mtime != 0
+ && (!(file_info_ok = os_get_file_info((char *)buf->b_ffname, &file_info))
+ || time_differs((long)file_info.stat.st_mtim.tv_sec, buf->b_mtime)
+ || (int)file_info.stat.st_mode != buf->b_orig_mode
+ )) {
retval = 1;
/* set b_mtime to stop further warnings (e.g., when executing
* FileChangedShell autocmd) */
- if (stat_res < 0) {
+ if (!file_info_ok) {
buf->b_mtime = 0;
buf->b_orig_size = 0;
buf->b_orig_mode = 0;
- } else
- buf_store_time(buf, &st, buf->b_ffname);
+ } else {
+ buf_store_file_info(buf, &file_info, buf->b_ffname);
+ }
/* Don't do anything for a directory. Might contain the file
* explorer. */
@@ -5147,10 +5130,10 @@ buf_check_timestamp (
* was set, the global option value otherwise.
*/
else if ((buf->b_p_ar >= 0 ? buf->b_p_ar : p_ar)
- && !bufIsChanged(buf) && stat_res >= 0)
+ && !bufIsChanged(buf) && file_info_ok)
reload = TRUE;
else {
- if (stat_res < 0)
+ if (!file_info_ok)
reason = "deleted";
else if (bufIsChanged(buf))
reason = "conflict";
@@ -5435,15 +5418,12 @@ void buf_reload(buf_T *buf, int orig_mode)
/* Careful: autocommands may have made "buf" invalid! */
}
-void buf_store_time(buf_T *buf, struct stat *st, char_u *fname)
+// TODO(stefan991): remove unused parameter fname
+void buf_store_file_info(buf_T *buf, FileInfo *file_info, char_u *fname)
{
- buf->b_mtime = (long)st->st_mtime;
- buf->b_orig_size = st->st_size;
-#ifdef HAVE_ST_MODE
- buf->b_orig_mode = (int)st->st_mode;
-#else
- buf->b_orig_mode = os_getperm(fname);
-#endif
+ buf->b_mtime = (long)file_info->stat.st_mtim.tv_sec;
+ buf->b_orig_size = file_info->stat.st_size;
+ buf->b_orig_mode = (int)file_info->stat.st_mode;
}
/*
@@ -5527,9 +5507,6 @@ vim_tempname (
#ifdef TEMPDIRNAMES
static char *(tempdirs[]) = {TEMPDIRNAMES};
int i;
-# ifndef EEXIST
- struct stat st;
-# endif
/*
* This will create a directory for private use by this instance of Vim.
@@ -5580,7 +5557,7 @@ vim_tempname (
/* If mkdir() does not set errno to EEXIST, check for
* existing file here. There is a race condition then,
* although it's fail-safe. */
- if (mch_stat((char *)itmp, &st) >= 0)
+ if (os_file_exists(itmp))
continue;
# endif
# if defined(UNIX)