Commit d87cd06296
lib/std/fs/file.zig
@@ -29,6 +29,18 @@ pub const File = struct {
pub const Mode = os.mode_t;
pub const INode = os.ino_t;
+ pub const Kind = enum {
+ BlockDevice,
+ CharacterDevice,
+ Directory,
+ NamedPipe,
+ SymLink,
+ File,
+ UnixDomainSocket,
+ Whiteout,
+ Unknown,
+ };
+
pub const default_mode = switch (builtin.os.tag) {
.windows => 0,
.wasi => 0,
@@ -219,13 +231,14 @@ pub const File = struct {
/// unique across time, as some file systems may reuse an inode after its file has been deleted.
/// Some systems may change the inode of a file over time.
///
- /// On Linux, the inode _is_ structure that stores the metadata, and the inode _number_ is what
+ /// On Linux, the inode is a structure that stores the metadata, and the inode _number_ is what
/// you see here: the index number of the inode.
///
/// The FileIndex on Windows is similar. It is a number for a file that is unique to each filesystem.
inode: INode,
size: u64,
mode: Mode,
+ kind: Kind,
/// Access time in nanoseconds, relative to UTC 1970-01-01.
atime: i128,
@@ -254,6 +267,7 @@ pub const File = struct {
.inode = info.InternalInformation.IndexNumber,
.size = @bitCast(u64, info.StandardInformation.EndOfFile),
.mode = 0,
+ .kind = if (info.StandardInformation.Directory == 0) .File else .Directory,
.atime = windows.fromSysTime(info.BasicInformation.LastAccessTime),
.mtime = windows.fromSysTime(info.BasicInformation.LastWriteTime),
.ctime = windows.fromSysTime(info.BasicInformation.CreationTime),
@@ -268,6 +282,16 @@ pub const File = struct {
.inode = st.ino,
.size = @bitCast(u64, st.size),
.mode = st.mode,
+ .kind = switch (st.mode & os.S_IFMT) {
+ os.S_IFBLK => .BlockDevice,
+ os.S_IFCHR => .CharacterDevice,
+ os.S_IFDIR => .Directory,
+ os.S_IFIFO => .NamedPipe,
+ os.S_IFLNK => .SymLink,
+ os.S_IFREG => .File,
+ os.S_IFSOCK => .UnixDomainSocket,
+ else => .Unknown,
+ },
.atime = @as(i128, atime.tv_sec) * std.time.ns_per_s + atime.tv_nsec,
.mtime = @as(i128, mtime.tv_sec) * std.time.ns_per_s + mtime.tv_nsec,
.ctime = @as(i128, ctime.tv_sec) * std.time.ns_per_s + ctime.tv_nsec,
lib/std/fs.zig
@@ -261,17 +261,7 @@ pub const Dir = struct {
name: []const u8,
kind: Kind,
- pub const Kind = enum {
- BlockDevice,
- CharacterDevice,
- Directory,
- NamedPipe,
- SymLink,
- File,
- UnixDomainSocket,
- Whiteout,
- Unknown,
- };
+ pub const Kind = File.Kind;
};
const IteratorError = error{AccessDenied} || os.UnexpectedError;
src-self-hosted/main.zig
@@ -670,11 +670,12 @@ const FmtError = error{
ReadOnlyFileSystem,
LinkQuotaExceeded,
FileBusy,
+ EndOfStream,
} || fs.File.OpenError;
fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool) FmtError!void {
// get the real path here to avoid Windows failing on relative file paths with . or .. in them
- var real_path = fs.realpathAlloc(fmt.gpa, file_path) catch |err| {
+ const real_path = fs.realpathAlloc(fmt.gpa, file_path) catch |err| {
std.debug.warn("unable to open '{}': {}\n", .{ file_path, err });
fmt.any_error = true;
return;
@@ -684,47 +685,65 @@ fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool) FmtError!void {
if (fmt.seen.exists(real_path)) return;
try fmt.seen.put(real_path);
- const source_file = fs.cwd().openFile(real_path, .{}) catch |err| {
- std.debug.warn("unable to open '{}': {}\n", .{ file_path, err });
- fmt.any_error = true;
- return;
+ fmtPathFile(fmt, file_path, check_mode, real_path) catch |err| switch (err) {
+ error.IsDir, error.AccessDenied => return fmtPathDir(fmt, file_path, check_mode, real_path),
+ else => {
+ std.debug.warn("unable to format '{}': {}\n", .{ file_path, err });
+ fmt.any_error = true;
+ return;
+ },
};
- defer source_file.close();
+}
- const stat = source_file.stat() catch |err| {
- std.debug.warn("unable to stat '{}': {}\n", .{ file_path, err });
- fmt.any_error = true;
- return;
- };
+fn fmtPathDir(fmt: *Fmt, file_path: []const u8, check_mode: bool, parent_real_path: []const u8) FmtError!void {
+ var dir = try fs.cwd().openDir(parent_real_path, .{ .iterate = true });
+ defer dir.close();
+
+ var dir_it = dir.iterate();
+ while (try dir_it.next()) |entry| {
+ const is_dir = entry.kind == .Directory;
+ if (is_dir or mem.endsWith(u8, entry.name, ".zig")) {
+ const full_path = try fs.path.join(fmt.gpa, &[_][]const u8{ file_path, entry.name });
+ const sub_real_path = fs.realpathAlloc(fmt.gpa, full_path) catch |err| {
+ std.debug.warn("unable to open '{}': {}\n", .{ file_path, err });
+ fmt.any_error = true;
+ return;
+ };
+ defer fmt.gpa.free(sub_real_path);
+
+ if (fmt.seen.exists(sub_real_path)) return;
+ try fmt.seen.put(sub_real_path);
+
+ if (is_dir) {
+ try fmtPathDir(fmt, full_path, check_mode, sub_real_path);
+ } else {
+ fmtPathFile(fmt, full_path, check_mode, sub_real_path) catch |err| {
+ std.debug.warn("unable to format '{}': {}\n", .{ full_path, err });
+ fmt.any_error = true;
+ return;
+ };
+ }
+ }
+ }
+}
- const source_code = source_file.readAllAlloc(fmt.gpa, stat.size, max_src_size) catch |err| switch (err) {
- error.IsDir => {
- var dir = try fs.cwd().openDir(file_path, .{ .iterate = true });
- defer dir.close();
+fn fmtPathFile(fmt: *Fmt, file_path: []const u8, check_mode: bool, real_path: []const u8) FmtError!void {
+ const source_file = try fs.cwd().openFile(real_path, .{});
+ defer source_file.close();
- var dir_it = dir.iterate();
+ const stat = try source_file.stat();
- while (try dir_it.next()) |entry| {
- if (entry.kind == .Directory or mem.endsWith(u8, entry.name, ".zig")) {
- const full_path = try fs.path.join(fmt.gpa, &[_][]const u8{ file_path, entry.name });
- try fmtPath(fmt, full_path, check_mode);
- }
- }
- return;
- },
- else => {
- std.debug.warn("unable to read '{}': {}\n", .{ file_path, err });
- fmt.any_error = true;
- return;
- },
+ if (stat.kind == .Directory)
+ return error.IsDir;
+
+ const source_code = source_file.readAllAlloc(fmt.gpa, stat.size, max_src_size) catch |err| switch (err) {
+ error.ConnectionResetByPeer => unreachable,
+ error.ConnectionTimedOut => unreachable,
+ else => |e| return e,
};
defer fmt.gpa.free(source_code);
- const tree = std.zig.parse(fmt.gpa, source_code) catch |err| {
- std.debug.warn("error parsing file '{}': {}\n", .{ file_path, err });
- fmt.any_error = true;
- return;
- };
+ const tree = try std.zig.parse(fmt.gpa, source_code);
defer tree.deinit();
for (tree.errors) |parse_error| {