Home > Archive > Unix Programming > December 2004 > Opening a file for update with creation if necessary
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Opening a file for update with creation if necessary
|
|
| Tom Anderson 2004-12-11, 8:56 pm |
| Hi all,
I'm not much of a UNIX programmer, or any of a C programmer (python's my
language - although i'll try to speak in C here), so apologies if this is
a stupid question.
I want to open a file for updating - mode r+. However, i'd like it to be
created if it doesn't exist, as with mode w. Can i do this with fopen, or
am i going to have to use open (with flags O_RDWR | O_CREAT) and fdopen?
Thanks,
tom
--
So the moon is approximately 24 toasters from Scunthorpe.
| |
| Bjørn Augestad 2004-12-11, 8:56 pm |
| Tom Anderson wrote:
> Hi all,
>
> I'm not much of a UNIX programmer, or any of a C programmer (python's my
> language - although i'll try to speak in C here), so apologies if this is
> a stupid question.
>
> I want to open a file for updating - mode r+. However, i'd like it to be
> created if it doesn't exist, as with mode w. Can i do this with fopen, or
> am i going to have to use open (with flags O_RDWR | O_CREAT) and fdopen?
>
> Thanks,
> tom
>
Check out fopen() with mode a+, possibly with an additional call to
fs /rewind/fsetpos to move to the start of the file if needed.
Bjørn.
| |
| Tom Anderson 2004-12-11, 8:56 pm |
| On Sat, 11 Dec 2004, Bjørn Augestad wrote:
> Tom Anderson wrote:
>
>
> Check out fopen() with mode a+, possibly with an additional call to
> fs /rewind/fsetpos to move to the start of the file if needed.
Won't that force all writes to go to the end of the file? The standard (or
at least a standard) seems to think so:
http://www.opengroup.org/onlinepubs.../xsh/fopen.html
Although i'm pretty sure Linux, at least, doesn't do this.
tom
--
Science runs with us, making us Gods.
| |
| Michael B Allen 2004-12-12, 3:58 am |
| On Sat, 11 Dec 2004 16:19:14 -0500, Tom Anderson wrote:
> I want to open a file for updating - mode r+. However, i'd like it to be
> created if it doesn't exist, as with mode w. Can i do this with fopen,
> or am i going to have to use open (with flags O_RDWR | O_CREAT) and
> fdopen?
To be honest I'm not certain that this really applies to your question
but the following function will open a file, creating it if necessary,
and return a value indicating wheather the file was created as opposed to
opened. It seems to me that you might be able to adapt it to your purpose.
Mike
int
copen(const char *pathname, int flags, mode_t mode, int *cre)
{
int fd, max = 3; /* maximum attempts to open */
if ((flags & O_CREAT) == 0) {
if ((fd = open(pathname, flags, mode)) == -1) {
return -1;
}
*cre = 0;
return fd;
}
while (max--) {
if ((fd = open(pathname, flags & ~(O_CREAT | O_EXCL))) != -1) {
*cre = 0;
return fd;
} else if (errno != ENOENT) {
return -1;
}
if ((fd = open(pathname, flags | O_EXCL, mode)) != -1) {
*cre = 1;
return fd;
} else if (errno != EEXIST) {
return -1;
}
}
errno = EACCES;
return -1;
}
| |
| Bjørn Augestad 2004-12-12, 3:58 am |
| Tom Anderson wrote:
> On Sat, 11 Dec 2004, Bjørn Augestad wrote:
>
>
>
>
> Won't that force all writes to go to the end of the file? The standard (or
> at least a standard) seems to think so:
>
> http://www.opengroup.org/onlinepubs.../xsh/fopen.html
>
> Although i'm pretty sure Linux, at least, doesn't do this.
>
You're right, from the man page:
Opening a file with append mode (a as the first character in the mode
argument) causes all subsequent writes to the file to be forced to the
then current end-of-file, regardless of intervening calls to fs ().
My apologies for the crappy advice I gave you. I guess a double call to
fopen() is the way to go then. Something like the code below.
Bjørn
#include <stdio.h>
int main(int ac, char** av)
{
FILE *f;
if( (f = fopen("blabla", "r+")) == NULL
&& (f = fopen("blabla", "w+")) == NULL) {
perror("fopen");
exit(1);
}
while(*++av)
fprintf(f, "%s\n", *av);
fclose(f);
return 0;
}
> tom
>
| |
| Tom Anderson 2004-12-13, 4:08 pm |
| On Sat, 11 Dec 2004, Michael B Allen wrote:
> On Sat, 11 Dec 2004 16:19:14 -0500, Tom Anderson wrote:
>
>
> To be honest I'm not certain that this really applies to your question
I don't think it does - i'm all about the locking, baby. Still, it's a
nice function!
tom
--
isn't it about time we had some new label for people interested in technology who also have an interest in drinking binges, womanising and occasional bouts of ultra violence? -- D
| |
| Tom Anderson 2004-12-13, 4:08 pm |
| On Sun, 12 Dec 2004, Bjørn Augestad wrote:
> Tom Anderson wrote:
>
>
> You're right, from the man page:
>
> Opening a file with append mode (a as the first character in the mode
> argument) causes all subsequent writes to the file to be forced to the
> then current end-of-file, regardless of intervening calls to fs ().
Which OS was that on? The man page on OS X (ie FreeBSD) says something
similar; the one on Linux (Debian 2.4.28) says "Open for writing. The file
is created if it does not exist. The stream is positioned at the end of
the file." - nothing about forcing writes to EOF. Those crazy Linux
hippies!
> My apologies for the crappy advice I gave you. I guess a double call to
> fopen() is the way to go then. Something like the code below.
>
> #include <stdio.h>
>
> int main(int ac, char** av)
> {
> FILE *f;
>
> if( (f = fopen("blabla", "r+")) == NULL
> && (f = fopen("blabla", "w+")) == NULL) {
> perror("fopen");
> exit(1);
> }
>
> while(*++av)
> fprintf(f, "%s\n", *av);
>
> fclose(f);
> return 0;
> }
That's more or less what i came up with, except i explicitly test for the
existence of the file first, rather than catching the error from the first
fopen. I think your way is more efficient, though.
The trouble is, there's still a risk of race conditions; i can't lock the
file until i've got it open, and opening with w+ will clobber it, so it
would be possible to get:
A: open with r+, fail
A: open with w+, succeed
B: open with some writing mode
B: lock
B: write
B: close + unlock
A: lock
A: now has a file that's supposed to be empty but isn't!
Actually, this isn't so bad - process A didn't explicitly want the file to
be empty anyway. And if it does, it just has to manually (re-)clobber the
file after it locks it.
I think the Right Way to do this is with fcntl.open, with funky flags, and
then stdio.fdopen - you only ever have to make one open call, you don't
have to test the state of the file, and there's no inappropriate
clobbering. More of a pain to write, though!
tom
--
isn't it about time we had some new label for people interested in technology who also have an interest in drinking binges, womanising and occasional bouts of ultra violence? -- D
| |
| Måns Rullgård 2004-12-13, 4:08 pm |
| Tom Anderson <twic@urchin.earth.li> writes:
> On Sun, 12 Dec 2004, Bjørn Augestad wrote:
>
>
> Which OS was that on? The man page on OS X (ie FreeBSD) says something
> similar; the one on Linux (Debian 2.4.28) says "Open for writing. The file
> is created if it does not exist. The stream is positioned at the end of
> the file." - nothing about forcing writes to EOF. Those crazy Linux
> hippies!
The man page on my Linux system has this paragraph:
Opening a file in append mode (a as the first character of
mode) causes all subsequent write operations to this stream to
occur at end-of-file, as if preceded by an
fs (stream,0,SEEK_END);
call.
--
Måns Rullgård
mru@inprovide.com
| |
| Tom Anderson 2004-12-13, 9:01 pm |
| On Mon, 13 Dec 2004, Måns Rullgård wrote:
> Tom Anderson <twic@urchin.earth.li> writes:
>
>
> The man page on my Linux system has this paragraph:
>
> Opening a file in append mode (a as the first character of
> mode) causes all subsequent write operations to this stream to
> occur at end-of-file, as if preceded by an
> fs (stream,0,SEEK_END);
> call.
Hmm. The man page for fopen on mine has nothing at all like that; perhaps
we have different versions of glibc or something. The man page for open
says:
The file is opened in append mode. Before each
write, the file pointer is positioned at the end of
the file, as if with ls .
And when i actually get of my arse and try it, i see that fopening with
mode "a" does indeed get you the 'correct' force-to-end behaviour. ISTR
reading something about Linux not doing this; that might be an old version
or something. So it goes.
tom
--
This isn't right. This isn't even wrong.
| |
| Ara.T.Howard@noaa.gov 2004-12-14, 3:57 am |
| |
|
|
|
|