Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
27.filebuf.members.stdcxx-308.cpp
Go to the documentation of this file.
1
39#include <cassert> // for assert()
40#include <cstdio> // for remove(), size_t
41#include <fstream> // for filebuf
42
43#if !defined (_WIN32) || defined (__CYGWIN__)
44# include <sys/resource.h> // for getrlimit(), rlim_t
45# include <unistd.h> // for close(), write(), ssize_t
46#endif // !_WIN32 || __CYGWIN__
47
48
49int write_bytes (const char *fname, std::size_t nbytes)
50{
51 std::filebuf fb;
52
53 if ( 0 == fb.pubsetbuf (0, nbytes + 1)
54 || 0 == fb.open (fname, std::ios::out))
55 return -1;
56
57#if defined (_RWSTD_VER) && !defined (_RWSTD_NO_EXT_FILEBUF)
58
59 // use the filebuf::fd() extension to get the filebuf's
60 // associated file descriptor
61 const int fd = fb.fd ();
62
63#else // if defined (RWSTD_NO_EXT_FILEBUF)
64
65 // assume fd is the next available file descriptor after
66 // STDIN_FILENO, _FILENO_STDOUT, and STDERR_FILENO
67 const int fd = 3;
68
69#endif // RWSTD_NO_EXT_FILEBUF
70
71 if (0 < fd) {
72 // fill up the filebuf's character buffer without
73 // overflowing
74 for (std::size_t i = 0; i != nbytes; ++i)
75 fb.sputc ('*');
76 }
77
78 // have filebuf dtor try to flush the object's character
79 // buffer and expect it to fail (and flush out only the
80 // number specified by RLIMIT_FSIZE)
81
82 // return the file descriptor to the caller so that it can
83 // verify that it has been closed
84 return fd;
85}
86
87
88int main ()
89{
90#if !defined (_WIN32) || defined (__CYGWIN__)
91
92 const char fname[] = "testfile.text";
93
94 std::remove (fname);
95
96 rlimit rl;
97 int status;
98
99 // retrieve the current file size limits
100 status = getrlimit (RLIMIT_FSIZE, &rl);
101
102 if (status) {
103 std::perror ("getrlimit(RLIMIT_FSIZE, ...)");
104 return 1;
105 }
106
107 // uncomment for debugging
108 // std::printf ("file size limits = %ld, %ld\n",
109 // long (rl.rlim_cur), long (rl.rlim_max));
110
111 const rlim_t rlim_cur_saved = rl.rlim_cur;
112 rl.rlim_cur = 32;
113
114 // set a new file size limit
115 status = setrlimit (RLIMIT_FSIZE, &rl);
116 if (status) {
117 std::perror ("setrlimit(RLIMIT_FSIZE, ...)");
118 return 1;
119 }
120
121 // uncomment for debugging
122 // status = getrlimit (RLIMIT_FSIZE, &rl);
123
124 // if (status) {
125 // std::perror ("getrlimit(RLIMIT_FSIZE, ...)");
126 // return 1;
127 // }
128 // std::printf ("file size limits = %ld, %ld\n",
129 // long (rl.rlim_cur), long (rl.rlim_max));
130
131 // try to write more bytes than the current soft limit using
132 // filebuf, expecting the class dtor to fail but close the
133 // associated file descriptor
134 const int fd = write_bytes (fname, std::size_t (rl.rlim_cur + 1));
135 if (fd < 0) {
136 std::perror ("filebuf::~filebuf()");
137 std::remove (fname);
138 return 1;
139 }
140
141 // restore the previous soft limit
142 rl.rlim_cur = rlim_cur_saved;
143
144 status = setrlimit (RLIMIT_FSIZE, &rl);
145 if (status) {
146 std::perror ("setrlimit(RLIMIT_FSIZE, ...)");
147
148 close (fd);
149
150 std::remove (fname);
151 return 1;
152 }
153
154 // try to write to the filebuf's file descriptor, expecting
155 // the write() to fail
156 const ssize_t nwrote = write (fd, "<", 1);
157
158 assert (-1 == nwrote);
159
160 // close file descriptor before removing the file (it's okay
161 // if the call fails because the fd has already been closed)
162 close (fd);
163 std::remove (fname);
164
165#else // Windows
166
167 // See about implementing using SetFileValidData():
168 // http://msdn.microsoft.com/en-us/library/aa365544(VS.85).aspx
169
170#endif // !_WIN32 || __CYGWIN__
171
172 return 0;
173}
#define i
Definition 17.names.cpp:126
#define close(f)
int write_bytes(const char *fname, std::size_t nbytes)
#define assert(expr)
Definition _cassert.h:40