174 lines
5.2 KiB
C++
174 lines
5.2 KiB
C++
/***********************************************************************
|
|
*
|
|
* 27.filebuf.members.stdcxx-308.cpp - regression test for STDCXX-308
|
|
* http://issues.apache.org/jira/browse/STDCXX-308
|
|
*
|
|
* $Id: 27.filebuf.members.stdcxx-308.cpp 648752 2008-04-16 17:01:56Z faridz $
|
|
*
|
|
***********************************************************************
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing
|
|
* permissions and limitations under the License.
|
|
*
|
|
* Copyright 2008 Rogue Wave Software, Inc.
|
|
*
|
|
***********************************************************************
|
|
*
|
|
* Test description:
|
|
* Sets a maxinum file size limit, forces filebuf to exceed the limit,
|
|
* causing the class dtor to fail to flush the excess data. Verifies
|
|
* that the dtor closes the associated file descriptor regardless of
|
|
* the failure as required by the resolution of LWG issue 622:
|
|
* http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#622
|
|
*
|
|
***********************************************************************/
|
|
|
|
#include <cassert> // for assert()
|
|
#include <cstdio> // for remove(), size_t
|
|
#include <fstream> // for filebuf
|
|
|
|
#if !defined (_WIN32) || defined (__CYGWIN__)
|
|
# include <sys/resource.h> // for getrlimit(), rlim_t
|
|
# include <unistd.h> // for close(), write(), ssize_t
|
|
#endif // !_WIN32 || __CYGWIN__
|
|
|
|
|
|
int write_bytes (const char *fname, std::size_t nbytes)
|
|
{
|
|
std::filebuf fb;
|
|
|
|
if ( 0 == fb.pubsetbuf (0, nbytes + 1)
|
|
|| 0 == fb.open (fname, std::ios::out))
|
|
return -1;
|
|
|
|
#if defined (_RWSTD_VER) && !defined (_RWSTD_NO_EXT_FILEBUF)
|
|
|
|
// use the filebuf::fd() extension to get the filebuf's
|
|
// associated file descriptor
|
|
const int fd = fb.fd ();
|
|
|
|
#else // if defined (RWSTD_NO_EXT_FILEBUF)
|
|
|
|
// assume fd is the next available file descriptor after
|
|
// STDIN_FILENO, _FILENO_STDOUT, and STDERR_FILENO
|
|
const int fd = 3;
|
|
|
|
#endif // RWSTD_NO_EXT_FILEBUF
|
|
|
|
if (0 < fd) {
|
|
// fill up the filebuf's character buffer without
|
|
// overflowing
|
|
for (std::size_t i = 0; i != nbytes; ++i)
|
|
fb.sputc ('*');
|
|
}
|
|
|
|
// have filebuf dtor try to flush the object's character
|
|
// buffer and expect it to fail (and flush out only the
|
|
// number specified by RLIMIT_FSIZE)
|
|
|
|
// return the file descriptor to the caller so that it can
|
|
// verify that it has been closed
|
|
return fd;
|
|
}
|
|
|
|
|
|
int main ()
|
|
{
|
|
#if !defined (_WIN32) || defined (__CYGWIN__)
|
|
|
|
const char fname[] = "testfile.text";
|
|
|
|
std::remove (fname);
|
|
|
|
rlimit rl;
|
|
int status;
|
|
|
|
// retrieve the current file size limits
|
|
status = getrlimit (RLIMIT_FSIZE, &rl);
|
|
|
|
if (status) {
|
|
std::perror ("getrlimit(RLIMIT_FSIZE, ...)");
|
|
return 1;
|
|
}
|
|
|
|
// uncomment for debugging
|
|
// std::printf ("file size limits = %ld, %ld\n",
|
|
// long (rl.rlim_cur), long (rl.rlim_max));
|
|
|
|
const rlim_t rlim_cur_saved = rl.rlim_cur;
|
|
rl.rlim_cur = 32;
|
|
|
|
// set a new file size limit
|
|
status = setrlimit (RLIMIT_FSIZE, &rl);
|
|
if (status) {
|
|
std::perror ("setrlimit(RLIMIT_FSIZE, ...)");
|
|
return 1;
|
|
}
|
|
|
|
// uncomment for debugging
|
|
// status = getrlimit (RLIMIT_FSIZE, &rl);
|
|
|
|
// if (status) {
|
|
// std::perror ("getrlimit(RLIMIT_FSIZE, ...)");
|
|
// return 1;
|
|
// }
|
|
// std::printf ("file size limits = %ld, %ld\n",
|
|
// long (rl.rlim_cur), long (rl.rlim_max));
|
|
|
|
// try to write more bytes than the current soft limit using
|
|
// filebuf, expecting the class dtor to fail but close the
|
|
// associated file descriptor
|
|
const int fd = write_bytes (fname, std::size_t (rl.rlim_cur + 1));
|
|
if (fd < 0) {
|
|
std::perror ("filebuf::~filebuf()");
|
|
std::remove (fname);
|
|
return 1;
|
|
}
|
|
|
|
// restore the previous soft limit
|
|
rl.rlim_cur = rlim_cur_saved;
|
|
|
|
status = setrlimit (RLIMIT_FSIZE, &rl);
|
|
if (status) {
|
|
std::perror ("setrlimit(RLIMIT_FSIZE, ...)");
|
|
|
|
close (fd);
|
|
|
|
std::remove (fname);
|
|
return 1;
|
|
}
|
|
|
|
// try to write to the filebuf's file descriptor, expecting
|
|
// the write() to fail
|
|
const ssize_t nwrote = write (fd, "<", 1);
|
|
|
|
assert (-1 == nwrote);
|
|
|
|
// close file descriptor before removing the file (it's okay
|
|
// if the call fails because the fd has already been closed)
|
|
close (fd);
|
|
std::remove (fname);
|
|
|
|
#else // Windows
|
|
|
|
// See about implementing using SetFileValidData():
|
|
// http://msdn.microsoft.com/en-us/library/aa365544(VS.85).aspx
|
|
|
|
#endif // !_WIN32 || __CYGWIN__
|
|
|
|
return 0;
|
|
}
|