1 /* Copyright (C) 2019 MariaDB Corporation
2 
3    This program is free software; you can redistribute it and/or
4    modify it under the terms of the GNU General Public License
5    as published by the Free Software Foundation; version 2 of
6    the License.
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., 51 Franklin Street, Fifth Floor, Boston,
16    MA 02110-1301, USA. */
17 
18 #include <fcntl.h>
19 
20 #include "SMDataFile.h"
21 
22 using namespace std;
23 
24 namespace idbdatafile
25 {
26 
~SMDataFile()27 SMDataFile::~SMDataFile()
28 {
29 }
30 
SMDataFile(const char * name,int _openmode,const struct stat & _stat)31 SMDataFile::SMDataFile(const char *name, int _openmode, const struct stat &_stat) :
32     IDBDataFile(name)
33 {
34     openmode = _openmode;
35     // the 'a' file open mode is the only one that starts at EOF
36     if ((openmode & O_APPEND) && !(openmode & O_RDWR))
37         position = _stat.st_size;
38     else
39         position = 0;
40     comm = SMComm::get();
41 }
42 
pread(void * buf,off64_t offset,size_t count)43 ssize_t SMDataFile::pread(void *buf, off64_t offset, size_t count)
44 {
45     return comm->pread(name(), buf, count, offset);
46 }
47 
read(void * buf,size_t count)48 ssize_t SMDataFile::read(void *buf, size_t count)
49 {
50     ssize_t ret = comm->pread(name(), buf, count, position);
51     if (ret < 0)
52         return ret;
53     position += ret;
54     return ret;
55 }
56 
write(const void * buf,size_t count)57 ssize_t SMDataFile::write(const void *buf, size_t count)
58 {
59     if (openmode & O_APPEND)
60         return comm->append(name(), buf, count);
61     ssize_t ret = comm->pwrite(name(), buf, count, position);
62     if (ret < 0)
63         return ret;
64     position += ret;
65     return ret;
66 }
67 
seek(off64_t offset,int whence)68 int SMDataFile::seek(off64_t offset, int whence)
69 {
70     switch (whence) {
71         case SEEK_SET:
72             position = offset;
73             break;
74         case SEEK_CUR:
75             position += offset;
76             break;
77         case SEEK_END:
78         {
79             struct stat _stat;
80             int err = comm->stat(name(), &_stat);
81             if (err)
82                 return err;
83             position = _stat.st_size + offset;
84             break;
85         }
86         default:
87             errno = EINVAL;
88             return -1;
89     }
90     return 0;
91 }
92 
truncate(off64_t length)93 int SMDataFile::truncate(off64_t length)
94 {
95     return comm->truncate(name(), length);
96 }
97 
fallocate(int mode,off64_t offset,off64_t length)98 int SMDataFile::fallocate(int mode, off64_t offset, off64_t length)
99 {
100     idbassert_s(mode == 0, "SMDataFile::fallocate() does not support mode != 0 right now.");
101     return comm->truncate(name(), offset + length);
102 }
103 
size()104 off64_t SMDataFile::size()
105 {
106     struct stat _stat;
107     int err = comm->stat(name(), &_stat);
108 
109     if (err)
110         return err;
111     return _stat.st_size;
112 }
113 
tell()114 off64_t SMDataFile::tell()
115 {
116     return position;
117 }
118 
flush()119 int SMDataFile::flush()
120 {
121     return 0;    // writes are synchronous b/c of replication.  If we allow asynchronous replication,
122                  // then we need to implement a flush() cmd in SMComm.
123 }
124 
mtime()125 time_t SMDataFile::mtime()
126 {
127     struct stat _stat;
128     int err = comm->stat(name(), &_stat);
129 
130     if (err)
131         return (time_t) err;
132     return _stat.st_mtime;
133 }
134 
close()135 int SMDataFile::close()
136 {
137     return 0;
138 }
139 
140 // constructor used for testing
SMDataFile(const char * fname,int _openmode,size_t fake_size)141 SMDataFile::SMDataFile(const char *fname, int _openmode, size_t fake_size)
142     : IDBDataFile(fname)
143 {
144     openmode = _openmode;
145     // the 'a' file open mode is the only one that starts at EOF
146     if ((openmode & O_APPEND) && !(openmode & O_RDWR))
147         position = fake_size;
148     else
149         position = 0;
150     comm = SMComm::get();
151 }
152 
153 }
154