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 <sys/stat.h>
19 #include <fcntl.h>
20 #include "SMFileFactory.h"
21 #include "SMDataFile.h"
22 #include "SMComm.h"
23 #include "BufferedFile.h"
24 #include "IDBDataFile.h"
25 
26 using namespace std;
27 
28 
29 namespace idbdatafile {
30 
open(const char * filename,const char * mode,unsigned opts,unsigned colWidth)31 IDBDataFile* SMFileFactory::open(const char *filename, const char *mode, unsigned opts, unsigned colWidth)
32 {
33     // TODO, test whether this breaks anything.
34     //if (opts & IDBDataFile::USE_TMPFILE)
35     //    return new BufferedFile(filename, mode, opts);
36 
37     bool _read = false;
38     bool _write = false;
39     bool create = false;
40     bool truncate = false;
41     bool append = false;
42 
43     // strip 'b' chars from mode
44     char newmode[8] = {'\0'};  // there'd better not be 7 chars in the mode string
45     int i = 0;
46     for (const char *c = mode; *c != '\0' && i < 8; c++)
47         if (*c != 'b')
48             newmode[i++] = *c;
49     if (i == 8) {
50         errno = EINVAL;
51         return NULL;
52     }
53 
54     // parse the new mode string
55     if (newmode[0] == 'r')
56     {
57         _read = true;
58         if (newmode[1] == '+')
59             _write = true;
60     }
61     else if (newmode[0] == 'w')
62     {
63         _write = true;
64         truncate = true;
65         create = true;
66         if (newmode[1] == '+')
67             _read = true;
68     }
69     else if (newmode[0] == 'a')
70     {
71         _write = true;
72         create = true;
73         append = true;
74         if (newmode[1] == '+')
75             _read = true;
76     }
77     else
78     {
79         errno = EINVAL;
80         return NULL;
81     }
82 
83     // turn newmode into posix flags
84     uint posix_flags = 0;
85     if (_read && _write)
86         posix_flags |= O_RDWR;
87     else if (_read)
88         posix_flags |= O_RDONLY;
89     else if (_write)
90         posix_flags |= O_WRONLY;
91 
92     posix_flags |= (create ? O_CREAT : 0);
93     posix_flags |= (truncate ? O_TRUNC : 0);
94     posix_flags |= (append ? O_APPEND : 0);
95 
96     SMComm *comm = SMComm::get();
97     struct stat _stat;
98     int err = comm->open(filename, posix_flags, &_stat);
99     if (err)
100         return NULL;
101 
102     SMDataFile *ret = new SMDataFile(filename, posix_flags, _stat);
103     return ret;
104 }
105 
106 
107 }
108