From 4bd026cccb2c22279dd9c88e704642c5a65d3c53 Mon Sep 17 00:00:00 2001
From: Michael Santos
Date: Fri, 30 Apr 2010 12:22:11 -0400
Subject: Support opening files in exclusive mode
Add an option that atomically tests for the existence of a file and
creates it if the file does not exist, by passing the O_EXCL flag
to open() on Unix and CREATE_NEW flag on Windows. Support for O_EXCL
varies across platforms and filesystems.
{ok, Fd} = file:open("/tmp/foo", [write,exclusive]),
{error, eexist} = file:open("/tmp/foo", [write,exclusive]).
---
lib/kernel/doc/src/file.xml | 13 ++++++++++++-
lib/kernel/src/file.erl | 2 +-
lib/kernel/test/file_SUITE.erl | 20 ++++++++++++++++++--
lib/kernel/test/prim_file_SUITE.erl | 20 ++++++++++++++++++--
4 files changed, 49 insertions(+), 6 deletions(-)
(limited to 'lib')
diff --git a/lib/kernel/doc/src/file.xml b/lib/kernel/doc/src/file.xml
index 382262d1ee..a9ceac0bcf 100644
--- a/lib/kernel/doc/src/file.xml
+++ b/lib/kernel/doc/src/file.xml
@@ -603,7 +603,7 @@ f.txt: {person, "kalle", 25}.
Filename = name()
Modes = [Mode]
- Mode = read | write | append | raw | binary | {delayed_write, Size, Delay} | delayed_write | {read_ahead, Size} | read_ahead | compressed
+ Mode = read | write | append | exclusive | raw | binary | {delayed_write, Size, Delay} | delayed_write | {read_ahead, Size} | read_ahead | compressed
Size = Delay = int()
IoDevice = io_device()
Reason = ext_posix() | system_limit
@@ -630,6 +630,17 @@ f.txt: {person, "kalle", 25}.
file opened with append will take place at
the end of the file.
+ -
The raw option allows faster access to a file,
diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl
index a37614e424..1ba329a12b 100644
--- a/lib/kernel/src/file.erl
+++ b/lib/kernel/src/file.erl
@@ -81,7 +81,7 @@
-type mode() :: 'read' | 'write' | 'append' | 'raw' | 'binary' |
{'delayed_write', non_neg_integer(), non_neg_integer()} |
'delayed_write' | {'read_ahead', pos_integer()} |
- 'read_ahead' | 'compressed'.
+ 'read_ahead' | 'compressed' | 'exclusive'.
-type name() :: string() | atom() | [name()].
-type posix() :: atom().
-type bindings() :: any().
diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl
index 15bab0dccd..17c47f871d 100644
--- a/lib/kernel/test/file_SUITE.erl
+++ b/lib/kernel/test/file_SUITE.erl
@@ -53,7 +53,7 @@
-export([file_info/1, file_info_basic_file/1, file_info_basic_directory/1,
file_info_bad/1, file_info_times/1, file_write_file_info/1]).
-export([rename/1, access/1, truncate/1, datasync/1, sync/1,
- read_write/1, pread_write/1, append/1]).
+ read_write/1, pread_write/1, append/1, exclusive/1]).
-export([errors/1, e_delete/1, e_rename/1, e_make_dir/1, e_del_dir/1]).
-export([otp_5814/1]).
@@ -466,7 +466,7 @@ files(suite) ->
sync,datasync,advise].
open(suite) -> [open1,old_modes,new_modes,path_open,close,access,read_write,
- pread_write,append,open_errors].
+ pread_write,append,open_errors,exclusive].
open1(suite) -> [];
open1(doc) -> [];
@@ -840,6 +840,22 @@ open_errors(Config) when is_list(Config) ->
?line test_server:timetrap_cancel(Dog),
ok.
+exclusive(suite) -> [];
+exclusive(doc) -> "Test exclusive access to a file.";
+exclusive(Config) when is_list(Config) ->
+ ?line Dog = test_server:timetrap(test_server:seconds(5)),
+ ?line RootDir = ?config(priv_dir,Config),
+ ?line NewDir = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_exclusive"),
+ ?line ok = ?FILE_MODULE:make_dir(NewDir),
+ ?line Name = filename:join(NewDir, "ex_file.txt"),
+ ?line {ok, Fd} = ?FILE_MODULE:open(Name, [write, exclusive]),
+ ?line {error, eexist} = ?FILE_MODULE:open(Name, [write, exclusive]),
+ ?line ok = ?FILE_MODULE:close(Fd),
+ ?line test_server:timetrap_cancel(Dog),
+ ok.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
pos(suite) -> [pos1,pos2].
diff --git a/lib/kernel/test/prim_file_SUITE.erl b/lib/kernel/test/prim_file_SUITE.erl
index 21bdc06fdc..1688ec45ca 100644
--- a/lib/kernel/test/prim_file_SUITE.erl
+++ b/lib/kernel/test/prim_file_SUITE.erl
@@ -35,7 +35,7 @@
file_write_file_info_a/1, file_write_file_info_b/1]).
-export([rename_a/1, rename_b/1,
access/1, truncate/1, datasync/1, sync/1,
- read_write/1, pread_write/1, append/1]).
+ read_write/1, pread_write/1, append/1, exclusive/1]).
-export([errors/1, e_delete/1, e_rename/1, e_make_dir/1, e_del_dir/1]).
-export([compression/1, read_not_really_compressed/1,
@@ -385,7 +385,7 @@ win_cur_dir_1(_Config, Handle) ->
files(suite) -> [open,pos,file_info,truncate,sync,datasync,advise].
open(suite) -> [open1,modes,close,access,read_write,
- pread_write,append].
+ pread_write,append,exclusive].
open1(suite) -> [];
open1(doc) -> [];
@@ -610,6 +610,22 @@ append(Config) when is_list(Config) ->
?line test_server:timetrap_cancel(Dog),
ok.
+exclusive(suite) -> [];
+exclusive(doc) -> "Test exclusive access to a file.";
+exclusive(Config) when is_list(Config) ->
+ ?line Dog = test_server:timetrap(test_server:seconds(5)),
+ ?line RootDir = ?config(priv_dir,Config),
+ ?line NewDir = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_exclusive"),
+ ?line ok = ?PRIM_FILE:make_dir(NewDir),
+ ?line Name = filename:join(NewDir, "ex_file.txt"),
+ ?line {ok,Fd} = ?PRIM_FILE:open(Name, [write, exclusive]),
+ ?line {error, eexist} = ?PRIM_FILE:open(Name, [write, exclusive]),
+ ?line ok = ?PRIM_FILE:close(Fd),
+ ?line test_server:timetrap_cancel(Dog),
+ ok.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
pos(suite) -> [pos1,pos2].
--
cgit v1.2.3