PerlIO :APR / apr_file_open() flag issue
am 21.04.2009 01:59:19 von Marc AdkinsThis is a multi-part message in MIME format.
--------------030406030309040509030007
Content-Type: multipart/alternative;
boundary="------------080906040709040709080601"
--------------080906040709040709080601
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
Originally posted to the APR dev list. The response (from jTrawick) was
as follows:
The Perl code that builds the apr_file_open() flags needs to turn on
APR_WRITE.
I think that this patch to mod_perl is what you need:
--- modperl_apr_perlio.c.orig 2007-12-31 02:39:50.000000000 -0500
+++ modperl_apr_perlio.c 2009-04-20 19:37:25.954107404 -0400
@@ -85,7 +85,7 @@
switch (*mode) {
case 'a':
- apr_flag = APR_APPEND | APR_CREATE;
+ apr_flag = APR_WRITE | APR_CREATE | APR_APPEND;
break;
case 'w':
apr_flag = APR_WRITE | APR_CREATE | APR_TRUNCATE;
The rest of this email is my original post. I would still like a
workaround is one exists.
------------------------------------------------------------ --
I found this in mod_perl but the issue can be demonstrated with Perl
alone and also without Perl. I'll start from the latter...
Attempting to open a file for append using the following flags:
APR_BUFFERED | APR_BINARY | APR_CREATE | APR_APPEND
will not work. The apr_file_open() function returns APR_EACCES. If the
following flags are used:
APR_BUFFERED | APR_BINARY | APR_CREATE | APR_WRITE | APR_APPEND
it works fine. In a vacuum this behavior is debatable. On the one
hand, APR_APPEND could be seen to imply APR_WRITE. On the other hand,
it might be argued that the first case is incomplete flag-wise.
In the context of Perl, however, particularly when using the APR PerlIO
filter, this becomes problematic. Perl uses special character sequences
which are converted to the proper flags down underneath the covers. So
in Perl '>' (write to a new file) converts properly but '>>' (append to
an existing file or create a new one if necessary) does not. There is
no message either, AFAIK, it just fails silently.
I'm attaching a couple of my test files. They demonstrate the problem
but don't show why it happens. I instrumented a copy of
file_io/unix/open.c to figure out what was happening. It fails in this
code:
if ((flag & APR_READ) && (flag & APR_WRITE)) {
oflags = O_RDWR;
}
else if (flag & APR_READ) {
oflags = O_RDONLY;
}
else if (flag & APR_WRITE) {
oflags = O_WRONLY;
}
else {
printf("fails here...\n");
return APR_EACCES;
}
I might suggest checking for APR_WRITE /or/ APR_APPEND, but there may be
some reason why it's done this way.
Has anyone else stumbled on this or am I doing something that breaks the
warranty? Is there a work-around in Perl?
--
Marc M. Adkins
Software Development Engineer
520 Pike Street, Suite 500
Seattle, WA 98101
P: 206-331-3508
F: 206.331.3695
E: madkins@marchex.com
Marchex Inc.
www.marchex.com
This e-mail message and any attachments are solely for
intended recipients, and may contain information that is
privileged and confidential. If you are not the intended
recipient, any dissemination, distribution or copying is
strictly prohibited. If you believe that you may have
received this message in error, please immediately notify
the sender by replying to this e-mail message.
--------------080906040709040709080601
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
Originally posted to the APR dev list. The response (from jTrawick)
was as follows:
The Perl code that builds the apr_file_open() flags needs
to turn on APR_WRITE.
I think that this patch to mod_perl is what you need:
---
modperl_apr_perlio.c.orig 2007-12-31 02:39:50.000000000 -0500
+++ modperl_apr_perlio.c 2009-04-20 19:37:25.954107404 -0400
@@ -85,7 +85,7 @@
switch (*mode) {
case 'a':
- apr_flag = APR_APPEND | APR_CREATE;
+ apr_flag = APR_WRITE | APR_CREATE | APR_APPEND;
break;
case 'w':
apr_flag = APR_WRITE | APR_CREATE | APR_TRUNCATE;
The rest of this email is my original post. I would still like a
workaround is one exists.
------------------------------------------------------------ --
I found this in mod_perl but the issue can be demonstrated with Perl
alone and also without Perl. I'll start from the latter...
Attempting to open a file for append using the following flags:
APR_BUFFERED |
APR_BINARY | APR_CREATE | APR_APPEND
will not work. The apr_file_open()
function returns APR_EACCES.
If the following flags are used:
APR_BUFFERED |
APR_BINARY | APR_CREATE | APR_WRITE | APR_APPEND
it works fine. In a vacuum this behavior is debatable. On the one
hand, APR_APPEND
could be seen to imply APR_WRITE.
On the other hand, it might be argued that the first case is incomplete
flag-wise.
In the context of Perl, however, particularly when using the APR PerlIO
filter, this becomes problematic. Perl uses special character
sequences which are converted to the proper flags down underneath the
covers. So in Perl '>'
(write to a new file) converts properly but face="Courier New, Courier, monospace">'>>' (append to an
existing file or create a new one if necessary) does not. There is no
message either, AFAIK, it just fails silently.
I'm attaching a couple of my test files. They demonstrate the problem
but don't show why it happens. I instrumented a copy of face="Courier New, Courier, monospace">file_io/unix/open.c to
figure out what was happening. It fails in this code:
if ((flag &
APR_READ) && (flag & APR_WRITE)) {
oflags = O_RDWR;
}
else if (flag & APR_READ) {
oflags = O_RDONLY;
}
else if (flag & APR_WRITE) {
oflags = O_WRONLY;
}
else {
printf("fails here...\n");
return APR_EACCES;
}
I might suggest checking for face="Courier New, Courier, monospace">APR_WRITE or face="Courier New, Courier, monospace">APR_APPEND, but there
may be some reason why it's done this way.
Has anyone else stumbled on this or am I doing something that breaks
the warranty? Is there a work-around in Perl?
--
Marc M. Adkins
Software Development Engineer
520 Pike Street, Suite 500
Seattle, WA 98101
P: 206-331-3508
F: 206.331.3695
E:
Marchex Inc.
This e-mail message and any attachments are solely for
intended recipients, and may contain information that is
privileged and confidential. If you are not the intended
recipient, any dissemination, distribution or copying is
strictly prohibited. If you believe that you may have
received this message in error, please immediately notify
the sender by replying to this e-mail message.
--------------080906040709040709080601--
--------------030406030309040509030007
Content-Type: text/x-csrc;
name="aprio.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="aprio.c"
#include
#include
typedef long long off64_t;
#include
#include
#include
char *text = "Nevermore will we sing\n";
int main (int argc, const char *argv[]) {
apr_file_t *file;
apr_int32_t flag;
apr_pool_t *pool;
apr_size_t size;
apr_status_t stat;
stat = apr_initialize();
if (stat != APR_SUCCESS) {
printf("Unable to initialize\n");
return -1;
}
printf("Initialized!\n");
apr_pool_create(&pool, NULL);
// flag = APR_BUFFERED | APR_BINARY | APR_CREATE | APR_WRITE | APR_TRUNCATE;
flag = APR_BUFFERED | APR_BINARY | APR_CREATE | APR_APPEND;
// flag = APR_BUFFERED | APR_BINARY | APR_CREATE | APR_WRITE | APR_APPEND;
stat = apr_file_open(&file, "test.txt", flag, APR_OS_DEFAULT, pool);
if (stat == APR_SUCCESS) {
size = strlen(text);
stat = apr_file_write(file, text, &size);
if (stat != APR_SUCCESS) {
printf("Error writing to file (%d)\n", stat);
}
} else {
printf("Error opening file (%d)\n", stat);
}
apr_pool_destroy(pool);
apr_terminate();
return 0;
}
--------------030406030309040509030007
Content-Type: application/x-perl;
name="perlio-apr.pl"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="perlio-apr.pl"
#!/usr/bin/perl
use strict;
use warnings;
use APR::PerlIO;
use APR::Pool;
our $hndl;
our $pool = new APR::Pool;
warn "### $APR::PerlIO::VERSION\n";
die "*** Unable to open file: $! $@\n"
unless open $hndl, " >> :APR", "test.txt", $pool;
my @now = localtime;
printf $hndl "%04d-%02d-%02d %02d:%02d:%02d Testing, 1, 2, 3\n",
$now[5] + 1900, $now[4] + 1,
reverse @now[0..3];
close $hndl;
--------------030406030309040509030007--