source: sources/src/ioFileRegular.cc @ 1464:3f6711617be1

Revision 1464:3f6711617be1, 16.3 KB checked in by niam, 22 months ago (diff)

{issue #58[resolved]} support for non-c++ exceptions

Line 
1/***************************************************************************
2 *            ioFileRegular.cc
3 *
4 *  Wed Oct 8 2005
5 *  Copyright  2005  Dmytro Milinevskyy
6 *  milinevskyy@gmail.com
7 ****************************************************************************/
8
9/*
10 *  This program is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU Lesser General Public License version 2.1 as published by
12 *  the Free Software Foundation;
13 *
14 *  This program is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU Library General Public License for more details.
18 *
19 *  You should have received a copy of the GNU Lesser General Public License
20 *  along with this program; if not, write to the Free Software
21 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
24/**
25 * vim indentation settings
26 * set tabstop=4
27 * set shiftwidth=4
28 */
29
30#include <libdodo/directives.h>
31
32#include <unistd.h>
33#include <sys/types.h>
34#include <sys/stat.h>
35#include <errno.h>
36#include <string.h>
37
38#include "ioFile.inline"
39
40#include <libdodo/ioFileRegular.h>
41#include <libdodo/toolsFilesystem.h>
42#include <libdodo/ioFileRegularEx.h>
43#include <libdodo/types.h>
44#include <libdodo/pcSyncStack.h>
45#include <libdodo/ioChannel.h>
46#include <libdodo/ioBlockChannel.h>
47
48using namespace dodo::io::file;
49
50regular::regular(short protection) : block::channel(protection),
51                                     handle(new io::__file__)
52{
53#ifndef IO_WO_XEXEC
54    collectedData.setExecObject(xexec::OBJECT_IOFILEREGULAR);
55#endif
56}
57
58//-------------------------------------------------------------------
59
60regular::regular(const dodo::string &a_path,
61                 short            a_mode,
62                 short            protection) : block::channel(protection),
63                                                path(a_path),
64                                                mode(a_mode),
65                                                handle(new io::__file__)
66{
67#ifndef IO_WO_XEXEC
68    collectedData.setExecObject(xexec::OBJECT_IOFILEREGULAR);
69#endif
70
71    bool exists(false);
72
73    if (path.size() == 0) {
74        delete handle;
75
76        dodo_throw exception::basic(exception::MODULE_IOFILEREGULAR, REGULAREX_REGULAR, exception::ERRNO_LIBDODO, REGULAREX_WRONGFILENAME, IOFILEREGULAREX_WRONGFILENAME_STR, __LINE__, __FILE__, path);
77    } else {
78        struct stat st;
79
80        if (::lstat(path.data(), &st) == -1) {
81            if (errno != ENOENT) {
82                delete handle;
83
84                dodo_throw exception::basic(exception::MODULE_IOFILEREGULAR, REGULAREX_REGULAR, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
85            }
86        } else {
87            exists = true;
88        }
89
90        if (exists && !S_ISREG(st.st_mode) && !S_ISBLK(st.st_mode)) {
91            delete handle;
92
93            dodo_throw exception::basic(exception::MODULE_IOFILEREGULAR, REGULAREX_REGULAR, exception::ERRNO_LIBDODO, REGULAREX_WRONGFILENAME, IOFILEREGULAREX_WRONGFILENAME_STR, __LINE__, __FILE__, path);
94        }
95
96        switch (mode) {
97            case OPEN_MODE_READ_WRITE:
98
99                handle->file = fopen(path.data(), "r+");
100                if (handle->file == NULL)
101                    handle->file = fopen(path.data(), "w+");
102
103                break;
104
105            case OPEN_MODE_READ_WRITE_TRUNCATE:
106
107                handle->file = fopen(path.data(), "w+");
108
109                break;
110
111            case OPEN_MODE_READ_ONLY:
112            default:
113
114                handle->file = fopen(path.data(), "r");
115        }
116    }
117
118    if (handle->file == NULL) {
119        delete handle;
120
121        dodo_throw exception::basic(exception::MODULE_IOFILEREGULAR, REGULAREX_REGULAR, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
122    }
123
124    if (!exists) {
125        dodo_try {
126            tools::filesystem::chmod(path, DEFAULT_FILE_PERM);
127        } dodo_catch (exception::basic *e UNUSED) {
128            delete handle;
129
130            dodo_rethrow;
131        }
132    }
133}
134
135//-------------------------------------------------------------------
136
137regular::regular(const regular &fd) : block::channel(fd.protection),
138                                      path(fd.path),
139                                      mode(fd.mode),
140                                      handle(new io::__file__)
141
142{
143#ifndef IO_WO_XEXEC
144    collectedData.setExecObject(xexec::OBJECT_IOFILEREGULAR);
145#endif
146
147    append = fd.append;
148    pos = fd.pos;
149    bs = fd.bs;
150
151    if (fd.handle->file !=  NULL) {
152        int oldDesc, newDesc;
153
154        oldDesc = fileno(fd.handle->file);
155        if (oldDesc == -1) {
156            delete handle;
157
158            dodo_throw exception::basic(exception::MODULE_IOFILEREGULAR, REGULAREX_REGULAR, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
159        }
160
161        newDesc = dup(oldDesc);
162        if (newDesc == -1) {
163            delete handle;
164
165            dodo_throw exception::basic(exception::MODULE_IOFILEREGULAR, REGULAREX_REGULAR, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
166        }
167
168        switch (mode) {
169            case OPEN_MODE_READ_WRITE:
170            case OPEN_MODE_READ_WRITE_TRUNCATE:
171
172                handle->file = fdopen(newDesc, "r+");
173
174                break;
175
176            case OPEN_MODE_READ_ONLY:
177            default:
178
179                handle->file = fdopen(newDesc, "r");
180        }
181
182        if (handle->file == NULL) {
183            delete handle;
184
185            dodo_throw exception::basic(exception::MODULE_IOFILEREGULAR, REGULAREX_REGULAR, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
186        }
187    }
188}
189
190//-------------------------------------------------------------------
191
192regular::~regular()
193{
194    if (handle->file !=  NULL)
195        fclose(handle->file);
196
197    delete handle;
198}
199
200//-------------------------------------------------------------------
201
202int
203regular::inDescriptor() const
204{
205    pc::sync::stack pg(keeper);
206
207    if (handle->file == NULL)
208        dodo_throw exception::basic(exception::MODULE_IOFILEREGULAR, REGULAREX_INDESCRIPTOR, exception::ERRNO_LIBDODO, REGULAREX_NOTOPENED, IOFILEREGULAREX_NOTOPENED_STR, __LINE__, __FILE__, path);
209
210    return fileno(handle->file);
211}
212
213//-------------------------------------------------------------------
214
215int
216regular::outDescriptor() const
217{
218    pc::sync::stack pg(keeper);
219
220    if (handle->file == NULL)
221        dodo_throw exception::basic(exception::MODULE_IOFILEREGULAR, REGULAREX_OUTDESCRIPTOR, exception::ERRNO_LIBDODO, REGULAREX_NOTOPENED, IOFILEREGULAREX_NOTOPENED_STR, __LINE__, __FILE__, path);
222
223    return fileno(handle->file);
224}
225
226//-------------------------------------------------------------------
227
228void
229regular::clone(const regular &fd)
230{
231    pc::sync::stack pg(keeper);
232
233    if (handle->file !=  NULL) {
234        if (fclose(handle->file) != 0)
235            dodo_throw exception::basic(exception::MODULE_IOFILEREGULAR, REGULAREX_CLONE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
236
237        handle->file = NULL;
238    }
239
240    path = fd.path;
241    mode = fd.mode;
242    pos = fd.pos;
243    append = fd.append;
244    bs = fd.bs;
245
246    if (fd.handle->file !=  NULL) {
247        int oldDesc, newDesc;
248
249        oldDesc = fileno(fd.handle->file);
250        if (oldDesc == -1)
251            dodo_throw exception::basic(exception::MODULE_IOFILEREGULAR, REGULAREX_CLONE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
252
253        newDesc = dup(oldDesc);
254        if (newDesc == -1)
255            dodo_throw exception::basic(exception::MODULE_IOFILEREGULAR, REGULAREX_CLONE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
256
257        switch (mode) {
258            case OPEN_MODE_READ_WRITE:
259            case OPEN_MODE_READ_WRITE_TRUNCATE:
260
261                handle->file = fdopen(newDesc, "r+");
262
263                break;
264
265            case OPEN_MODE_READ_ONLY:
266            default:
267
268                handle->file = fdopen(newDesc, "r");
269        }
270
271        if (handle->file == NULL)
272            dodo_throw exception::basic(exception::MODULE_IOFILEREGULAR, REGULAREX_CLONE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
273    }
274}
275
276//-------------------------------------------------------------------
277
278void
279regular::close()
280{
281    pc::sync::stack pg(keeper);
282
283#ifndef IO_WO_XEXEC
284    performPreExec(OPERATION_CLOSE);
285#endif
286
287    if (handle->file !=  NULL) {
288        if (fclose(handle->file) != 0)
289            dodo_throw exception::basic(exception::MODULE_IOFILEREGULAR, REGULAREX_CLOSE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
290
291        handle->file = NULL;
292    }
293
294#ifndef IO_WO_XEXEC
295    performPostExec(OPERATION_CLOSE);
296#endif
297}
298
299//-------------------------------------------------------------------
300
301void
302regular::open(const dodo::string &a_path,
303              short            a_mode)
304{
305    pc::sync::stack pg(keeper);
306
307#ifndef IO_WO_XEXEC
308    performPreExec(OPERATION_OPEN);
309#endif
310
311    path = a_path;
312    mode = a_mode;
313
314    if (handle->file !=  NULL) {
315        if (fclose(handle->file) != 0)
316            dodo_throw exception::basic(exception::MODULE_IOFILEREGULAR, REGULAREX_OPEN, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
317
318        handle->file = NULL;
319    }
320
321    bool exists(false);
322
323    if (path.size() == 0)
324        dodo_throw exception::basic(exception::MODULE_IOFILEREGULAR, REGULAREX_OPEN, exception::ERRNO_LIBDODO, REGULAREX_WRONGFILENAME, IOFILEREGULAREX_WRONGFILENAME_STR, __LINE__, __FILE__, path);
325    else {
326        struct stat st;
327
328        if (::lstat(path.data(), &st) == -1) {
329            if (errno != ENOENT)
330                dodo_throw exception::basic(exception::MODULE_IOFILEREGULAR, REGULAREX_OPEN, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
331        } else
332            exists = true;
333
334        if (exists && !S_ISREG(st.st_mode) && !S_ISBLK(st.st_mode))
335            dodo_throw exception::basic(exception::MODULE_IOFILEREGULAR, REGULAREX_OPEN, exception::ERRNO_LIBDODO, REGULAREX_WRONGFILENAME, IOFILEREGULAREX_WRONGFILENAME_STR, __LINE__, __FILE__, path);
336
337        switch (mode) {
338            case OPEN_MODE_READ_WRITE:
339
340                handle->file = fopen(path.data(), "r+");
341                if (handle->file == NULL)
342                    handle->file = fopen(path.data(), "w+");
343
344                break;
345
346            case OPEN_MODE_READ_WRITE_TRUNCATE:
347
348                handle->file = fopen(path.data(), "w+");
349
350                break;
351
352            case OPEN_MODE_READ_ONLY:
353            default:
354
355                handle->file = fopen(path.data(), "r");
356        }
357    }
358
359    if (handle->file == NULL)
360        dodo_throw exception::basic(exception::MODULE_IOFILEREGULAR, REGULAREX_OPEN, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
361
362    if (!exists)
363        tools::filesystem::chmod(path, DEFAULT_FILE_PERM);
364
365#ifndef IO_WO_XEXEC
366    performPostExec(OPERATION_OPEN);
367#endif
368}
369
370//-------------------------------------------------------------------
371
372unsigned long
373regular::_read(char * const data) const
374{
375    if (handle->file == NULL)
376        dodo_throw exception::basic(exception::MODULE_IOFILEREGULAR, REGULAREX__READ, exception::ERRNO_LIBDODO, REGULAREX_NOTOPENED, IOFILEREGULAREX_NOTOPENED_STR, __LINE__, __FILE__, path);
377
378    if (fseek(handle->file, pos, SEEK_SET) == -1)
379        dodo_throw exception::basic(exception::MODULE_IOFILEREGULAR, REGULAREX__READ, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
380
381    char *s = data;
382
383    unsigned long batch = bs, n;
384
385    while (batch != 0) {
386        while (true) {
387            if ((n = fread(s, 1, batch, handle->file)) == 0) {
388                if (feof(handle->file) != 0 || errno == EAGAIN)
389                    return bs - batch;
390
391                if (errno == EINTR)
392                    continue;
393
394                if (ferror(handle->file) != 0)
395                    dodo_throw exception::basic(exception::MODULE_IOFILEREGULAR, REGULAREX__READ, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
396            }
397
398            break;
399        }
400
401        batch -= n;
402        s += n;
403    }
404
405    return bs - batch;
406}
407
408//-------------------------------------------------------------------
409
410unsigned long
411regular::_write(const char *const data) const
412{
413    if (handle->file == NULL)
414        dodo_throw exception::basic(exception::MODULE_IOFILEREGULAR, REGULAREX__WRITE, exception::ERRNO_LIBDODO, REGULAREX_NOTOPENED, IOFILEREGULAREX_NOTOPENED_STR, __LINE__, __FILE__, path);
415
416    if (append) {
417        if (fseek(handle->file, 0, SEEK_END) == -1)
418            dodo_throw exception::basic(exception::MODULE_IOFILEREGULAR, REGULAREX__WRITE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
419    } else {
420        if (fseek(handle->file, pos, SEEK_SET) == -1)
421            dodo_throw exception::basic(exception::MODULE_IOFILEREGULAR, REGULAREX__WRITE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
422    }
423
424    const char *s = data;
425
426    unsigned long batch = bs, n;
427
428    while (batch != 0) {
429        while (true) {
430            if ((n = fwrite(s, 1, batch, handle->file)) == 0) {
431                if (errno == EINTR)
432                    continue;
433
434                if (errno == EAGAIN)
435                    break;
436
437                if (ferror(handle->file) != 0)
438                    dodo_throw exception::basic(exception::MODULE_IOFILEREGULAR, REGULAREX__WRITE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
439            }
440
441            break;
442        }
443
444        batch -= n;
445        s += n;
446    }
447
448    return bs;
449}
450
451//-------------------------------------------------------------------
452
453void
454regular::erase()
455{
456    pc::sync::stack pg(keeper);
457
458    char *empty = new char[bs];
459
460    memset(empty, 0, bs);
461    dodo_try {
462        _write(empty);
463    } dodo_catch (exception::basic *e UNUSED) {
464        delete [] empty;
465
466        dodo_rethrow;
467    }
468
469    delete [] empty;
470}
471
472//-------------------------------------------------------------------
473
474void
475regular::flush() const
476{
477    pc::sync::stack pg(keeper);
478
479    if (handle->file == NULL)
480        dodo_throw exception::basic(exception::MODULE_IOFILEREGULAR, REGULAREX_FLUSH, exception::ERRNO_LIBDODO, REGULAREX_NOTOPENED, IOFILEREGULAREX_NOTOPENED_STR, __LINE__, __FILE__, path);
481
482    if (fflush(handle->file) != 0)
483        dodo_throw exception::basic(exception::MODULE_IOFILEREGULAR, REGULAREX_FLUSH, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
484}
485
486//-------------------------------------------------------------------
487
488unsigned long
489regular::_readString(char * const data) const
490{
491    if (handle->file == NULL)
492        dodo_throw exception::basic(exception::MODULE_IOFILEREGULAR, REGULAREX__READSTRING, exception::ERRNO_LIBDODO, REGULAREX_NOTOPENED, IOFILEREGULAREX_NOTOPENED_STR, __LINE__, __FILE__, path);
493
494    unsigned long readSize = bs + 1;
495
496    if (fseek(handle->file, pos, SEEK_SET) == -1)
497        dodo_throw exception::basic(exception::MODULE_IOFILEREGULAR, REGULAREX__READSTRING, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
498
499    while (true) {
500        if (fgets(data, readSize, handle->file) == NULL) {
501            if (errno == EINTR)
502                continue;
503
504            if (errno == EAGAIN)
505                break;
506
507            if (ferror(handle->file) != 0)
508                dodo_throw exception::basic(exception::MODULE_IOFILEREGULAR, REGULAREX__READSTRING, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
509        }
510
511        break;
512    }
513
514    return strlen(data);
515}
516
517//-------------------------------------------------------------------
518
519unsigned long
520regular::_writeString(const char *const data) const
521{
522    if (handle->file == NULL)
523        dodo_throw exception::basic(exception::MODULE_IOFILEREGULAR, REGULAREX__WRITESTRING, exception::ERRNO_LIBDODO, REGULAREX_NOTOPENED, IOFILEREGULAREX_NOTOPENED_STR, __LINE__, __FILE__, path);
524
525    if (fseek(handle->file, 0, SEEK_END) == -1)
526        dodo_throw exception::basic(exception::MODULE_IOFILEREGULAR, REGULAREX__WRITESTRING, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
527
528    unsigned long _bs = bs;
529    unsigned long written;
530
531    dodo_try {
532        bs = strnlen(data, bs);
533
534        written = _write(data);
535
536        bs = _bs;
537    } dodo_catch (exception::basic *e UNUSED) {
538        bs = _bs;
539
540        dodo_rethrow;
541    }
542
543    return written;
544}
545
546//-------------------------------------------------------------------
547
Note: See TracBrowser for help on using the repository browser.