1 // Copyright (C) 2018 Bruce Guenter <bruce@untroubled.org>
2 //
3 // This program is free software; you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation; either version 2 of the License, or
6 // (at your option) any later version.
7 //
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16 
17 #include "fdbuf.h"
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <string.h>
21 #include <unistd.h>
22 
23 ///////////////////////////////////////////////////////////////////////////////
24 // Class fdbuf
25 ///////////////////////////////////////////////////////////////////////////////
fdbuf(int fdesc,bool dc,unsigned bufsz)26 fdbuf::fdbuf(int fdesc, bool dc, unsigned bufsz)
27   : buf(new char[bufsz]),
28     buflength(0),
29     bufstart(0),
30     offset(0),
31     errnum(0),
32     flags(0),
33     bufsize(bufsz),
34     fd(fdesc),
35     do_close(dc)
36 {
37   if(!buf) {
38     flags = flag_error;
39     errnum = errno;
40   }
41   if(fdesc < 0)
42     flags |= flag_closed;
43 #ifdef _REENTRANT
44   pthread_mutex_t tmp = PTHREAD_MUTEX_INITIALIZER;
45   mutex = tmp;
46   pthread_mutex_init(&mutex, 0);
47 #else
48 #ifdef FDBUF_MUTEX_DEBUG
49   mutex_count = 0;
50 #endif
51 #endif
52 }
53 
~fdbuf()54 fdbuf::~fdbuf()
55 {
56   close();
57 #ifdef _REENTRANT
58   pthread_mutex_destroy(&mutex);
59 #endif
60   delete buf;
61 }
62 
error() const63 bool fdbuf::error() const
64 {
65   return flags & flag_error;
66 }
67 
closed() const68 bool fdbuf::closed() const
69 {
70   return flags & flag_closed;
71 }
72 
close()73 bool fdbuf::close()
74 {
75   if(do_close && fd >= 0 && !(flags & flag_closed)) {
76     if(::close(fd) == -1) {
77       errnum = errno;
78       flags |= flag_error;
79       return false;
80     }
81     flags |= flag_closed;
82   }
83   return true;
84 }
85 
86 #if defined(FDBUF_MUTEX_DEBUG) && !defined(_REENTRANT)
87 {
88   int* null = 0;
89   (*null)++;
90   kill(getpid(), 9);
91 }
92 
93 // Debugging code
lock()94 void fdbuf::lock()
95 {
96   if(mutex)
97     abort();
98   ++mutex;
99 }
100 
unlock()101 void fdbuf::unlock()
102 {
103   if(mutex != 1)
104     abort();
105   --mutex;
106 }
107 #endif
108