Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > fclose then fopen equivalent for stdout?

Reply
Thread Tools

fclose then fopen equivalent for stdout?

 
 
Chris Torek
Guest
Posts: n/a
 
      10-25-2006
In article <eho4hq$6vb$>
David Mathog <> wrote:
>A program of mine writes to a tape unit. Output can be either through
>stdout or through a file opened with fopen(). When all the data is
>transferred to tape the program needs to close the output stream so that
>the tape driver will write a filemark on the tape. Otherwise multiple
>clumps of data saved to tape would all appear to be one big file on the
>tape.
>
>When the tape unit device was explicitly opened with fopen()
>that's possible: call fclose() and then for the next batch
>of data fopen() the tape device again and write some more.
>
>However when data is going through stdout like:
>
> program > /dev/nst0
>
>is there an equivalent operation?


Not only is this impossible in Standard C, it is not even possible
on most POSIX systems. You can *close* the standard output stream
with:

fclose(stdout);

but you can never guarantee to get it open again. That is, if this
fclose succeeds, stdout is dead. (The next fopen() call may in
fact re-use the old stdout "FILE *", effectively resurrecting it,
but it also might not.)

By cheating -- going directly to POSIX file descriptors -- you can
avoid "killing" the C library stdout stream, while closing the
underlying file descriptor. For instance, something like this:

fflush(stdout); /* pass output to underlying fd */
close(STDOUT_FILENO); /* POSIX-specific: close stdout */
fd = open(path, openmode, creatmode_opt); /* POSIX-specific */
if (fd != STDOUT_FILENO) ... uh oh ...

(which relies on STDOUT_FILENO being the first available one so
that open() uses it), but you will need to find the "path" (by
"magic"; see below). Moreover, with this method -- just as with
the fopen(), fclose(), fopen() again method -- there is no guarantee
that the same pathname refers to the same physical device twice in
a row (consider what happens if the super-user renames /dev/nst0
to /dev/nst0.old and creates a new /dev/nst0, for instance).

Your best best for "truly safe" operation, given the non-portability
of the whole thing, is to use a system-specific operation (probably
an ioctl) to write tape-marks, without ever closing the device.
If that is unavailable or impractical, your second-best-bet is to
require the path-name; "recovering" the device name (by using,
e.g., fts_open() on "/dev" and comparing "st_dev" IDs in "stat"
structures) is possible but tricky.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
 
Reply With Quote
 
 
 
 
Eric Sosman
Guest
Posts: n/a
 
      10-25-2006


David Mathog wrote On 10/25/06 13:28,:
> Eric Sosman wrote:
>
>
>> Here's a suggestion: You're trying to obtain the effect
>>of fclose(), right? Does any particular function spring to
>>mind as being likely to perform the operations of fclose()?
>>How about ... <<wait for it>> ... fclose()?
>>

>
>
> I'm not trying to get fclose, I'm trying to get
>
> fclose()
> fopen()


Aha! Okay, sorry -- that wasn't clear to me.

> How then does the program CONTINUE to write to stdout
> so that data gets to the tape device after having called
> fclose(stdout)?
>
> What parameters for fopen() reassociate stdout with the same
> output stream following the fclose()?


I don't think there's any way to do this in Standard C's
very simple model of I/O. In fact, I don't think what you're
doing with an explicit device name is guaranteed to work: C
only understands "files," not multi-file "volumes."

--


 
Reply With Quote
 
 
 
 
Eric Sosman
Guest
Posts: n/a
 
      10-25-2006


Harald van Dijk wrote On 10/25/06 13:29,:
> Eric Sosman wrote:
>
>>David Mathog wrote On 10/25/06 12:48,:
>>
>>> freopen(NULL,"wb",stdout);

>>
>> Undefined behavior: The first argument is supposed to
>>be a string (a string that names a file), but NULL is not
>>a string. It's much like trying fopen(NULL, "wb").

>
>
> Actually, freopen() has special behaviour for a NULL filename. I don't
> know enough about it to know if that special behaviour is useful here,
> though.


Oh, drat! Serves me right for looking at a man page
instead of checking the Standard. The behavior is not
undefined, but implementation-defined .. and as far as
I can tell, it doesn't help the O.P.

>> Here's a suggestion: You're trying to obtain the effect
>>of fclose(), right? Does any particular function spring to
>>mind as being likely to perform the operations of fclose()?
>>How about ... <<wait for it>> ... fclose()?

>
>
> So how do you write to stdout again after closing it?


You don't. It's closed. (I had not realized that he
wanted to keep on writing until he counter-replied to my
reply. It was all there in the original message, if I'd
squinted at it hard enough -- not my day, evidently ...)

--


 
Reply With Quote
 
CBFalconer
Guest
Posts: n/a
 
      10-25-2006
David Mathog wrote:
> Eric Sosman wrote:
>
>> Here's a suggestion: You're trying to obtain the effect
>> of fclose(), right? Does any particular function spring to
>> mind as being likely to perform the operations of fclose()?
>> How about ... <<wait for it>> ... fclose()?

>
> I'm not trying to get fclose, I'm trying to get
>
> fclose()
> fopen()
>
> How then does the program CONTINUE to write to stdout
> so that data gets to the tape device after having called
> fclose(stdout)?
>
> What parameters for fopen() reassociate stdout with the same
> output stream following the fclose()?


No guaranteed way. Read the manuals for your system. Most tape
units have some sort of control channel that can be told "Now write
an inter-file gap". Since this is system specific it is off-topic
here, where we deal in portable C programming. I have no idea what
your system is and thus no idea what newsgroup would be
appropriate.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>


 
Reply With Quote
 
Serve Laurijssen
Guest
Posts: n/a
 
      10-25-2006

"David Mathog" <> wrote in message
news:eho4hq$6vb$...
>A program of mine writes to a tape unit. Output can be either through
>stdout or through a file opened with fopen(). When all the data is
> transferred to tape the program needs to close the output stream so that
> the tape driver will write a filemark on the tape.


what part of fclose exactly triggers the filemark writing? You probably
tried it, but it might be as simple as fflush


 
Reply With Quote
 
Rod Pemberton
Guest
Posts: n/a
 
      10-25-2006

"David Mathog" <> wrote in message
news:eho6r0$7no$...
> Eric Sosman wrote:
>
> > Here's a suggestion: You're trying to obtain the effect
> > of fclose(), right? Does any particular function spring to
> > mind as being likely to perform the operations of fclose()?
> > How about ... <<wait for it>> ... fclose()?
> >

>
> I'm not trying to get fclose, I'm trying to get
>
> fclose()
> fopen()
>
> How then does the program CONTINUE to write to stdout
> so that data gets to the tape device after having called
> fclose(stdout)?
>
> What parameters for fopen() reassociate stdout with the same
> output stream following the fclose()?
>


I'm a bit unfamiliar with pipes, but, won't closing stdout from your program
also close the pipe? How do you intend to keep the pipe open through an
open and close of stdout? I suspect this is a second issue no one else has
mentioned.

I think your best bet is to not use a pipe at all, and replace the fclose();
fopen() sequence with a routine specific to the tape drive which writes the
control data, (as Falconer suggested).

Another option would be to have a single control program which spawn()'s or
exec()'s, etc., a separate program which writes one file at a time. The
command line for the spawn'd or exec'd program could use a pipe, if desired.


Rod Pemberton


 
Reply With Quote
 
David Mathog
Guest
Posts: n/a
 
      10-26-2006
Serve Laurijssen wrote:
> "David Mathog" <> wrote in message
> news:eho4hq$6vb$...
>> A program of mine writes to a tape unit. Output can be either through
>> stdout or through a file opened with fopen(). When all the data is
>> transferred to tape the program needs to close the output stream so that
>> the tape driver will write a filemark on the tape.

>
> what part of fclose exactly triggers the filemark writing? You probably
> tried it, but it might be as simple as fflush


When the linux st driver receives a close operation following a write it
(the st driver) writes the filemark. The fclose() and fflush() don't
write that mark themselves. Apparently the only way to write multiple
files to tape through stdout, and to place a filemark between them,
is to use ioctl(). Even that is tricky, as doing something like:

fwrite(buffer1,BUFSIZE,1,stdout);
ioctl( <appropriate parameters> );
fwrite(buffer2,BUFSIZE,1,stdout);

might result in the filemarks being written before all of the buffer1
data gets to the tape drive.

Thanks all,

David Mathog
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      10-26-2006
David Mathog <> writes:
> Serve Laurijssen wrote:

[...]
>> what part of fclose exactly triggers the filemark writing? You
>> probably tried it, but it might be as simple as fflush

>
> When the linux st driver receives a close operation following a write it
> (the st driver) writes the filemark. The fclose() and fflush() don't
> write that mark themselves. Apparently the only way to write multiple
> files to tape through stdout, and to place a filemark between them,
> is to use ioctl(). Even that is tricky, as doing something like:
>
> fwrite(buffer1,BUFSIZE,1,stdout);
> ioctl( <appropriate parameters> );
> fwrite(buffer2,BUFSIZE,1,stdout);
>
> might result in the filemarks being written before all of the buffer1
> data gets to the tape drive.


<SEMI-OT>

Perhaps this would work:

fwrite(buffer1,BUFSIZE,1,stdout);
fflush(stdout);
ioctl( <appropriate parameters> );
fwrite(buffer2,BUFSIZE,1,stdout);

</SEMI-OT>

--
Keith Thompson (The_Other_Keith) kst- <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
 
Reply With Quote
 
Walter Roberson
Guest
Posts: n/a
 
      10-26-2006
In article <eholcr$efp$>,
Serve Laurijssen <> wrote:

>"David Mathog" <> wrote in message
>news:eho4hq$6vb$...
>>A program of mine writes to a tape unit. Output can be either through
>>stdout or through a file opened with fopen(). When all the data is
>> transferred to tape the program needs to close the output stream so that
>> the tape driver will write a filemark on the tape.


>what part of fclose exactly triggers the filemark writing? You probably
>tried it, but it might be as simple as fflush


As others have noted, it is part of the device driver, not a standard
C function.

Someone referenced a Linux ioctl(); that's certainly a possibility on
appropriate versions of Linux.

As additional off-topic information about the difficulty of doing this:
On SCSI tape devices, the end-of-file marker or end-of-medium markers
are handled by specific operation codes. If your device driver does not
provide an ioctl() or equivilent, then you may have to issue the
SCSI-layer command yourself, if your system provides a generalized
SCSI device driver.

Also it might be worth keeping in mind that most Unix-type systems
provide a command "mt" with a "weof" option. But then there's the
difficulty that "mt" wants the name of a tape device on its command
line, and if you are using stdout then you don't know the tape device
name. Since you'd be presuming a unix-type system for this purpose,
you could fstat() to find the major and minor device numbers
associated with stdout, and iterate through the standard tape drive
name /dev subdirectory and hope for a match... and then mangle that
name to ensure that you include the appropriate name code for
non-rewind.

I wonder if the OP took into account that if the invoking user
redirected to an autorewind tape device (as is likely if they
hadn't been hit over the head several times with this issue),
that the fclose() equivilent that is proposed to be done would
trigger a tape rewind...


How would I handle it? Well, I would code the application to
take a tape device name as a parameter, and write to that instead
of stdout; perhaps I'd allow the semi-standard use of a single dash
to indicate standard output, but in that case I'd have the program
balk if it would have been expected to write several file marks.

No matter what you know about your own system, I don't think you
can reasonably be expected to be able to write multiple file marks
in a scenario such as

$ OurTapeBackups basedirectory | \
ssh -c operator@remotehost "dd of=/dev/tape"
--
"law -- it's a commodity"
-- Andrew Ryan (The Globe and Mail, 2005/11/26)
 
Reply With Quote
 
CBFalconer
Guest
Posts: n/a
 
      10-26-2006
Walter Roberson wrote:
>

.... snip ...
>
> I wonder if the OP took into account that if the invoking user
> redirected to an autorewind tape device (as is likely if they
> hadn't been hit over the head several times with this issue),
> that the fclose() equivilent that is proposed to be done would
> trigger a tape rewind...


In which case he might be surprised at how little tape is needed
for the complete dump.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
fopen and fclose? kathy C++ 17 02-15-2006 06:14 PM
If forget to fclose() after fopen(), is there any testing tool who can detect it automatically? lihua C Programming 19 07-07-2005 03:50 AM
fgets,fopen, fclose Trying_Harder C Programming 5 09-03-2003 05:15 PM
Re: Question about fopen, fput, fclose? Peter Shaggy Haywood C Programming 0 08-30-2003 12:05 AM
Re: Question about fopen, fput, fclose? prama C Programming 5 08-28-2003 02:53 AM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57