deutsch@jplgodo.UUCP (Michael Deutsch ) (04/06/88)
I have a "C" program that records the program results into a file, provided that file already exists. In case the file DOES NOT exist I want the program to function identically but the results should be flushed down the tube, i.e. nowhere, i.e. written to a non-existing file? What sort of "file pointer" or trick should I use to accomplish my goal? Please reply by e-mail, or call me collect : Michael Deutsch (619) 452 - 8649 Thanks
lm@arizona.edu (Larry McVoy) (04/06/88)
In article <9654@jplgodo.UUCP> deutsch@jplgodo.UUCP (Michael Deutsch ) writes: > >I have a "C" program that records the program >results into a file, provided that file already >exists. In case the file DOES NOT exist I want >the program to function identically but the results >should be flushed down the tube, i.e. nowhere ------ UNTESTED! ------- If you are using FILE* # include <stdio.h> # include <sys/types.h> # include <sys/stat.h> FILE* myopen(name) char* name; { struct stat buf; extern errno; if (stat(name, &buf) == -1 && errno == ENOENT) return fopen("/dev/null", "w"); else return fopen(name, "w"); } Else myopen(name) char* name; { struct stat buf; extern errno; if (stat(name, &buf) == -1 && errno == ENOENT) return open("/dev/null", 1); else return open(name, 1); } How's that? -- "These aren't my thoughts, they're my cat walking on the keyboard." Larry McVoy lm@arizona.edu or ...!{uwvax,sun}!arizona.edu!lm
davidsen@steinmetz.steinmetz.ge.com (William E. Davidsen Jr) (04/06/88)
In article <9654@jplgodo.UUCP> deutsch@jplgodo.UUCP (Michael Deutsch ) writes: | | I have a "C" program that records the program | results into a file, provided that file already | exists. In case the file DOES NOT exist I want | the program to function identically but the results | should be flushed down the tube, i.e. nowhere, i.e. | written to a non-existing file? First problem is to open the file if it exists, by fp = fopen(MYFILE, "r+"); /* open, no create */ outflag = fp != NULL; /* set a flag */ if (outflag) fseek(fp, 0L, 2); /* rewind if open ok */ You can then print to the file using a macro, such as: #define cprintf if (outflag) fprintf . . cprintf(fp, "format", data); -- bill davidsen (wedu@ge-crd.arpa) {uunet | philabs | seismo}!steinmetz!crdos1!davidsen "Stupidity, like virtue, is its own reward" -me
ron@topaz.rutgers.edu (Ron Natalie) (04/08/88)
Contemplate the following: fd = open("file", 1); if(fd == -1) fd = open("/dev/null", 1);
flaps@dgp.toronto.edu (Alan J Rosenthal) (04/08/88)
davidsen@crdos1.UUCP (bill davidsen) writes: > if (outflag) fseek(fp, 0L, 2); /* rewind if open ok */ That's "fseek(fp,0L,0)". The given fseek() call seeks to the end of the file. > #define cprintf if (outflag) fprintf This kind of macro is very unsafe. Consider: if(something) cprintf(blah blah); else something else; The `else' clause will pair with the if in the cprintf expansion, much to your surprise and irritation. When at all possible, define macros to be expressions rather than larger amounts of code. For example: extern int fprintf(),mydonothing(); #define cprintf (outflag ? fprintf : mydonothing) and, elsewhere: int mydonothing() { return(0); } Some adjustments are needed to make it valid ANSI C due to mydonothing()'s being variadic; I think fprintf() will be declared in stdio.h but I'm not sure. ajr -- "Comment, Spock?" "Very bad poetry, Captain."
wes@obie.UUCP (Barnacle Wes) (04/11/88)
In article <9654@jplgodo.UUCP> deutsch@jplgodo.UUCP (Michael Deutsch ) writes: | I have a "C" program that records the program | results into a file, provided that file already | exists. In case the file DOES NOT exist I want | the program to function identically but the results | should be flushed down the tube, i.e. nowhere, i.e. | written to a non-existing file? In article <10285@steinmetz.steinmetz.ge.com>, davidsen@steinmetz.steinmetz.ge.com (William E. Davidsen Jr) replies: > First problem is to open the file if it exists, by > fp = fopen(MYFILE, "r+"); /* open, no create */ > outflag = fp != NULL; /* set a flag */ > if (outflag) fseek(fp, 0L, 2); /* rewind if open ok */ > > You can then print to the file using a macro, such as: > #define cprintf if (outflag) fprintf > . > . > cprintf(fp, "format", data); I'd do it slightly different. Unless you need speed, try using access(2) to determine if the file is available to you, and if not open /dev/null for writing: char *name; FILE *ofp; if (access("/data/file/name", 02)) /* 02 = write access */ name = "/data/file/name"; else name = "/dev/null"; ofp = fopen(name, "a"); ... Then just fprintf all of your data to handle "ofp". Less efficient in the no-output case, but it makes the program somewhat easier to read. -- /\ - "Against Stupidity, - {backbones}! /\/\ . /\ - The Gods Themselves - utah-cs!utah-gr! / \/ \/\/ \ - Contend in Vain." - uplherc!sp7040! / U i n T e c h \ - Schiller - obie!wes
friedl@vsi.UUCP (Stephen J. Friedl) (04/16/88)
In article <9654@jplgodo.UUCP> deutsch@jplgodo.UUCP (Michael Deutsch ) writes: > I have a "C" program that records the program results into a file, > provided that file already exists. In case the file DOES NOT exist > I want the program to function identically but the results should > be flushed down the tube, i.e. nowhere, i.e. written to a nong > file? Then (William E. Davidsen Jr) replies: > [little C fragment to do the above] In article <147@obie.UUCP>, wes@obie.UUCP (Barnacle Wes) writes: > I'd do it slightly different. Unless you need speed, try using > access(2) to determine if the file is available to you, and if not > open /dev/null for writing: > > [little C fragment to do the above] AAAAAAAAAARGH! Please do not use access(2) as a handy-dandy "does the file exist?" function. It is designed to be used by set-{user,group}-id programs to see if the underlying user has permission to access the file in the requested manner. I hate to sound like a flamer, but programmers who do not understand the troubles with access(2) should probably not use it; you will make life difficult for somebody down the road. Stat(2) can be used to do the same thing with just a little extra code. I wrote an "accfile(3)" function that does what you *think* access(2) is doing; send me a note to get a copy. Steve Friedl, resident access(2)-basher -- Steve Friedl V-Systems, Inc. "Yes, I'm jeff@unh's brother" friedl@vsi.com {backbones}!vsi.com!friedl attmail!vsi!friedl
henry@utzoo.uucp (Henry Spencer) (04/17/88)
> I'd do it slightly different. Unless you need speed, try using > access(2) to determine if the file is available to you... --------------------------> NO!!! <----------------------- You should never use access(2) except when a setuid program wants to determine whether a file would be accessible in the absence of setuid privileges. For determining accessibility in normal circumstances, use stat(2) and look at the mode bits. (There was an eaccess() function posted to one of the sources groups a few years ago that would do this for you.) If your program happens to be run under setuid conditions, and it is using access(2) for ordinary availability checking, it will get the wrong answers. -- "Noalias must go. This is | Henry Spencer @ U of Toronto Zoology non-negotiable." --DMR | {ihnp4,decvax,uunet!mnetor}!utzoo!henry
decot@hpisod2.HP.COM (Dave Decot) (04/19/88)
> > I'd do it slightly different. Unless you need speed, try using > > access(2) to determine if the file is available to you, and if not > > open /dev/null for writing: > > > > [little C fragment to do the above] > > AAAAAAAAAARGH! Please do not use access(2) as a handy-dandy > "does the file exist?" function. It is designed to be used > by set-{user,group}-id programs to see if the underlying user > has permission to access the file in the requested manner. Uh...I think a file's existence is independent of your user-id. It's perfectly acceptable to use access(2) the F_OK (0) value of amode it to determine whether files exist. Such calls succeed exactly when calls to stat(2) succeed. access(2) should not be used to determine the other access permissions except in setuid programs, and even then, not for testing execute access by setuid-root programs. Dave Decot hpda!decot
mike@turing.UNM.EDU (Michael I. Bushnell) (04/20/88)
In article <14020030@hpisod2.HP.COM> decot@hpisod2.HP.COM (Dave Decot) writes: >> AAAAAAAAAARGH! Please do not use access(2) as a handy-dandy >> "does the file exist?" function. It is designed to be used >> by set-{user,group}-id programs to see if the underlying user >> has permission to access the file in the requested manner. >Uh...I think a file's existence is independent of your user-id. Nope. A file can be said to "exist" for a process if you can SEARCH ALL THE DIRECTORIES in the path leading to the file. So, if you are under suid conditions, use access for F_OK, then you will get misleading results if a directory along the path wasn't searcheable for your real uid. >It's perfectly acceptable to use access(2) the F_OK (0) value of amode >it to determine whether files exist. Such calls succeed exactly when >calls to stat(2) succeed. So, DON'T use access(2) EVER unless you are a suid program (or have done setuid(geteuid()) (which is really perverse in non-suid programs). >access(2) should not be used to determine the other access permissions >except in setuid programs, and even then, not for testing execute >access by setuid-root programs. Why not? What if I have a suid program which executes a given user program in a funky way, with appropriate permission settings, but it needs to determine if it will be able to run the program before is does its funky stuff (to wit): Make access call if FAILED report error, die; Do funky stuff (requiring root permissions) setuid(geteuid) exec(USER PROGRAM) Yes, I know, there are problems if the user deletes or otherwise messes with things on the program, but there are ways around that. N u m q u a m G l o r i a D e o Michael I. Bushnell HASA - "A" division 14308 Skyline Rd NE Computer Science Dept. Albuquerque, NM 87123 OR Farris Engineering Ctr. OR University of New Mexico mike@turing.unm.edu Albuquerque, NM 87131 {ucbvax,gatech}!unmvax!turing.unm.edu!mike
friedl@vsi.UUCP (Stephen J. Friedl) (04/20/88)
In article <14020030@hpisod2.HP.COM>, decot@hpisod2.HP.COM (Dave Decot) writes: > Uh...I think a file's existence is independent of your user-id. > > It's perfectly acceptable to use access(2) the F_OK (0) value of amode > it to determine whether files exist. Such calls succeed exactly when > calls to stat(2) succeed. Not quite -- parent directory modes will get in the way. In the case where the real uid has no permission in a parent directory component of a file but but the effective uid does, stat(2) succeeds and access(2) fails. So, access("/tmp/secret.dir/open.file", 0); and stat("/tmp/secret.dir/open.file", &stbuf); are not guaranteed to return the same values if /tmp/secret.dir is available to the set-user-id but not to me. -- Steve Friedl V-Systems, Inc. Resident access(2) basher friedl@vsi.com {backbones}!vsi.com!friedl attmail!vsi!friedl
mouse@mcgill-vision.UUCP (der Mouse) (04/23/88)
In article <147@obie.UUCP>, wes@obie.UUCP (Barnacle Wes) writes: > I'd do it slightly different. Unless you need speed, try using > access(2) to determine if the file is available to you, and if not > open /dev/null for writing: [code which is supposed to do that - I didn't check it] This is wrong if the program might ever run setuid. access() does not exist to allow vanilla users to find out whether files are accessible; it's for setuid programs to determine whether the real user can access a file. (It's the wrong way to do even that, because of the resulting window, but that's another can of worms.) The right way to find out whether you can open a file for write is...try it! der Mouse uucp: mouse@mcgill-vision.uucp arpa: mouse@larry.mcrcim.mcgill.edu
elwiz@killer.UUCP (Chert Pellett) (04/25/88)
How about just try: int fd; fd = open (FILENAME, O_APPEND| O_RDWR); /* Will fail if file not there */ if (fd < 0) fd = open ("/dev/null", O_RDWR); /* Discard output, as per original article */ if you want to use stdio, use the fdopen (fd, "w+") to get your FILE * type... -- Chert Pellett (why would anyone use stat/access then have to do an open call?)