mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-15 05:29:30 +02:00
+ support for file locking for *nix systems based on flock (mantis #13012)
git-svn-id: trunk@12630 -
This commit is contained in:
parent
527dd80aa2
commit
a730ee7f10
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -8151,6 +8151,7 @@ tests/test/units/sysutils/texec1.pp svneol=native#text/plain
|
||||
tests/test/units/sysutils/texec2.pp svneol=native#text/plain
|
||||
tests/test/units/sysutils/textractquote.pp svneol=native#text/plain
|
||||
tests/test/units/sysutils/tfile1.pp svneol=native#text/plain
|
||||
tests/test/units/sysutils/tfile2.pp svneol=native#text/plain
|
||||
tests/test/units/sysutils/tfilename.pp svneol=native#text/plain
|
||||
tests/test/units/sysutils/tfloattostr.pp -text
|
||||
tests/test/units/sysutils/tlocale.pp svneol=native#text/plain
|
||||
|
@ -176,11 +176,51 @@ Begin
|
||||
End;
|
||||
|
||||
|
||||
Function DoFileLocking(Handle: Longint; Mode: Integer) : Longint;
|
||||
var
|
||||
lockop: cint;
|
||||
lockres: cint;
|
||||
begin
|
||||
DoFileLocking:=Handle;
|
||||
if (Handle>=0) then
|
||||
begin
|
||||
case (mode and (fmShareExclusive or fmShareDenyWrite or fmShareDenyRead)) of
|
||||
fmShareCompat,
|
||||
fmShareExclusive:
|
||||
lockop:=LOCK_EX or LOCK_NB;
|
||||
fmShareDenyWrite:
|
||||
lockop:=LOCK_SH or LOCK_NB;
|
||||
fmShareDenyNone:
|
||||
exit;
|
||||
else
|
||||
begin
|
||||
{ fmShareDenyRead does not exit under *nix, only shared access
|
||||
(similar to fmShareDenyWrite) and exclusive access (same as
|
||||
fmShareExclusive)
|
||||
}
|
||||
FpClose(Handle);
|
||||
DoFileLocking:=-1;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
repeat
|
||||
lockres:=fpflock(Handle,lockop);
|
||||
until lockres<>ESysEIntr;
|
||||
if (lockres<>0) then
|
||||
begin
|
||||
FpClose(Handle);
|
||||
DoFileLocking:=-1;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
Function FileOpen (Const FileName : string; Mode : Integer) : Longint;
|
||||
|
||||
Var LinuxFlags : longint;
|
||||
|
||||
BEGIN
|
||||
Var
|
||||
LinuxFlags : longint;
|
||||
begin
|
||||
LinuxFlags:=0;
|
||||
Case (Mode and 3) of
|
||||
0 : LinuxFlags:=LinuxFlags or O_RdOnly;
|
||||
@ -188,7 +228,8 @@ BEGIN
|
||||
2 : LinuxFlags:=LinuxFlags or O_RdWr;
|
||||
end;
|
||||
FileOpen:=fpOpen (pointer(FileName),LinuxFlags);
|
||||
//!! We need to set locking based on Mode !!
|
||||
|
||||
FileOpen:=DoFileLocking(FileOpen, Mode);
|
||||
end;
|
||||
|
||||
|
||||
@ -201,7 +242,7 @@ end;
|
||||
|
||||
Function FileCreate (Const FileName : String;Mode : Longint) : Longint;
|
||||
|
||||
BEGIN
|
||||
begin
|
||||
FileCreate:=fpOpen(pointer(FileName),O_RdWr or O_Creat or O_Trunc,Mode);
|
||||
end;
|
||||
|
||||
|
185
tests/test/units/sysutils/tfile2.pp
Normal file
185
tests/test/units/sysutils/tfile2.pp
Normal file
@ -0,0 +1,185 @@
|
||||
{$ifdef fpc}
|
||||
{$mode objfpc}
|
||||
{$h+}
|
||||
{$endif}
|
||||
|
||||
uses
|
||||
SysUtils;
|
||||
|
||||
{$ifndef fpc}
|
||||
const
|
||||
fmsharecompat = cardinal(0);
|
||||
fsFromBeginning = cardinal(0);
|
||||
{$endif}
|
||||
|
||||
var
|
||||
l,l2: longint;
|
||||
begin
|
||||
try
|
||||
try
|
||||
l:=filecreate('tfile2.dat');
|
||||
if (l<0) then
|
||||
raise exception.create('unable to create file');
|
||||
fileclose(l);
|
||||
l:=fileopen('tfile2.dat',fmopenread);
|
||||
if (filewrite(l,l,sizeof(l))>0) then
|
||||
raise exception.create('writing to read-only file succeeded');
|
||||
fileclose(l);
|
||||
deletefile('tfile2.dat');
|
||||
|
||||
|
||||
l:=filecreate('tfile2.dat');
|
||||
if (l<0) then
|
||||
raise exception.create('unable to create file (2)');
|
||||
fileclose(l);
|
||||
l:=fileopen('tfile2.dat',fmopenwrite);
|
||||
if (filewrite(l,l,sizeof(l))<>sizeof(l)) then
|
||||
raise exception.create('writing to write-only file failed');
|
||||
if (fileseek(l,0,fsFromBeginning)<>0) then
|
||||
raise exception.create('seeking write-only file failed');
|
||||
if (fileread(l,l2,sizeof(l))>=0) then
|
||||
raise exception.create('reading from write-only file succeeded');
|
||||
fileclose(l);
|
||||
|
||||
l:=fileopen('tfile2.dat',fmopenread or fmShareDenyWrite);
|
||||
if (l<0) then
|
||||
raise exception.create('unable to open file in read-only mode and fmShareDenyWrite mode');
|
||||
l2:=fileopen('tfile2.dat',fmopenread or fmShareDenyWrite);
|
||||
if (l2 < 0) then
|
||||
raise exception.create('opening two files as read-only with fmShareDenyWrite failed');
|
||||
fileclose(l2);
|
||||
l2:=fileopen('tfile2.dat',fmopenread or fmShareExclusive);
|
||||
if (l2 >= 0) then
|
||||
begin
|
||||
fileclose(l2);
|
||||
raise exception.create('opening file first as read-only with fmShareDenyWrite, and then again as fmopenread with fmShareExclusive succeeded');
|
||||
end;
|
||||
fileclose(l);
|
||||
|
||||
|
||||
l:=fileopen('tfile2.dat',fmopenwrite or fmShareExclusive);
|
||||
if (l<0) then
|
||||
raise exception.create('unable to open file in write-only and fmShareExclusive mode');
|
||||
l2:=fileopen('tfile2.dat',fmopenwrite or fmShareExclusive);
|
||||
if (l2 >= 0) then
|
||||
begin
|
||||
fileclose(l2);
|
||||
raise exception.create('opening two files as write-only with fmShareExclusive succeeded');
|
||||
end;
|
||||
l2:=fileopen('tfile2.dat',fmopenwrite or fmShareDenyWrite);
|
||||
if (l2 >= 0) then
|
||||
begin
|
||||
fileclose(l2);
|
||||
raise exception.create('opening file first as write-only with fmShareExclusive, and then again as fmopenwrite with fmShareDenyWrite succeeded');
|
||||
end;
|
||||
fileclose(l);
|
||||
|
||||
|
||||
l:=fileopen('tfile2.dat',fmopenread or fmShareExclusive);
|
||||
if (l<0) then
|
||||
raise exception.create('unable to open file in read-only and fmShareExclusive mode');
|
||||
l2:=fileopen('tfile2.dat',fmopenread or fmShareExclusive);
|
||||
if (l2 >= 0) then
|
||||
begin
|
||||
fileclose(l2);
|
||||
raise exception.create('opening two files as read-only with fmShareExclusive succeeded');
|
||||
end;
|
||||
l2:=fileopen('tfile2.dat',fmopenread or fmShareDenyWrite);
|
||||
if (l2 >= 0) then
|
||||
begin
|
||||
fileclose(l2);
|
||||
raise exception.create('opening file first as read-only with fmShareExclusive, and then again as fmopenread with fmShareDenyWrite succeeded');
|
||||
end;
|
||||
fileclose(l);
|
||||
|
||||
|
||||
l:=fileopen('tfile2.dat',fmopenread);
|
||||
if (l<0) then
|
||||
raise exception.create('unable to open file in read-only mode (2)');
|
||||
l2:=fileopen('tfile2.dat',fmopenread);
|
||||
if (l2 >= 0) then
|
||||
begin
|
||||
fileclose(l2);
|
||||
raise exception.create('opening two files as read-only without sharing specified succeeded (should both be exclusive)');
|
||||
end;
|
||||
l2:=fileopen('tfile2.dat',fmopenread or fmShareDenyWrite);
|
||||
if (l2 >= 0) then
|
||||
begin
|
||||
fileclose(l2);
|
||||
raise exception.create('opening file first as read-only without sharing mode (should be exclusive), and then again as fmopenread with fmShareDenyWrite succeeded');
|
||||
end;
|
||||
fileclose(l);
|
||||
|
||||
|
||||
{ should be same as fmShareExclusive }
|
||||
l:=fileopen('tfile2.dat',fmopenread or fmShareCompat);
|
||||
if (l<0) then
|
||||
raise exception.create('unable to open file in read-only and fmShareCompat mode');
|
||||
l2:=fileopen('tfile2.dat',fmopenread or fmShareCompat);
|
||||
if (l2 >= 0) then
|
||||
begin
|
||||
fileclose(l2);
|
||||
raise exception.create('opening two files as read-only with fmShareCompat succeeded');
|
||||
end;
|
||||
l2:=fileopen('tfile2.dat',fmopenread or fmShareDenyWrite);
|
||||
if (l2 >= 0) then
|
||||
begin
|
||||
fileclose(l2);
|
||||
raise exception.create('opening file first as read-only with fmShareCompat, and then again as fmopenread with fmShareDenyWrite succeeded');
|
||||
end;
|
||||
fileclose(l);
|
||||
|
||||
|
||||
l:=fileopen('tfile2.dat',fmopenread or fmShareDenyNone);
|
||||
if (l<0) then
|
||||
raise exception.create('unable to open file in read-only mode and fmShareDenyNone mode');
|
||||
l2:=fileopen('tfile2.dat',fmopenread or fmShareDenyNone);
|
||||
if (l2 >= 0) then
|
||||
raise exception.create('opening two files as read-only with fmShareDenyNone failed');
|
||||
fileclose(l2);
|
||||
{ unix-specific that this fails? }
|
||||
l2:=fileopen('tfile2.dat',fmopenread or fmShareDenyWrite);
|
||||
if (l2 >= 0) then
|
||||
raise exception.create('opening two files as read-only with fmShareDenyNone and then fmShareDenyWrite succeeded');
|
||||
fileclose(l2);
|
||||
{ unix-specific that this fails? }
|
||||
l2:=fileopen('tfile2.dat',fmopenread or fmShareExclusive);
|
||||
if (l2 >= 0) then
|
||||
raise exception.create('opening two files as read-only with fmShareDenyNone and then fmShareExclusive succeeded');
|
||||
fileclose(l2);
|
||||
fileclose(l);
|
||||
|
||||
l:=fileopen('tfile2.dat',fmopenread or fmShareDenyWrite);
|
||||
if (l<0) then
|
||||
raise exception.create('unable to open file in read-only mode and fmShareDenyWrite mode (2)');
|
||||
{ unix-specific that this fails? }
|
||||
l2:=fileopen('tfile2.dat',fmopenread or fmShareDenyNone);
|
||||
if (l2 >= 0) then
|
||||
raise exception.create('opening files as read-only with fmShareDenyWrite and then fmShareDenyNone succeeded');
|
||||
fileclose(l2);
|
||||
fileclose(l);
|
||||
|
||||
|
||||
l:=fileopen('tfile2.dat',fmopenwrite or fmShareDenyNone);
|
||||
if (l<0) then
|
||||
raise exception.create('unable to open file in write-only mode and fmShareDenyNone mode');
|
||||
l2:=fileopen('tfile2.dat',fmopenread or fmShareDenyNone);
|
||||
if (l2 >= 0) then
|
||||
begin
|
||||
fileclose(l2);
|
||||
raise exception.create('opening two files as read/write-only with fmShareDenyNone succeeded');
|
||||
end;
|
||||
fileclose(l2);
|
||||
|
||||
except
|
||||
on e: exception do
|
||||
begin
|
||||
writeln(e.message);
|
||||
exitcode:=1;
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
fileclose(l);
|
||||
deletefile('tfile2.dat');
|
||||
end;
|
||||
end.
|
Loading…
Reference in New Issue
Block a user