[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference turris::c_plus_plus

Title:C++
Notice:Read 1.* and use keywords (e.g. SHOW KEY/FULL KIT_CXX_VAX_VMS)
Moderator:DECCXX::AMARTIN
Created:Fri Nov 06 1987
Last Modified:Thu Jun 05 1997
Last Successful Update:Fri Jun 06 1997
Number of topics:3604
Total number of notes:18242

3489.0. "how about a "truncate at current position" manipulator for fstream?" by CUJO::SAMPSON () Thu Mar 13 1997 01:06

	Hello,

	A customer made a suggestion today that seems reasonable.
He was looking for a way to open a stream file, read the contents,
add, remove, and/or modify information in memory, overwrite the
file with the entire modified contents, and truncate the file at
its new size.  I suggested possible methods that would use ACP QIO,
RMS, or DEC C RTL calls, but he wanted to stay with the C++ class
library.

	He would like to have a function or manipulator (or whatever)
for the fstream class, that would truncate the file at the current
position.  There is an available option (called ios::trunc, I think)
that allows an existing file's contents to be truncated away when
first opened, but this would not allow him to read the file first
without closing it.  He wants to open the file once for read and write
access, using it as a lock against other accessors.

	Anyway, he decided that it's no big deal if the file isn't
truncated precisely at the end of the valid contents, since he can
always add a byte count at the start, and/or a special end-of-data
indicator at the end.  In principle, though, it would be useful to
have such a tool available.  What do you think of the idea?

	Thanks,
	Bob Sampson
T.RTitleUserPersonal
Name
DateLines
3489.1TLE::D_SMITHDuane Smith -- DEC C RTLThu Mar 13 1997 06:414
    In C, the functions are called "truncate" and "ftruncate".  They were
    added in OpenVMS V7.
    
    Duane
3489.2that's good; how to use them?CUJO::SAMPSONThu Mar 13 1997 20:361
	Oh!  Can they be applied to an open fstream object?  If so, how?
3489.3answer to .2DECC::J_WARDFri Mar 14 1997 12:504
You can always get access to the underlying C file
descriptor for an fstream by calling rdbuf()->fd().
Then use the file descriptor for the ftruncate() call.
3489.4oops, I was thinking trunc-at-x, not trunc-hereSPECXN::DERAMODan D'EramoFri Mar 14 1997 15:4250
        // for discussion purposes only ...
        
        #include <iostream.hxx>
        #include <fstream.hxx>
        #include <unistd.h>
        
        class Trunc {             // Sample usage:   ofstrm << Trunc(100);
        public:
            int offset;
            Trunc() :offset(0) {}
            Trunc(int o) :offset(o) {}
        };
        
        ofstream &operator<<(ofstream &ofs, const Trunc &t)
        {
            filebuf *fbp = ofs.rdbuf();
            if (fbp == 0) { /* error handling ... */ }
        
            int fd = fbp->fd();
            if (fd < 0) { /* error handling ... */ }
        
            // anything else you need/want to do first, such as
            // flushing the buffer ...
        
            int result = ftruncate(fd, t.offset);
            if (result != 0) { /* error handling ... */ }
        
            // put the ofstream and filebuf objects back into a
            // consistent state with respect to the now truncated
            // file ...
        
            // Must return the ofstream argument.
            return ofs;
        }
        
        Three problems ... First is the missing code fragments. 
        Second, as is a Trunc object can't encode "truncate at current
        position", it can only encode an offset.  Third, Trunc objects
        don't play well with cascading <<'s.  For example,
        
        	const char done[] = "\nDone\n";
        	ofstrm << done << Trunc(currpos + strlen(done));
        
        This is (ofstrm << done) << Trunc(...) and the type of the
        left hand side argument is ostream, not ofstream, but the only
        defined << with a Trunc on the right hand side takes an
        ofstream on the left hand side.
        
        Dan
        
3489.5find current position with ftell()?CUJO::SAMPSONFri Mar 14 1997 21:452
	Okay, cool, thanks!  So, the answer is: the needed tools are
available in OpenVMS V7.0; after that, it's just a SMOP...
3489.6ftruncate() opens and closes the fileDECC::J_WARDMon Mar 17 1997 09:1010
From the ftruncate() man page:

  path      Specifies the name of a file that is opened, truncated, and then
            closed.  The path parameter must point to a pathname which names
  	    ...

So if what the user wants is to be able to truncate the file
without also opening and closing it, then I don't think this command
will help.
3489.7SPECXN::DERAMODan D&#039;EramoMon Mar 17 1997 10:4840
	But the path argument is passed to truncate().  ftruncate()
        takes a file descriptor to an already opened file.
        
        How much information does an ofstream and/or filebuf object
        cache about the state of the file that will be messed up by
        calling ftruncate() with the file descriptor?
        
        Dan
        
        
        
truncate(2)                                                       truncate(2)



NAME

  truncate, ftruncate - Changes file length

SYNOPSIS

  #include <sys/types.h>
  int truncate (
          const char *path,
          off_t length );
  int ftruncate (
          int filedes,
          off_t length );
        
PARAMETERS

  path      Specifies the name of a file that is opened, truncated, and then
            closed.  The path parameter must point to a pathname which names
            a regular file for which the calling process has write permis-
            sion.  If the path parameter refers to a symbolic link, the
            length of the file pointed to by the symbolic link is truncated.

  filedes   Specifies the descriptor of a file that must be open for writing.

  length    Specifies the new length of the file in bytes.
3489.8might work for this customerCUJO::SAMPSONMon Mar 17 1997 21:087
>        How much information does an ofstream and/or filebuf object
>        cache about the state of the file that will be messed up by
>        calling ftruncate() with the file descriptor?

	Hmmm.  Would it work out okay if the file were closed
	immediately after the ftruncate() call?  Perhaps by
	next calling fclose(), then close on the fstream?