source: git/ppcc/adlib/os.cc @ 54b24c

spielwiese
Last change on this file since 54b24c was 54b24c, checked in by Reimer Behrends <behrends@…>, 5 years ago
Finalizing thread support.
  • Property mode set to 100644
File size: 8.7 KB
RevLine 
[54b24c]1#include "lib.h"
2
3#include <sys/stat.h>
4#include <limits.h>
5#ifdef HAVE_DIRENT_H
6#include <dirent.h>
7#endif
8
9Str *ReadFile(FILE *fp) {
10  char buffer[65536];
11  if (fp == NULL)
12    return NULL;
13  Str *result = new Str(1024);
14  for (;;) {
15    size_t nbytes = fread(buffer, 1, sizeof(buffer), fp);
16    if (nbytes == 0)
17      break;
18    result->add(buffer, nbytes);
19  }
20  return result;
21}
22
23Str *ReadFile(const char *filename) {
24  FILE *fp = fopen(filename, "r");
25  Str *result = ReadFile(fp);
26  fclose(fp);
27  return result;
28}
29
30Str *ReadFile(Str *filename) {
31  return ReadFile(filename->c_str());
32}
33
34int WriteFile(FILE *fp, Str *data) {
35  char *p = data->c_str();
36  Int len = data->len();
37  while (len != 0) {
38    Int written = fwrite(p, 1, len, fp);
39    if (written == 0)
40      return 0;
41    len -= written;
42    p += written;
43  }
44  return 1;
45}
46
47int WriteFile(const char *filename, Str *data) {
48  FILE *fp = fopen(filename, "w");
49  if (!fp)
50    return 0;
51  int success = WriteFile(fp, data);
52  fclose(fp);
53  return success;
54}
55
56int WriteFile(Str *filename, Str *data) {
57  return WriteFile(filename->c_str(), data);
58}
59
60StrArr *ReadLines(const char *filename) {
61  Str *contents = ReadFile(filename);
62  return contents->splitLines();
63}
64
65StrArr *ReadLines(Str *filename) {
66  return ReadLines(filename->c_str());
67}
68
69static char safe_chars[256];
70
71void InitSafeChars() {
72  for (int i = 'a'; i <= 'z'; i++)
73    safe_chars[i] = 1;
74  for (int i = 'A'; i <= 'Z'; i++)
75    safe_chars[i] = 1;
76  for (int i = '0'; i <= '9'; i++)
77    safe_chars[i] = 1;
78  const char *p = ",._+:@%/-";
79  while (*p)
80    safe_chars[(unsigned char) *p++] = 1;
81}
82
83INIT(_AdLibOS, InitSafeChars(););
84
85Str *ShellEscape(Str *arg) {
86  int safe = 1;
87  for (Int i = 0; i < arg->len(); i++) {
88    if (!safe_chars[arg->byte(i)]) {
89      safe = 0;
90      break;
91    }
92  }
93  if (safe)
94    return arg;
95  Str *result = new Str(arg->len());
96  result->add('\'');
97  for (Str::Each it(arg); it; ++it) {
98    if (*it == '\'')
99      result->add("'\\''");
100    else
101      result->add(*it);
102  }
103  result->add('\'');
104  return result;
105}
106
107Str *BuildCommand(Str *prog, StrArr *args) {
108  Str *command = new Str(1024);
109  command->add(ShellEscape(prog));
110  for (Int i = 0; i < args->len(); i++) {
111    command->add(' ')->add(ShellEscape(args->at(i)));
112  }
113  return command;
114}
115
116Str *ReadProcess(Str *prog, StrArr *args) {
117  Str *command = BuildCommand(prog, args);
118  FILE *pipe = popen(command->c_str(), "r");
119  if (!pipe)
120    return NULL;
121  Str *result = ReadFile(pipe);
122  if (pclose(pipe))
123    return NULL;
124  return result;
125}
126
127StrArr *ReadProcessLines(Str *prog, StrArr *args) {
128  Str *output = ReadProcess(prog, args);
129  return output->splitLines();
130}
131
132int WriteProcess(Str *prog, StrArr *args, Str *data) {
133  Str *command = BuildCommand(prog, args);
134  FILE *pipe = popen(command->c_str(), "w");
135  if (!pipe)
136    return 0;
137  int success = WriteFile(pipe, data);
138  if (pclose(pipe))
139    return 0;
140  return success;
141}
142
143int System(Str *prog, StrArr *args) {
144  Str *command = BuildCommand(prog, args);
145  int result = system(command->c_str());
146  if (result >= 256)
147    result >>= 8;
148  return result;
149}
150
151void Print(Str *str) {
152  printf("%s", str->c_str());
153}
154
155void PrintLn(Str *str) {
156  printf("%s\n", str->c_str());
157}
158
159void PrintErr(Str *str) {
160  fprintf(stderr, "%s", str->c_str());
161}
162
163void PrintErrLn(Str *str) {
164  fprintf(stderr, "%s\n", str->c_str());
165}
166
167void Print(const char *str) {
168  printf("%s", str);
169}
170
171void PrintLn(const char *str) {
172  printf("%s\n", str);
173}
174
175void PrintErr(const char *str) {
176  fprintf(stderr, "%s", str);
177}
178
179void PrintErrLn(const char *str) {
180  fprintf(stderr, "%s\n", str);
181}
182
183void Print(Int i) {
184  printf("%" WORD_FMT "d", i);
185}
186
187void PrintLn(Int i) {
188  printf("%" WORD_FMT "d\n", i);
189}
190
191void PrintErr(Int i) {
192  fprintf(stderr, "%" WORD_FMT "d", i);
193}
194
195void PrintErrLn(Int i) {
196  fprintf(stderr, "%" WORD_FMT "d\n", i);
197}
198
199Str *Pwd() {
200#ifdef PATH_MAX
201  char *path = getcwd(NULL, PATH_MAX);
202#else
203  char *path = getcwd(NULL, 8192);
204#endif
205  Str *result = new Str(path);
206  free(path);
207  return result;
208}
209
210bool ChDir(const char *path) {
211  return !chdir(path);
212}
213
214bool ChDir(Str *path) {
215  return ChDir(path->c_str());
216}
217
218bool FileStat(FileInfo &info, const char *path, bool follow_links) {
219  struct stat st;
220  if (follow_links) {
221    if (stat(path, &st) < 0)
222      return false;
223  } else {
224    if (lstat(path, &st) < 0)
225      return false;
226  }
227  memset(&info, 0, sizeof(info));
228  if (S_ISDIR(st.st_mode)) {
229    info.is_dir = true;
230  } else if (S_ISREG(st.st_mode)) {
231    info.is_file = true;
232  } else if (S_ISLNK(st.st_mode)) {
233    info.is_link = true;
234  } else {
235    info.is_other = true;
236  }
237  info.atime = st.st_atime;
238  info.mtime = st.st_mtime;
239  info.ctime = st.st_ctime;
240  info.size = st.st_size;
241  return true;
242}
243
244bool FileStat(FileInfo &info, Str *path, bool follow_links) {
245  return FileStat(info, path->c_str(), follow_links);
246}
247
248FileInfo *FileStat(const char *path, bool follow_links) {
249  FileInfo info;
250  if (FileStat(info, path, follow_links))
251    return new FileInfo(info);
252  else
253    return NULL;
254}
255
256FileInfo *FileStat(Str *path, bool follow_links) {
257  return FileStat(path->c_str(), follow_links);
258}
259
260StrArr *ListFiles(const char *path) {
261#ifdef HAVE_DIRENT_H
262  StrArr *result = new StrArr();
263  DIR *dir = opendir(path);
264  if (!dir)
265    return NULL;
266  for (;;) {
267    struct dirent *entry = readdir(dir);
268    if (!entry)
269      break;
270    if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
271      continue;
272    result->add(new Str(entry->d_name));
273  }
274  closedir(dir);
275  return result;
276#else
277  return NULL;
278#endif
279}
280
281StrArr *ListFiles(Str *path) {
282  return ListFiles(path->c_str());
283}
284
285static void WalkDir(StrArr *acc, const char *path, int mode) {
286  StrArr *files = ListFiles(path);
287  if (!files)
288    return;
289  FileInfo info;
290  for (Int i = 0; i < files->len(); i++) {
291    Str *newpath = new Str(path);
292    if (!newpath->ends_with(PathSeparator))
293      newpath->add(PathSeparator);
294    newpath->add(files->at(i));
295    if (FileStat(info, newpath)) {
296      if (info.is_dir) {
297        newpath->add(PathSeparator);
298        WalkDir(acc, newpath->c_str(), mode);
299        if (mode & ListFilesAndDirs)
300          acc->add(newpath);
301      } else {
302        acc->add(newpath);
303      }
304    }
305  }
306}
307
308StrArr *ListFileTree(const char *path, int mode) {
309  StrArr *result = new StrArr();
310  FileInfo info;
311  if (FileStat(info, path, true)) {
312    if (info.is_dir) {
313      Str *dir = new Str(path);
314      if (!dir->ends_with(PathSeparator))
315        dir->add(PathSeparator);
316      Int prefixlen = dir->len();
317      result->add(dir);
318      WalkDir(result, dir->c_str(), mode);
319      if (mode & ListFilesRelative) {
320        for (Int i = 0; i < result->len(); i++) {
321          result->at(i)->remove(0, prefixlen);
322        }
323      }
324    } else {
325      if ((mode & ListFilesRelative) == 0)
326        result->add(S(path));
327    }
328  }
329  return result;
330}
331
332StrArr *ListFileTree(Str *path, int mode) {
333  return ListFileTree(path->c_str(), mode);
334}
335
336Str *DirName(Str *path) {
337  Int pos = path->rfind(PathSeparator);
338  if (pos == NOWHERE) {
339    return path->clone();
340  } else {
341    return path->range_excl(0, pos);
342  }
343}
344
345Str *BaseName(Str *path) {
346  Int pos = path->rfind(PathSeparator);
347  if (pos == NOWHERE) {
348    return path->clone();
349  } else {
350    return path->range_excl(pos+1, path->len());
351  }
352}
353
354Str *FileExtension(Str *path) {
355  Int slash = path->rfind(PathSeparator);
356  Int dot = path->rfind('.');
357  if (dot == NOWHERE || dot < slash) {
358    return S("");
359  } else {
360    return path->range_excl(dot, path->len());
361  }
362}
363
364
365static bool MakeDirRec(Str *path) {
366  FileInfo info;
367  path = path->clone();
368  for (Int i = 1; i < path->len();) {
369    Int p = path->find(PathSeparator, i);
370    if (p == NOWHERE)
371      break;
372    path->at(p) = '\0';
373    if (FileStat(info, path, true)) {
374      if (!info.is_dir)
375        return false;
376    } else if (mkdir(path->c_str(), 0777) < 0) {
377      return false;
378    }
379    path->at(p) = PathSeparator[0];
380    i = p+1;
381  }
382  if (FileStat(info, path, true)) {
383    if (!info.is_dir)
384      return false;
385  } else if (mkdir(path->c_str(), 0777) < 0) {
386    return false;
387  }
388  return true;
389}
390
391bool MakeDir(const char *path, bool recursive) {
392  if (!recursive)
393    return mkdir(path, 0777) >= 0;
394  return MakeDirRec(S(path));
395}
396
397bool MakeDir(Str *path, bool recursive) {
398  if (!recursive)
399    return mkdir(path->c_str(), 0777) >= 0;
400  return MakeDirRec(path);
401}
402
403bool RemoveDir(const char *path) {
404  return rmdir(path) >= 0;
405}
406
407bool RemoveDir(Str *path) {
408  return RemoveDir(path->c_str());
409}
410
411bool RemoveFile(const char *path) {
412  return unlink(path) >= 0;
413}
414
415bool RemoveFile(Str *path) {
416  return RemoveFile(path->c_str());
417}
418
419
420bool Rename(const char *path, const char *path2) {
421  return rename(path, path2) >= 0;
422}
423
424bool Rename(Str *path, Str *path2) {
425  return Rename(path->c_str(), path2->c_str());
426}
Note: See TracBrowser for help on using the repository browser.