• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 /**************************************************************************************************
3  * IOWOW library
4  *
5  * MIT License
6  *
7  * Copyright (c) 2012-2022 Softmotions Ltd <info@softmotions.com>
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining a copy
10  * of this software and associated documentation files (the "Software"), to deal
11  * in the Software without restriction, including without limitation the rights
12  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13  *  copies of the Software, and to permit persons to whom the Software is
14  * furnished to do so, subject to the following conditions:
15  *
16  * The above copyright notice and this permission notice shall be included in all
17  * copies or substantial portions of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25  * SOFTWARE.
26  *************************************************************************************************/
27 
28 
29 #include "log/iwlog.h"
30 #include "platform/iwp.h"
31 #include "utils/iwutils.h"
32 #include "utils/iwuuid.h"
33 #include <stdio.h>
34 
35 #if defined(_WIN32)
36 #include <libiberty/libiberty.h>
37 #include <direct.h>
38 #else
39 #include <libgen.h>
40 #endif
41 
42 #include <string.h>
43 
44 unsigned int iwcpuflags = 0;
45 static iwrc _iwp_init_impl(void);
46 
47 #if defined(__linux) || defined(__unix) || defined(__APPLE__)
48 #include "unix/unix.c"
49 #elif defined(_WIN32)
50 #include "win32/win32.c"
51 #else
52 #error Unsupported platform
53 #endif
54 
55 // Thanks to https://attractivechaos.wordpress.com/2017/09/04/on-cpu-dispatch
x86_simd(void)56 static unsigned int x86_simd(void) {
57 #if defined(__i386__) || defined(__amd64__)
58   unsigned int eax, ebx, ecx, edx, flag = 0;
59 # ifdef _MSC_VER
60   int cpuid[4];
61   __cpuid(cpuid, 1);
62   eax = cpuid[0], ebx = cpuid[1], ecx = cpuid[2], edx = cpuid[3];
63 # else
64   __asm volatile ("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (1));
65 # endif
66   if (edx >> 25 & 1) {
67     flag |= IWCPU_SSE;
68   }
69   if (edx >> 26 & 1) {
70     flag |= IWCPU_SSE2;
71   }
72   if (ecx >> 0 & 1) {
73     flag |= IWCPU_SSE3;
74   }
75   if (ecx >> 19 & 1) {
76     flag |= IWCPU_SSE4_1;
77   }
78   if (ecx >> 20 & 1) {
79     flag |= IWCPU_SSE4_2;
80   }
81   if (ecx >> 28 & 1) {
82     flag |= IWCPU_AVX;
83   }
84   if (ebx >> 5 & 1) {
85     flag |= IWCPU_AVX2;
86   }
87   if (ebx >> 16 & 1) {
88     flag |= IWCPU_AVX512F;
89   }
90   return flag;
91 #else
92   return 0;
93 #endif
94 }
95 
iwp_copy_bytes(HANDLE fh,off_t off,size_t siz,off_t noff)96 iwrc iwp_copy_bytes(HANDLE fh, off_t off, size_t siz, off_t noff) {
97   if (INVALIDHANDLE(fh)) {
98     return IW_ERROR_INVALID_HANDLE;
99   }
100   int overlap = IW_RANGES_OVERLAP(off, off + siz, noff, noff + siz);
101   size_t sp, sp2;
102   iwrc rc = 0;
103   off_t pos = 0;
104   uint8_t buf[4096];
105   if (overlap && (noff > off)) {
106     // todo resolve it!!
107     return IW_ERROR_OVERFLOW;
108   }
109 #if !defined(__APPLE__) && !defined(_WIN32)
110   if (siz > sizeof(buf)) {
111     posix_fadvise(fh, off, siz, POSIX_FADV_SEQUENTIAL);
112   }
113 #endif
114   while (pos < siz) {
115     rc = iwp_pread(fh, off + pos, buf, MIN(sizeof(buf), (siz - pos)), &sp);
116     if (rc || !sp) {
117       break;
118     } else {
119       rc = iwp_pwrite(fh, noff + pos, buf, sp, &sp2);
120       pos += sp;
121       if (rc) {
122         break;
123       }
124       if (sp != sp2) {
125         rc = IW_ERROR_INVALID_STATE;
126         break;
127       }
128     }
129   }
130 #if !defined(__APPLE__) && !defined(_WIN32)
131   if (siz > sizeof(buf)) {
132     posix_fadvise(fh, off, siz, POSIX_FADV_NORMAL);
133   }
134 #endif
135   return rc;
136 }
137 
iwp_allocate_tmpfile_path(const char * prefix)138 char* iwp_allocate_tmpfile_path(const char *prefix) {
139   size_t plen = prefix ? strlen(prefix) : 0;
140   char tmpdir[PATH_MAX + 1];
141   size_t tlen = iwp_tmpdir(tmpdir, sizeof(tmpdir));
142   if (!tlen) {
143     return 0;
144   }
145   char *res = malloc(tlen + sizeof(IW_PATH_STR) - 1 + plen + IW_UUID_STR_LEN + 1 /*NULL*/);
146   if (!res) {
147     return 0;
148   }
149   char *wp = res;
150   memcpy(wp, tmpdir, tlen);
151   wp += tlen;
152   memcpy(wp, IW_PATH_STR, sizeof(IW_PATH_STR) - 1);
153   wp += sizeof(IW_PATH_STR) - 1;
154   if (plen && prefix) {
155     memcpy(wp, prefix, plen);
156     wp += plen;
157   }
158   iwu_uuid4_fill(wp);
159   wp += IW_UUID_STR_LEN;
160   *wp = 0;
161   return res;
162 }
163 
iwp_dirname(char * path)164 char* iwp_dirname(char *path) {
165   return dirname(path);
166 }
167 
iwp_basename(char * path)168 char* iwp_basename(char *path) {
169   size_t i;
170   if (!path || !*path) {
171     return ".";
172   }
173   i = strlen(path) - 1;
174 #ifdef _WIN32
175   for ( ; i && (path[i] == '/' || path[i] == '\\'); i--) path[i] = 0;
176   for ( ; i && (path[i - 1] != '/' && path[i - 1] != '\\'); i--);
177  #else
178   for ( ; i && path[i] == '/'; i--) path[i] = 0;
179   for ( ; i && path[i - 1] != '/'; i--);
180  #endif
181   return path + i;
182 }
183 
iwp_mkdirs(const char * path)184 iwrc iwp_mkdirs(const char *path) {
185   /* Adapted from http://stackoverflow.com/a/2336245/119527 */
186   iwrc rc = 0;
187   const size_t len = strlen(path);
188   char buf[PATH_MAX];
189   char *p, *ppath = buf;
190 
191   errno = 0;
192   /* Copy string so its mutable */
193   if (len >= sizeof(buf)) {
194     ppath = malloc(len + 1);
195     if (!ppath) {
196       return iwrc_set_errno(IW_ERROR_ALLOC, errno);
197     }
198   }
199   memcpy(ppath, path, len + 1);
200 
201   /* Iterate the string */
202   for (p = ppath + 1; *p; p++) {
203 #ifdef _WIN32
204     if (*p == '/' || *p == '\\') {
205 #else
206     if (*p == '/') {
207 #endif
208       /* Temporarily truncate */
209       *p = '\0';
210       #if (defined(_WIN32) || defined(__WIN32__))
211       if (_mkdir(_path) != 0) {
212       #else
213       if (mkdir(ppath, S_IRWXU) != 0) {
214       #endif
215         if (errno != EEXIST) {
216           rc = iwrc_set_errno(IW_ERROR_ERRNO, errno);
217           goto finish;
218         }
219       }
220       *p = '/';
221     }
222   }
223   #if (defined(_WIN32) || defined(__WIN32__))
224   if (_mkdir(_path) != 0) {
225   #else
226   if (mkdir(ppath, S_IRWXU) != 0) {
227   #endif
228     if (errno != EEXIST) {
229       rc = iwrc_set_errno(IW_ERROR_ERRNO, errno);
230       goto finish;
231     }
232   }
233 
234 finish:
235   if (ppath != buf) {
236     free(ppath);
237   }
238   return rc;
239 }
240 
241 iwrc iwp_mkdirs_for_file(const char *path) {
242   char buf[PATH_MAX];
243   char *ppath = buf;
244   const size_t len = strlen(path);
245   if (len >= sizeof(buf)) {
246     ppath = malloc(len + 1);
247     if (!ppath) {
248       return iwrc_set_errno(IW_ERROR_ALLOC, errno);
249     }
250   }
251   memcpy(ppath, path, len + 1);
252   iwp_dirname(ppath);
253   iwrc rc = iwp_mkdirs(ppath);
254   if (ppath != buf) {
255     free(ppath);
256   }
257   return rc;
258 }
259 
260 iwrc iwp_init(void) {
261   iwcpuflags = x86_simd();
262   _iwp_init_impl();
263   return 0;
264 }
265