1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 2016-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING.  If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 // These functions may be provided by gnulib.  We don't include gnulib
27 // headers directly in Octave's C++ source files to avoid problems that
28 // may be caused by the way that gnulib overrides standard library
29 // functions.
30 
31 #if defined (HAVE_CONFIG_H)
32 #  include "config.h"
33 #endif
34 
35 #include <time.h>
36 
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 
40 #include "stat-wrappers.h"
41 #include "uniconv-wrappers.h"
42 
43 #if defined (OCTAVE_USE_WINDOWS_API)
44 #  include <windows.h>
45 #  include <wchar.h>
46 #endif
47 
48 int
octave_mkdir_wrapper(const char * name,mode_t mode)49 octave_mkdir_wrapper (const char *name, mode_t mode)
50 {
51 #if defined (OCTAVE_USE_WINDOWS_API)
52   wchar_t *wname = u8_to_wchar (name);
53   int status = _wmkdir (wname);
54   free ((void *) wname);
55   octave_unused_parameter (mode);
56   return status;
57 #else
58   return mkdir (name, mode);
59 #endif
60 }
61 
62 int
octave_mkfifo_wrapper(const char * name,mode_t mode)63 octave_mkfifo_wrapper (const char *name, mode_t mode)
64 {
65   return mkfifo (name, mode);
66 }
67 
68 int
octave_umask_wrapper(mode_t mode)69 octave_umask_wrapper (mode_t mode)
70 {
71   return umask (mode);
72 }
73 
74 static inline void
assign_stat_fields(struct stat * buf,mode_t * mode,ino_t * ino,dev_t * dev,nlink_t * nlink,uid_t * uid,gid_t * gid,off_t * size,time_t * atime,time_t * mtime,time_t * ctime,dev_t * rdev,long * blksize,long * blocks)75 assign_stat_fields (struct stat *buf, mode_t *mode, ino_t *ino,
76                     dev_t *dev, nlink_t *nlink, uid_t *uid,
77                     gid_t *gid, off_t *size, time_t *atime,
78                     time_t *mtime, time_t *ctime, dev_t *rdev,
79                     long *blksize, long *blocks)
80 {
81   *mode = buf->st_mode;
82   *ino = buf->st_ino;
83   *dev = buf->st_dev;
84   *nlink = buf->st_nlink;
85   *uid = buf->st_uid;
86   *gid = buf->st_gid;
87   *size = buf->st_size;
88   *atime = buf->st_atime;
89   *mtime = buf->st_mtime;
90   *ctime = buf->st_ctime;
91 
92 #if defined (HAVE_STRUCT_STAT_ST_RDEV)
93   *rdev = buf->st_rdev;
94 #else
95   *rdev = 0;
96 #endif
97 
98 #if defined (HAVE_STRUCT_STAT_ST_BLKSIZE)
99   *blksize = buf->st_blksize;
100 #else
101   *blksize = 0;
102 #endif
103 
104 #if defined (HAVE_STRUCT_STAT_ST_BLOCKS)
105   *blocks = buf->st_blocks;
106 #else
107   *blocks = 0;
108 #endif
109 }
110 
111 int
octave_stat_wrapper(const char * fname,mode_t * mode,ino_t * ino,dev_t * dev,nlink_t * nlink,uid_t * uid,gid_t * gid,off_t * size,time_t * atime,time_t * mtime,time_t * ctime,dev_t * rdev,long * blksize,long * blocks)112 octave_stat_wrapper (const char *fname, mode_t *mode, ino_t *ino,
113                      dev_t *dev, nlink_t *nlink, uid_t *uid,
114                      gid_t *gid, off_t *size, time_t *atime,
115                      time_t *mtime, time_t *ctime, dev_t *rdev,
116                      long *blksize, long *blocks)
117 {
118   struct stat buf;
119 
120 #if defined (OCTAVE_USE_WINDOWS_API)
121   wchar_t *wfname = u8_to_wchar (fname);
122   int status = _wstati64 (wfname, &buf);
123   free ((void *) wfname);
124 #else
125   int status = stat (fname, &buf);
126 #endif
127 
128   assign_stat_fields (&buf, mode, ino, dev, nlink, uid, gid, size,
129                       atime, mtime, ctime, rdev, blksize, blocks);
130 
131   return status;
132 }
133 
134 int
octave_lstat_wrapper(const char * lname,mode_t * mode,ino_t * ino,dev_t * dev,nlink_t * nlink,uid_t * uid,gid_t * gid,off_t * size,time_t * atime,time_t * mtime,time_t * ctime,dev_t * rdev,long * blksize,long * blocks)135 octave_lstat_wrapper (const char *lname, mode_t *mode, ino_t *ino,
136                       dev_t *dev, nlink_t *nlink, uid_t *uid,
137                       gid_t *gid, off_t *size, time_t *atime,
138                       time_t *mtime, time_t *ctime, dev_t *rdev,
139                       long *blksize, long *blocks)
140 {
141   struct stat buf;
142 
143 #if defined (OCTAVE_USE_WINDOWS_API)
144   // Windows doesn't have an lstat. Use stat instead
145   wchar_t *wlname = u8_to_wchar (lname);
146   int status = _wstati64 (wlname, &buf);
147   free ((void *) wlname);
148 #else
149   int status = lstat (lname, &buf);
150 #endif
151 
152   assign_stat_fields (&buf, mode, ino, dev, nlink, uid, gid, size,
153                       atime, mtime, ctime, rdev, blksize, blocks);
154 
155   return status;
156 }
157 
158 int
octave_fstat_wrapper(int fid,mode_t * mode,ino_t * ino,dev_t * dev,nlink_t * nlink,uid_t * uid,gid_t * gid,off_t * size,time_t * atime,time_t * mtime,time_t * ctime,dev_t * rdev,long * blksize,long * blocks)159 octave_fstat_wrapper (int fid, mode_t *mode, ino_t *ino,
160                       dev_t *dev, nlink_t *nlink, uid_t *uid,
161                       gid_t *gid, off_t *size, time_t *atime,
162                       time_t *mtime, time_t *ctime, dev_t *rdev,
163                       long *blksize, long *blocks)
164 {
165   struct stat buf;
166 
167   int status = fstat (fid, &buf);
168 
169   assign_stat_fields (&buf, mode, ino, dev, nlink, uid, gid, size,
170                       atime, mtime, ctime, rdev, blksize, blocks);
171 
172   return status;
173 }
174 
175 #if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
176 // Disable the unused parameter warning for the following wrapper functions.
177 // The <sys/stat.h> header provided by gnulib may define some of the S_IS*
178 // macros to expand to a constant and ignore the parameter.
179 #pragma GCC diagnostic push
180 #pragma GCC diagnostic ignored "-Wunused-parameter"
181 #endif
182 
183 bool
octave_is_blk_wrapper(mode_t mode)184 octave_is_blk_wrapper (mode_t mode)
185 {
186 #if defined (S_ISBLK)
187   return S_ISBLK (mode);
188 #else
189   return false;
190 #endif
191 }
192 
193 bool
octave_is_chr_wrapper(mode_t mode)194 octave_is_chr_wrapper (mode_t mode)
195 {
196 #if defined (S_ISCHR)
197   return S_ISCHR (mode);
198 #else
199   return false;
200 #endif
201 }
202 
203 bool
octave_is_dir_wrapper(mode_t mode)204 octave_is_dir_wrapper (mode_t mode)
205 {
206 #if defined (S_ISDIR)
207   return S_ISDIR (mode);
208 #else
209   return false;
210 #endif
211 }
212 
213 bool
octave_is_fifo_wrapper(mode_t mode)214 octave_is_fifo_wrapper (mode_t mode)
215 {
216 #if defined (S_ISFIFO)
217   return S_ISFIFO (mode);
218 #else
219   return false;
220 #endif
221 }
222 
223 bool
octave_is_lnk_wrapper(mode_t mode)224 octave_is_lnk_wrapper (mode_t mode)
225 {
226 #if defined (S_ISLNK)
227   return S_ISLNK (mode);
228 #else
229   return false;
230 #endif
231 }
232 
233 bool
octave_is_reg_wrapper(mode_t mode)234 octave_is_reg_wrapper (mode_t mode)
235 {
236 #if defined (S_ISREG)
237   return S_ISREG (mode);
238 #else
239   return false;
240 #endif
241 }
242 
243 bool
octave_is_sock_wrapper(mode_t mode)244 octave_is_sock_wrapper (mode_t mode)
245 {
246 #if defined (S_ISSOCK)
247   return S_ISSOCK (mode);
248 #else
249   return false;
250 #endif
251 }
252 
253 #if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
254 // Restore prevailing warning state for remainder of the file.
255 #pragma GCC diagnostic pop
256 #endif
257 
258 bool
octave_have_struct_stat_st_rdev(void)259 octave_have_struct_stat_st_rdev (void)
260 {
261 #if defined (HAVE_STRUCT_STAT_ST_RDEV)
262   return true;
263 #else
264   return false;
265 #endif
266 }
267 
268 bool
octave_have_struct_stat_st_blksize(void)269 octave_have_struct_stat_st_blksize (void)
270 {
271 #if defined (HAVE_STRUCT_STAT_ST_BLKSIZE)
272   return true;
273 #else
274   return false;
275 #endif
276 }
277 
278 bool
octave_have_struct_stat_st_blocks(void)279 octave_have_struct_stat_st_blocks (void)
280 {
281 #if defined (HAVE_STRUCT_STAT_ST_BLOCKS)
282   return true;
283 #else
284   return false;
285 #endif
286 }
287