+ support for file locking for *nix systems based on flock (mantis #13012)

git-svn-id: trunk@12630 -
This commit is contained in:
Jonas Maebe 2009-01-30 15:08:30 +00:00
parent 527dd80aa2
commit a730ee7f10
3 changed files with 232 additions and 5 deletions

1
.gitattributes vendored
View File

@ -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

View File

@ -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;

View 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.