In Plan9 the create syscall fallback on a open(OTRUNC) if the path provided already exists. This is actually a common requirement as most programs (editors, cat...) simply requires that a file is there and is empty, and doesn't care overwriting existing contents (note that this is particularily sensible with something like fossil). In Jehanne the application is responsible of actually handle this "file exists" error but libc provides ocreate() to mimic the Plan9 behaviour. Note that ocreate introduce a subtle race too: the path is walked several times if the file exists, thus it could misbehave on concurrent namespace changes. However I guess this is not going to happen often enough to care now. NOTE we will probably address this rare race too, with a more drammatic change to syscalls: a new walk() syscall that will provide an unopen fd.
66 lines
1.6 KiB
C
66 lines
1.6 KiB
C
/*
|
|
* This file is part of the UCB release of Plan 9. It is subject to the license
|
|
* terms in the LICENSE file found in the top-level directory of this
|
|
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
|
|
* part of the UCB release of Plan 9, including this file, may be copied,
|
|
* modified, propagated, or distributed except according to the terms contained
|
|
* in the LICENSE file.
|
|
*/
|
|
|
|
/*
|
|
* pANS stdio -- freopen
|
|
*/
|
|
#include "iolib.h"
|
|
/*
|
|
* Open the named file with the given mode, using the given FILE
|
|
* Legal modes are given below, `additional characters may follow these sequences':
|
|
* r rb open to read
|
|
* w wb open to write, truncating
|
|
* a ab open to write positioned at eof, creating if non-existant
|
|
* r+ r+b rb+ open to read and write, creating if non-existant
|
|
* w+ w+b wb+ open to read and write, truncating
|
|
* a+ a+b ab+ open to read and write, positioned at eof, creating if non-existant.
|
|
*/
|
|
FILE *freopen(const char *name, const char *mode, FILE *f){
|
|
int m;
|
|
|
|
if(f->state!=CLOSED){
|
|
fclose(f);
|
|
/* premature; fall through and see what happens */
|
|
/* f->state=OPEN; */
|
|
}
|
|
|
|
m = *mode++;
|
|
if(m == 0)
|
|
return NULL;
|
|
if(*mode == 'b')
|
|
mode++;
|
|
switch(m){
|
|
default:
|
|
return NULL;
|
|
case 'r':
|
|
f->fd=open(name, (*mode == '+'? ORDWR: OREAD));
|
|
break;
|
|
case 'w':
|
|
f->fd=ocreate(name, (*mode == '+'? ORDWR: OWRITE), 0666);
|
|
break;
|
|
case 'a':
|
|
m = (*mode == '+'? ORDWR: OWRITE);
|
|
f->fd=open(name, m);
|
|
if(f->fd<0)
|
|
f->fd=ocreate(name, m, 0666);
|
|
seek(f->fd, 0LL, 2);
|
|
break;
|
|
}
|
|
|
|
if(f->fd==-1)
|
|
return NULL;
|
|
f->flags=(mode[0]=='a')? APPEND : 0;
|
|
f->state=OPEN;
|
|
f->buf=0;
|
|
f->rp=0;
|
|
f->wp=0;
|
|
f->lp=0;
|
|
return f;
|
|
}
|