FileID: implement FileID struct

`FileID` should encapsulate `st_dev` and `st_ino`. It is a new abstraction
used to check if two files are the same. `FileID`s will be embeded inside
other struts like `buf_t` or `ff_visited_T`, where a full `FileInfo` would be
to big.
This commit is contained in:
Stefan Hoffmann 2014-05-10 11:49:25 +02:00
parent 8a85b37253
commit 4a22fb06b9
4 changed files with 152 additions and 7 deletions

View File

@ -345,8 +345,69 @@ bool os_get_file_info_fd(int file_descriptor, FileInfo *file_info)
/// 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((char_u *)path, &statbuf) == OK) {
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;
}

19
src/nvim/os/fs_defs.h Normal file
View File

@ -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

View File

@ -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"

View File

@ -314,6 +314,12 @@ describe 'fs function', ->
is_file_info_filled = (file_info) ->
file_info[0].stat.st_ino > 0 and file_info[0].stat.st_dev > 0
file_id_new = () ->
file_info = ffi.new 'FileID[1]'
file_info[0].inode = 0
file_info[0].device_id = 0
file_info
describe 'os_get_file_info', ->
it 'returns false if given a non-existing file', ->
file_info = file_info_new!
@ -392,3 +398,67 @@ describe 'fs function', ->
assert.is_true (fs.os_get_file_info path_2, file_info_2)
assert.is_true (fs.os_file_info_id_equal file_info_1, file_info_2)
describe 'os_file_info_get_id', ->
it 'extracts ino/dev from file_info into file_id', ->
file_info = file_info_new!
file_id = file_id_new!
path = 'unit-test-directory/test.file'
assert.is_true (fs.os_get_file_info path, file_info)
fs.os_file_info_get_id(file_info, file_id)
eq file_info[0].stat.st_ino, file_id[0].inode
eq file_info[0].stat.st_dev, file_id[0].device_id
describe 'os_file_info_get_inode', ->
it 'returns the inode from file_info', ->
file_info = file_info_new!
path = 'unit-test-directory/test.file'
assert.is_true (fs.os_get_file_info path, file_info)
inode = fs.os_file_info_get_inode(file_info)
eq file_info[0].stat.st_ino, inode
describe 'os_get_file_id', ->
it 'returns false if given an non-existing file', ->
file_id = file_id_new!
assert.is_false (fs.os_get_file_id '/non-existent', file_id)
it 'returns true if given an existing file and fills file_id', ->
file_id = file_id_new!
path = 'unit-test-directory/test.file'
assert.is_true (fs.os_get_file_id path, file_id)
assert.is_true 0 < file_id[0].inode
assert.is_true 0 < file_id[0].device_id
describe 'os_file_id_equal', ->
it 'returns true if two FileIDs are equal', ->
file_id = file_id_new!
path = 'unit-test-directory/test.file'
assert.is_true (fs.os_get_file_id path, file_id)
assert.is_true (fs.os_file_id_equal file_id, file_id)
it 'returns false if two FileIDs are not equal', ->
file_id_1 = file_id_new!
file_id_2 = file_id_new!
path_1 = 'unit-test-directory/test.file'
path_2 = 'unit-test-directory/test_2.file'
assert.is_true (fs.os_get_file_id path_1, file_id_1)
assert.is_true (fs.os_get_file_id path_2, file_id_2)
assert.is_false (fs.os_file_id_equal file_id_1, file_id_2)
describe 'os_file_id_equal_file_info', ->
it 'returns true if file_id and file_info represent the same file', ->
file_id = file_id_new!
file_info = file_info_new!
path = 'unit-test-directory/test.file'
assert.is_true (fs.os_get_file_id path, file_id)
assert.is_true (fs.os_get_file_info path, file_info)
assert.is_true (fs.os_file_id_equal_file_info file_id, file_info)
it 'returns false if file_id and file_info represent different files',->
file_id = file_id_new!
file_info = file_info_new!
path_1 = 'unit-test-directory/test.file'
path_2 = 'unit-test-directory/test_2.file'
assert.is_true (fs.os_get_file_id path_1, file_id)
assert.is_true (fs.os_get_file_info path_2, file_info)
assert.is_false (fs.os_file_id_equal_file_info file_id, file_info)