forked from sirodcar/commonx
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBetterAdapters.pas
More file actions
167 lines (152 loc) · 4.39 KB
/
BetterAdapters.pas
File metadata and controls
167 lines (152 loc) · 4.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
unit BetterAdapters;
interface
uses
{$IFDEF MSWINDoWS}
windows,
{$ENDIF}
{$IFDEF POSIX}
Posix.Dlfcn, Posix.Fcntl, Posix.SysStat, Posix.SysTime, Posix.SysTypes,
{$ENDIF}
types,
sysutils;
function BetterFileOpen(const FileName: string; Mode: LongWord; Rights: cardinal; flags: cardinal): THandle;
function BetterFileCreate(const FileName: string; Mode: LongWord; Rights: cardinal; flags: cardinal): THandle;
implementation
uses
{$IFDEF POSIX}
{$IFNDEF ANDROID}
Posix.Iconv,
{$ENDIF}
Posix.Base, Posix.Dirent, Posix.Errno, Posix.Fnmatch,
Posix.Langinfo, Posix.Locale, Posix.Pthread, Posix.Stdio, Posix.Stdlib,
Posix.String_, Posix.SysSysctl, Posix.Time, Posix.Unistd, Posix.Utime,
Posix.Wordexp, Posix.Pwd, Posix.Signal,
{$ENDIF POSIX}
stringx;
function BetterFileOpen(const FileName: string; Mode: LongWord; Rights: cardinal; flags: cardinal): THandle;
{$IFDEF MSWINDOWS}
const
AccessMode: array[0..2] of LongWord = (
GENERIC_READ,
GENERIC_WRITE,
GENERIC_READ or GENERIC_WRITE);
ShareMode: array[0..4] of LongWord = (
0,
0,
FILE_SHARE_READ,
FILE_SHARE_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE);
begin
Result := INVALID_HANDLE_VALUE;
if ((Mode and 3) <= fmOpenReadWrite) and
((Mode and $F0) <= fmShareDenyNone) then
Result := CreateFile(PChar(FileName), AccessMode[Mode and 3],
ShareMode[(Mode and $F0) shr 4], nil, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL or flags, 0);
end;
{$ENDIF MSWINDOWS}
{$IFDEF POSIX}
const
ShareMode: array[0..fmShareDenyNone shr 4] of Byte = (
0, //No share mode specified
F_WRLCK, //fmShareExclusive
F_RDLCK, //fmShareDenyWrite
0); //fmShareDenyNone
var
FileHandle, Tvar: Integer;
LockVar: flock;
smode: Byte;
Code: Integer;
M:TMarshaller;
begin
Result := INVALID_HANDLE_VALUE;
if FileExists(FileName) and
((Mode and 3) <= fmOpenReadWrite) and
((Mode and $F0) <= fmShareDenyNone) then
begin
FileHandle := __open(M.AsAnsi(FileName, CP_UTF8).ToPointer, (Mode and 3), FileAccessRights);
if FileHandle = -1 then Exit;
smode := Mode and $F0 shr 4;
if ShareMode[smode] <> 0 then
begin
LockVar.l_whence := 0;//SEEK_SET;
LockVar.l_start := 0;
LockVar.l_len := 0;
LockVar.l_type := ShareMode[smode];
Tvar := fcntl(FileHandle, F_SETLK, @LockVar);
Code := errno;
if (Tvar = -1) and (Code <> EINVAL) and (Code <> ENOTSUP) then
// EINVAL/ENOTSUP - file doesn't support locking!
begin
__close(FileHandle);
Exit;
end;
end;
Result := FileHandle;
end;
end;
{$ENDIF POSIX}
function BetterFileCreate(const FileName: string; Mode: LongWord; Rights: cardinal; flags: cardinal): THandle;
{$IFDEF MSWINDOWS}
const
Exclusive: array[0..1] of LongWord = (
CREATE_ALWAYS,
CREATE_NEW);
ShareMode: array[0..4] of LongWord = (
0,
0,
FILE_SHARE_READ,
FILE_SHARE_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE);
begin
Result := INVALID_HANDLE_VALUE;
if (Mode and $F0) <= fmShareDenyNone then
Result := CreateFile(PChar(FileName), GENERIC_READ or GENERIC_WRITE,
ShareMode[(Mode and $F0) shr 4], nil, Exclusive[(Mode and $0004) shr 2], FILE_ATTRIBUTE_NORMAL or Flags, 0);
end;
{$ENDIF MSWINDOWS}
{$IFDEF POSIX}
const
Exclusive: array[0..1] of Cardinal = (
0,
O_EXCL);
ShareMode: array[0..fmShareDenyNone shr 4] of Byte = (
0, //No share mode specified
F_WRLCK, //fmShareExclusive
F_RDLCK, //fmShareDenyWrite
0); //fmShareDenyNone
var
FileHandle, Tvar: Integer;
LockVar: flock;
smode: Byte;
Code: Integer;
M:TMarshaller;
begin
Result := INVALID_HANDLE_VALUE;
if (Mode and $F0) <= fmShareDenyNone then
begin
FileHandle := Integer(__open(M.AsAnsi(FileName, CP_UTF8).ToPointer,
O_RDWR or O_CREAT or O_TRUNC or Exclusive[(Mode and $0004) shr 2], Rights));
if FileHandle = -1 then
Exit;
smode := Mode and $F0 shr 4;
if ShareMode[smode] <> 0 then
begin
LockVar.l_whence := 0;//SEEK_SET;
LockVar.l_start := 0;
LockVar.l_len := 0;
LockVar.l_type := ShareMode[smode];
Tvar := fcntl(FileHandle, F_SETLK, @LockVar);
Code := errno;
if (Tvar = -1) and (Code <> EINVAL) and (Code <> ENOTSUP) then
// EINVAL/ENOTSUP - file doesn't support locking
begin
__close(FileHandle);
Exit;
end;
end;
Result := FileHandle;
end;
end;
{$ENDIF POSIX}
end.