[comp.lang.c] Writing to A NON-Existing File in "C"

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

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