source: git/ppcc/adlib/os.cc

spielwiese
Last change on this file was aa4d31, checked in by Reimer Behrends <behrends@…>, 5 years ago
parallel preprocessor-related fixes.
  • Property mode set to 100644
File size: 10.3 KB
Line 
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  StrArr *result = new StrArr();
14  for (;;) {
15    size_t nbytes = fread(buffer, 1, sizeof(buffer), fp);
16    if (nbytes == 0)
17      break;
18    result->add(new Str(buffer, nbytes));
19  }
20  return StrJoin(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 *CurrentDir() {
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
391Str *AbsolutePath(Str *path) {
392  if (path->starts_with(PathSeparator)) {
393    return path->clone();
394  }
395  Str *result = CurrentDir();
396  return result->add(PathSeparator)->add(path);
397}
398
399Str *NormalizePath(Str *path) {
400  bool abs = path->starts_with(PathSeparator);
401  StrArr *parts = path->split(PathSeparator);
402  StrArr *result = new StrArr();
403  for (Int i = 0; i < parts->len(); i++) {
404    Str *part = parts->at(i);
405    if (part->eq("") || part->eq(".")) {
406      // do nothing
407    } else if (part->eq("..")) {
408      if (result->len() > 0)
409        result->pop();
410      else if (!abs)
411        result->add(part);
412    } else {
413      result->add(part);
414    }
415  }
416  if (abs)
417    return S(PathSeparator)->add(StrJoin(result, PathSeparator));
418  else
419    return StrJoin(result, PathSeparator);
420}
421
422Str *GetEnv(const char *name) {
423  char *result = getenv(name);
424  if (result)
425    return new Str(result);
426  else
427    return NULL;
428}
429
430Str *GetEnv(Str *name) {
431  return GetEnv(name->c_str());
432}
433
434Str *ProgramPath() {
435  Str *arg0 = new Str(ArgV[0]);
436  Str *result = arg0;
437  if (arg0) {
438    if (FileStat(result, true)) {
439      return NormalizePath(AbsolutePath(result));
440    }
441    if (!arg0->starts_with(PathSeparator)) {
442      Str *path = GetEnv("PATH");
443      StrArr *paths = path ? path->split(':') : A();
444      for (Int i = 0; i < paths->len(); i++) {
445        Str *p = paths->at(i)->clone();
446        p->add(PathSeparator);
447        p->add(arg0);
448        if (FileStat(p, true)) {
449          result = p;
450          break;
451        }
452      }
453    }
454  }
455  return result ? NormalizePath(AbsolutePath(result)) : result;
456}
457
458bool MakeDir(const char *path, bool recursive) {
459  if (!recursive)
460    return mkdir(path, 0777) >= 0;
461  return MakeDirRec(S(path));
462}
463
464bool MakeDir(Str *path, bool recursive) {
465  if (!recursive)
466    return mkdir(path->c_str(), 0777) >= 0;
467  return MakeDirRec(path);
468}
469
470bool RemoveDir(const char *path) {
471  return rmdir(path) >= 0;
472}
473
474bool RemoveDir(Str *path) {
475  return RemoveDir(path->c_str());
476}
477
478bool RemoveFile(const char *path) {
479  return unlink(path) >= 0;
480}
481
482bool RemoveFile(Str *path) {
483  return RemoveFile(path->c_str());
484}
485
486
487bool Rename(const char *path, const char *path2) {
488  return rename(path, path2) >= 0;
489}
490
491bool Rename(Str *path, Str *path2) {
492  return Rename(path->c_str(), path2->c_str());
493}
Note: See TracBrowser for help on using the repository browser.