mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-27 05:13:10 +00:00
parent
0705446e6e
commit
d19e5508d7
3 changed files with 52 additions and 7 deletions
13
src/libc.c
13
src/libc.c
|
@ -1,4 +1,5 @@
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <paths.h>
|
#include <paths.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
@ -6,6 +7,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
@ -198,3 +200,14 @@ bool C_portable_readdir(DIR* dirp, const char** d_name, size_t* d_name_len, uint
|
||||||
*d_type = dent->d_type;
|
*d_type = dent->d_type;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool C_portable_fstatat(int dirfd, const char* file, int flag, uint64_t* st_dev, uint64_t* st_ino, mode_t* st_mode) {
|
||||||
|
struct stat buf;
|
||||||
|
if (fstatat(dirfd, file, &buf, flag) == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*st_dev = buf.st_dev;
|
||||||
|
*st_ino = buf.st_ino;
|
||||||
|
*st_mode = buf.st_mode;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
35
src/libc.rs
35
src/libc.rs
|
@ -1,4 +1,4 @@
|
||||||
use std::sync::atomic::AtomicPtr;
|
use std::{ffi::CStr, sync::atomic::AtomicPtr};
|
||||||
|
|
||||||
use libc::{c_char, c_int};
|
use libc::{c_char, c_int};
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
@ -79,3 +79,36 @@ extern "C" {
|
||||||
d_type: *mut u8,
|
d_type: *mut u8,
|
||||||
) -> bool;
|
) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn portable_fstatat(
|
||||||
|
dirfd: c_int,
|
||||||
|
file: &CStr,
|
||||||
|
flag: c_int,
|
||||||
|
) -> Option<(u64, u64, libc::mode_t)> {
|
||||||
|
let mut st_dev = unsafe { std::mem::zeroed() };
|
||||||
|
let mut st_ino = unsafe { std::mem::zeroed() };
|
||||||
|
let mut st_mode = unsafe { std::mem::zeroed() };
|
||||||
|
if !unsafe {
|
||||||
|
C_portable_fstatat(
|
||||||
|
dirfd,
|
||||||
|
file.as_ptr(),
|
||||||
|
flag,
|
||||||
|
&mut st_dev,
|
||||||
|
&mut st_ino,
|
||||||
|
&mut st_mode,
|
||||||
|
)
|
||||||
|
} {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some((st_dev, st_ino, st_mode))
|
||||||
|
}
|
||||||
|
extern "C" {
|
||||||
|
fn C_portable_fstatat(
|
||||||
|
dirfd: c_int,
|
||||||
|
file: *const c_char,
|
||||||
|
flag: c_int,
|
||||||
|
st_dev: *mut u64,
|
||||||
|
st_ino: *mut u64,
|
||||||
|
st_mode: *mut libc::mode_t,
|
||||||
|
) -> bool;
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use super::wopendir;
|
use super::wopendir;
|
||||||
use crate::common::{cstr2wcstring, wcs2zstring};
|
use crate::common::{cstr2wcstring, wcs2zstring};
|
||||||
use crate::libc::portable_readdir;
|
use crate::libc::{portable_fstatat, portable_readdir};
|
||||||
use crate::wchar::{wstr, WString};
|
use crate::wchar::{wstr, WString};
|
||||||
use crate::wutil::DevInode;
|
use crate::wutil::DevInode;
|
||||||
use libc::{
|
use libc::{
|
||||||
|
@ -104,14 +104,13 @@ impl DirEntry {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let narrow = wcs2zstring(&self.name);
|
let narrow = wcs2zstring(&self.name);
|
||||||
let mut s: libc::stat = unsafe { std::mem::zeroed() };
|
if let Some((st_dev, st_ino, st_mode)) = portable_fstatat(fd, &narrow, 0) {
|
||||||
if unsafe { libc::fstatat(fd, narrow.as_ptr(), &mut s, 0) } == 0 {
|
|
||||||
let dev_inode = DevInode {
|
let dev_inode = DevInode {
|
||||||
device: s.st_dev as u64,
|
device: st_dev,
|
||||||
inode: s.st_ino as u64,
|
inode: st_ino,
|
||||||
};
|
};
|
||||||
self.dev_inode.set(Some(dev_inode));
|
self.dev_inode.set(Some(dev_inode));
|
||||||
self.typ.set(stat_mode_to_entry_type(s.st_mode));
|
self.typ.set(stat_mode_to_entry_type(st_mode));
|
||||||
} else {
|
} else {
|
||||||
match errno::errno().0 {
|
match errno::errno().0 {
|
||||||
ELOOP => {
|
ELOOP => {
|
||||||
|
|
Loading…
Reference in a new issue