File: System.pike

package info (click to toggle)
pike7 7.0.361-3
  • links: PTS
  • area: main
  • in suites: woody
  • size: 14,876 kB
  • ctags: 12,334
  • sloc: ansic: 142,667; makefile: 1,526; sh: 1,035; lisp: 290; sed: 34; perl: 3
file content (198 lines) | stat: -rw-r--r-- 4,200 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
inherit Filesystem.Base;

static Filesystem.Base parent; // parent filesystem

static string root = ""; // neither leading nor trailing "/"
static string wd; // always one leading and no trailing "/"

void create(void|string directory,  // default: cwd
	    void|string _root,   // internal: root
	    void|int fast,       // internal: fast mode (no check)
	    void|Filesystem.Base _parent)
   				 // internal: parent filesystem
{
  if(_root)
  {
    sscanf(reverse(_root), "%*[\\/]%s", root);
    sscanf(reverse(root), "%*[/]%s", root);
  }

  if(!fast)
  {
    array(int) a;
    if(!directory || directory=="" || directory[0]!='/')
      directory = combine_path(getcwd(), directory||"");
    if(!(a = file_stat("/"+root+directory)) ||
       !((a[0]&0xF000)==0x4000))
      error("Not a directory\n");
  }

  sscanf(reverse(directory), "%*[\\/]%s", wd);
  wd = reverse(wd);
  if(wd=="")
    wd = "/";
}

string _sprintf()
{
  return sprintf("Filesystem.System(/* root=%O, wd=%O */)", root, wd);
}

Filesystem.Base cd(string directory)
{
  Filesystem.Stat st = stat(directory);
  if(!st) return 0;
  if(st->isdir()) // stay
    return this_class(combine_path(wd, directory),
		      root, 1, parent);
  return st->cd(); // try something else
}

Filesystem.Base cdup()
{
  return cd("..");
}

string cwd()
{
  return wd;
}

Filesystem.Base chroot(void|string directory)
{
  if(directory)
  {
    Filesystem.Base new = cd(directory);
    if(!new) return 0;
    return new->chroot();
  }
  return this_class("/", root+wd, 1, parent);
}

Filesystem.Stat stat(string file, int|void lstat)
{
   array(int) a;
   string full = combine_path(wd, file);

   if((a = file_stat("/"+root+full, lstat)))
   {
     Filesystem.Stat s = Filesystem.Stat();
     s->fullpath = full;
     s->name = file;
     s->filesystem = this_object();
     s->attach_statarray(a);
     return s;
   }
   else
     return 0;
}

array(string) get_dir(void|string directory, void|string|array(string) globs)
{
  directory = directory ? combine_path(wd, directory) : wd;

  array(string) y = predef::get_dir("/"+root+directory);
  if(!globs)
    return y;
  else if(stringp(globs))
    return glob(globs, y);
  else
  {
    array(string) p = ({});
    foreach(globs, string g)
    {
      array(string) z;
      p += (z = glob(g, y));
      y -= z;
    }
    return p;
  }
}

array(Filesystem.Stat) get_stats(void|string directory,
				 void|string|array(string) globs)
{
  Filesystem.Base z = this_object();
  if(directory &&
     !(z = z->cd(directory)))
    return 0;

  array(string) a = z->get_dir("", globs);
  if(!a) return 0;

  return Array.map(a, z->stat, 1)-({0});
}

Stdio.File open(string filename, string mode)
{
  filename = combine_path(wd, filename);
  Stdio.File f = Stdio.File();

  if(!f->open("/"+root+filename, mode))
    return 0;
  return f;
}

// int access(string filename, string mode)
// {
//   return 1; // sure
// }

int rm(string filename)
{
  filename = combine_path(wd, filename);
  return predef::rm("/"+root+filename);
}

void chmod(string filename, int|string mode)
{
  filename = combine_path(wd, filename);
  if(stringp(mode))
  {
    Filesystem.Stat st = stat(filename); // call to self
    if(!st) return 0;
    mode = Filesystem.parse_mode(st->mode, mode);
  }
  predef::chmod("/"+root+filename, mode);
}

void chown(string filename, int|object owner, int|object group)
{
#if constant(chown)
  if(objectp(group))
    error("user objects not supported (yet)\n");
  if(objectp(owner))
    error("user objects not supported (yet)\n");

  filename = combine_path(wd, filename);
  predef::chown("/"+root+wd, owner, group);
#else
  error("system does not have a chown"); // system does not have a chown()
#endif
}

array find(void|function(Filesystem.Stat:int) mask, mixed ... extra)
{
  array res = ({}),
	d = get_stats() || ({}),
	r = Array.filter(d, "isdir");

  if(mask)
    res += Array.filter(d-r, mask, @extra);
  else
    res += d-r;

  foreach(r, Filesystem.Base dir)
  {
    if(!mask)
      res += ({ dir });
    else if(mask(dir, @extra))
      res += ({ dir });

    if(dir->name=="." || dir->name=="..")
      continue;
    res += dir->cd()->find(mask, @extra);
  }

  return res;
}