Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit bf0290c

Browse files
committed
Cleanup stat shims
* Provide explicit constants for interpreting file mode * Use extern "C" one function at a time * Rename FileStats to FileStatus to match POSIX language * Rename FileStatus to be more 1:1 with struct stat * Put parameters on their own lines in header
1 parent f09c828 commit bf0290c

File tree

5 files changed

+167
-93
lines changed

5 files changed

+167
-93
lines changed

src/Common/src/Interop/Unix/System.Native/Interop.Stat.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ internal static partial class Interop
88
{
99
internal static partial class System
1010
{
11-
internal struct FileStats
11+
internal struct FileStatus
1212
{
13-
private FileStatsFlags Flags;
13+
internal FileStatusFlags Flags;
1414
internal int Mode;
1515
internal int Uid;
1616
internal int Gid;
@@ -32,19 +32,19 @@ internal static class FileTypes
3232
}
3333

3434
[Flags]
35-
internal enum FileStatsFlags
35+
internal enum FileStatusFlags
3636
{
3737
None = 0,
3838
HasCreationTime = 1,
3939
}
4040

4141
[DllImport(Libraries.SystemNative, SetLastError = true)]
42-
internal static extern int FStat(int fileDescriptor, out FileStats output);
42+
internal static extern int FStat(int fileDescriptor, out FileStatus output);
4343

4444
[DllImport(Libraries.SystemNative, SetLastError = true)]
45-
internal static extern int Stat(string path, out FileStats output);
45+
internal static extern int Stat(string path, out FileStatus output);
4646

4747
[DllImport(Libraries.SystemNative, SetLastError = true)]
48-
internal static extern int LStat(string path, out FileStats output);
48+
internal static extern int LStat(string path, out FileStatus output);
4949
}
5050
}

src/Native/System.Native/pal_stat.cpp

Lines changed: 68 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
//
21
// Copyright (c) Microsoft. All rights reserved.
32
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
4-
//
53

64
#include "../config.h"
75
#include "pal_stat.h"
@@ -17,61 +15,89 @@
1715
# define lstat_ lstat
1816
#endif
1917

20-
static void ConvertFileStats(const struct stat_& src, FileStats* dst)
18+
// These numeric values are specified by POSIX.
19+
// Validate that our definitions match.
20+
static_assert(PAL_S_IRWXU == S_IRWXU, "");
21+
static_assert(PAL_S_IRUSR == S_IRUSR, "");
22+
static_assert(PAL_S_IWUSR == S_IWUSR, "");
23+
static_assert(PAL_S_IXUSR == S_IXUSR, "");
24+
static_assert(PAL_S_IRWXG == S_IRWXG, "");
25+
static_assert(PAL_S_IRGRP == S_IRGRP, "");
26+
static_assert(PAL_S_IWGRP == S_IWGRP, "");
27+
static_assert(PAL_S_IXGRP == S_IXGRP, "");
28+
static_assert(PAL_S_IRWXO == S_IRWXO, "");
29+
static_assert(PAL_S_IROTH == S_IROTH, "");
30+
static_assert(PAL_S_IWOTH == S_IWOTH, "");
31+
static_assert(PAL_S_IXOTH == S_IXOTH, "");
32+
static_assert(PAL_S_ISUID == S_ISUID, "");
33+
static_assert(PAL_S_ISGID == S_ISGID, "");
34+
35+
// These numeric values are not specified by POSIX, but the values
36+
// are common to our current targets. If these static asserts fail,
37+
// ConvertFileStatus needs to be updated to twiddle mode bits
38+
// accordingly.
39+
static_assert(PAL_S_IFMT == S_IFMT, "");
40+
static_assert(PAL_S_IFIFO == S_IFIFO, "");
41+
static_assert(PAL_S_IFCHR == S_IFCHR, "");
42+
static_assert(PAL_S_IFDIR == S_IFDIR, "");
43+
static_assert(PAL_S_IFREG == S_IFREG, "");
44+
static_assert(PAL_S_IFLNK == S_IFLNK, "");
45+
46+
static void ConvertFileStatus(const struct stat_& src, FileStatus* dst)
2147
{
22-
dst->Flags = FILESTATS_FLAGS_NONE;
23-
dst->Mode = src.st_mode;
24-
dst->Uid = src.st_uid;
25-
dst->Gid = src.st_gid;
26-
dst->Size = src.st_size;
27-
dst->AccessTime = src.st_atime;
28-
dst->ModificationTime = src.st_mtime;
29-
dst->StatusChangeTime = src.st_ctime;
48+
dst->Flags = FILESTATUS_FLAGS_NONE;
49+
dst->Mode = src.st_mode;
50+
dst->Uid = src.st_uid;
51+
dst->Gid = src.st_gid;
52+
dst->Size = src.st_size;
53+
dst->ATime = src.st_atime;
54+
dst->MTime = src.st_mtime;
55+
dst->CTime = src.st_ctime;
3056

3157
#if HAVE_STAT_BIRTHTIME
32-
dst->CreationTime = src.st_birthtime;
33-
dst->Flags |= FILESTATS_FLAGS_HAS_CREATION_TIME;
58+
dst->BirthTime = src.st_birthtime;
59+
dst->Flags |= FILESTATUSFLAGS_HAS_BIRTHTIME;
3460
#endif
3561
}
3662

3763
extern "C"
64+
int32_t Stat(const char* path, FileStatus* output)
3865
{
39-
int32_t Stat(const char* path, struct FileStats* output)
40-
{
41-
struct stat_ result;
42-
int ret = stat_(path, &result);
43-
44-
if (ret == 0)
45-
{
46-
ConvertFileStats(result, output);
47-
}
66+
struct stat_ result;
67+
int ret = stat_(path, &result);
4868

49-
return ret; // TODO: errno conversion
50-
}
69+
if (ret == 0)
70+
{
71+
ConvertFileStatus(result, output);
72+
}
5173

52-
int32_t FStat(int32_t fileDescriptor, FileStats* output)
53-
{
54-
struct stat_ result;
55-
int ret = fstat_(fileDescriptor, &result);
74+
return ret;
75+
}
5676

57-
if (ret == 0)
58-
{
59-
ConvertFileStats(result, output);
60-
}
77+
extern "C"
78+
int32_t FStat(int32_t fileDescriptor, FileStatus* output)
79+
{
80+
struct stat_ result;
81+
int ret = fstat_(fileDescriptor, &result);
6182

62-
return ret; // TODO: errno conversion
83+
if (ret == 0)
84+
{
85+
ConvertFileStatus(result, output);
6386
}
6487

65-
int32_t LStat(const char* path, struct FileStats* output)
66-
{
67-
struct stat_ result;
68-
int ret = lstat_(path, &result);
88+
return ret;
89+
}
6990

70-
if (ret == 0)
71-
{
72-
ConvertFileStats(result, output);
73-
}
91+
extern "C"
92+
int32_t LStat(const char* path, FileStatus* output)
93+
{
94+
struct stat_ result;
95+
int ret = lstat_(path, &result);
7496

75-
return ret; // TODO: errno conversion
97+
if (ret == 0)
98+
{
99+
ConvertFileStatus(result, output);
76100
}
101+
102+
return ret;
77103
}

src/Native/System.Native/pal_stat.h

Lines changed: 89 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -5,46 +5,94 @@
55

66
#include <stdint.h>
77

8-
extern "C"
8+
/**
9+
* File status returned by Stat or FStat.
10+
*/
11+
struct FileStatus
12+
{
13+
int32_t Flags; // flags for testing if some members are present (see FileStatusFlags)
14+
int32_t Mode; // file mode (see S_I* constants above for bit values)
15+
int32_t Uid; // user ID of owner
16+
int32_t Gid; // group ID of owner
17+
int64_t Size; // total size, in bytes
18+
int64_t ATime; // time of last access
19+
int64_t MTime; // time of last modification
20+
int64_t CTime; // time of last status change
21+
int64_t BirthTime; // time the file was created
22+
};
23+
24+
/**
25+
* Constants for interpreting the permissions encoded in FileStatus.Mode.
26+
* Both the names (without the PAL_ prefix and numeric values are specified by POSIX.1.2008
27+
*/
28+
enum
929
{
10-
struct FileStats
11-
{
12-
int32_t Flags; // flags for testing if some members are present (see values below)
13-
int32_t Mode; // protection
14-
int32_t Uid; // user ID of owner
15-
int32_t Gid; // group ID of owner
16-
int64_t Size; // total size, in bytes
17-
int64_t AccessTime; // time of last access (atime)
18-
int64_t ModificationTime; // time of last modification (mtime)
19-
int64_t StatusChangeTime; // time of last status change (ctime)
20-
int64_t CreationTime; // time the file was created (birthtime)
21-
};
22-
23-
enum
24-
{
25-
FILESTATS_FLAGS_NONE = 0,
26-
FILESTATS_FLAGS_HAS_CREATION_TIME = 1,
27-
};
28-
29-
/**
30-
* Get file stats from a decriptor. Implemented as shim to fstat(2).
31-
*
32-
* Returns 0 for success, -1 for failure. Sets errno on failure.
33-
*/
34-
int32_t FStat(int32_t fileDescriptor, FileStats* output);
35-
36-
/**
37-
* Get file stats from a full path. Implemented as shim to stat(2).
38-
*
39-
* Returns 0 for success, -1 for failure. Sets errno on failure.
40-
*/
41-
int32_t Stat(const char* path, FileStats* output);
42-
43-
/**
44-
* Get file stats from a full path. Implemented as shim to lstat(2).
45-
*
46-
* Returns 0 for success, -1 for failure. Sets errno on failure.
47-
*/
48-
int32_t LStat(const char* path, FileStats* output);
49-
}
30+
PAL_S_IRWXU = 00700, // Read, write, execute/search by owner.
31+
PAL_S_IRUSR = 00400, // Read permission, owner.
32+
PAL_S_IWUSR = 00200, // Write permission, owner.
33+
PAL_S_IXUSR = 00100, // Execute/search permission, owner.
34+
PAL_S_IRWXG = 00070, // Read, write, execute/search by group.
35+
PAL_S_IRGRP = 00040, // Read permission, group.
36+
PAL_S_IWGRP = 00020, // Write permission, group.
37+
PAL_S_IXGRP = 00010, // Execute/search permission, group.
38+
PAL_S_IRWXO = 00007, // Read, write, execute/search by others.
39+
PAL_S_IROTH = 00004, // Read permission, others.
40+
PAL_S_IWOTH = 00002, // Write permission, others.
41+
PAL_S_IXOTH = 00001, // Execute/search permission, others.
42+
PAL_S_ISUID = 04000, // Set-user-ID on execution.
43+
PAL_S_ISGID = 02000, // Set-group-ID on execution.
44+
};
5045

46+
/**
47+
* Constants for interpreting the permissions encoded in FileStatus.Mode
48+
* Only the names (without the PAL_ prefix) are specified by POSIX.1.2008.
49+
* The values chosen below are in common use, but not guaranteed.
50+
*/
51+
enum
52+
{
53+
PAL_S_IFMT = 0xF000, // Type of file (apply as mask to FileStatus.Mode and one of S_IF*)
54+
PAL_S_IFIFO = 0x1000, // FIFO (named pipe)
55+
PAL_S_IFCHR = 0x2000, // Character special
56+
PAL_S_IFDIR = 0x4000, // Directory
57+
PAL_S_IFREG = 0x8000, // Regular file
58+
PAL_S_IFLNK = 0xA000, // Symbolic link
59+
};
60+
61+
/**
62+
* Constants for interpreting FileStatus.Flags.
63+
*/
64+
enum
65+
{
66+
FILESTATUS_FLAGS_NONE = 0,
67+
FILESTATUS_FLAGS_HAS_BIRTHTIME = 1,
68+
};
69+
70+
/**
71+
* Get file status from a decriptor. Implemented as shim to fstat(2).
72+
*
73+
* Returns 0 for success, -1 for failure. Sets errno on failure.
74+
*/
75+
extern "C"
76+
int32_t FStat(
77+
int32_t fileDescriptor,
78+
FileStatus* output);
79+
80+
/**
81+
* Get file status from a full path. Implemented as shim to stat(2).
82+
*
83+
* Returns 0 for success, -1 for failure. Sets errno on failure.
84+
*/
85+
extern "C"
86+
int32_t Stat(
87+
const char* path,
88+
FileStatus* output);
89+
90+
/**
91+
* Get file stats from a full path. Implemented as shim to lstat(2).
92+
*
93+
* Returns 0 for success, -1 for failure. Sets errno on failure.
94+
*/
95+
extern "C"
96+
int32_t LStat(
97+
const char* path,
98+
FileStatus* output);

src/System.Console/src/System/ConsolePal.Unix.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ internal UnixConsoleStream(string devPath, FileAccess access)
378378
try
379379
{
380380
_handle.DangerousAddRef(ref gotFd);
381-
Interop.System.FileStats buf;
381+
Interop.System.FileStatus buf;
382382
_handleType =
383383
Interop.System.FStat((int)_handle.DangerousGetHandle(), out buf) == 0 ?
384384
(buf.Mode & Interop.System.FileTypes.S_IFMT) :

src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Linux.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -300,9 +300,9 @@ private WatchedDirectory AddDirectoryWatchUnlocked(WatchedDirectory parent, stri
300300
string fullPath = parent != null ? parent.GetPath(false, directoryName) : directoryName;
301301

302302
// inotify_add_watch will fail if this is a symlink, so check that we didn't get a symlink
303-
Interop.System.FileStats stats = default(Interop.System.FileStats);
304-
if ((Interop.System.LStat(fullPath, out stats) == 0) &&
305-
((stats.Mode & (uint)Interop.System.FileTypes.S_IFMT) == Interop.System.FileTypes.S_IFLNK))
303+
Interop.System.FileStatus status = default(Interop.System.FileStatus);
304+
if ((Interop.System.LStat(fullPath, out status) == 0) &&
305+
((status.Mode & (uint)Interop.System.FileTypes.S_IFMT) == Interop.System.FileTypes.S_IFLNK))
306306
{
307307
return null;
308308
}

0 commit comments

Comments
 (0)