blob: 255b23e67a9b751d8031b939548798ba22dbd086 [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001/***********************************************************
2Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
3Netherlands.
4
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000025/* File object implementation */
26
Guido van Rossumdd5c7be1990-10-26 14:58:11 +000027/* XXX This should become a built-in module 'io'. It should support more
28 functionality, better exception handling for invalid calls, etc.
Guido van Rossum3f5da241990-12-20 15:06:42 +000029 (Especially reading on a write-only file or vice versa!)
Guido van Rossumdd5c7be1990-10-26 14:58:11 +000030 It should also cooperate with posix to support popen(), which should
31 share most code but have a special close function. */
32
Guido van Rossum3f5da241990-12-20 15:06:42 +000033#include "allobjects.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000034
Guido van Rossumce5ba841991-03-06 13:06:18 +000035#define BUF(v) GETSTRINGVALUE((stringobject *)v)
36
Guido van Rossum3f5da241990-12-20 15:06:42 +000037#include "errno.h"
38#ifndef errno
39extern int errno;
40#endif
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000041
42typedef struct {
43 OB_HEAD
44 FILE *f_fp;
45 object *f_name;
46 object *f_mode;
Guido van Rossumeb183da1991-04-04 10:44:06 +000047 int f_softspace; /* Flag used by 'print' command */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000048} fileobject;
49
50FILE *
51getfilefile(f)
52 object *f;
53{
54 if (!is_fileobject(f)) {
Guido van Rossum3f5da241990-12-20 15:06:42 +000055 err_badcall();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000056 return NULL;
57 }
58 return ((fileobject *)f)->f_fp;
59}
60
61object *
62newopenfileobject(fp, name, mode)
63 FILE *fp;
64 char *name;
65 char *mode;
66{
67 fileobject *f = NEWOBJ(fileobject, &Filetype);
68 if (f == NULL)
69 return NULL;
70 f->f_fp = NULL;
71 f->f_name = newstringobject(name);
72 f->f_mode = newstringobject(mode);
Guido van Rossumeb183da1991-04-04 10:44:06 +000073 f->f_softspace = 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000074 if (f->f_name == NULL || f->f_mode == NULL) {
75 DECREF(f);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000076 return NULL;
77 }
78 f->f_fp = fp;
79 return (object *) f;
80}
81
82object *
83newfileobject(name, mode)
84 char *name, *mode;
85{
86 fileobject *f;
87 FILE *fp;
88 f = (fileobject *) newopenfileobject((FILE *)NULL, name, mode);
89 if (f == NULL)
90 return NULL;
Guido van Rossuma08095a1991-02-13 23:25:27 +000091#ifdef THINK_C
92 if (*mode == '*') {
93 FILE *fopenRF();
94 f->f_fp = fopenRF(name, mode+1);
95 }
96 else
97#endif
98 f->f_fp = fopen(name, mode);
99 if (f->f_fp == NULL) {
100 err_errno(RuntimeError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000101 DECREF(f);
102 return NULL;
103 }
104 return (object *)f;
105}
106
107/* Methods */
108
109static void
Guido van Rossum3f5da241990-12-20 15:06:42 +0000110file_dealloc(f)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000111 fileobject *f;
112{
113 if (f->f_fp != NULL)
114 fclose(f->f_fp);
115 if (f->f_name != NULL)
116 DECREF(f->f_name);
117 if (f->f_mode != NULL)
118 DECREF(f->f_mode);
119 free((char *)f);
120}
121
122static void
Guido van Rossum3f5da241990-12-20 15:06:42 +0000123file_print(f, fp, flags)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000124 fileobject *f;
125 FILE *fp;
126 int flags;
127{
128 fprintf(fp, "<%s file ", f->f_fp == NULL ? "closed" : "open");
129 printobject(f->f_name, fp, flags);
130 fprintf(fp, ", mode ");
131 printobject(f->f_mode, fp, flags);
132 fprintf(fp, ">");
133}
134
135static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000136file_repr(f)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000137 fileobject *f;
138{
139 char buf[300];
Guido van Rossum3f5da241990-12-20 15:06:42 +0000140 /* XXX This differs from file_print if the filename contains
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000141 quotes or other funny characters. */
142 sprintf(buf, "<%s file '%.256s', mode '%.10s'>",
143 f->f_fp == NULL ? "closed" : "open",
144 getstringvalue(f->f_name),
145 getstringvalue(f->f_mode));
146 return newstringobject(buf);
147}
148
149static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000150file_close(f, args)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000151 fileobject *f;
152 object *args;
153{
154 if (args != NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000155 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000156 return NULL;
157 }
158 if (f->f_fp != NULL) {
159 fclose(f->f_fp);
160 f->f_fp = NULL;
161 }
162 INCREF(None);
163 return None;
164}
165
166static object *
Guido van Rossumce5ba841991-03-06 13:06:18 +0000167file_seek(f, args)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000168 fileobject *f;
169 object *args;
170{
Guido van Rossumce5ba841991-03-06 13:06:18 +0000171 long offset;
172 long whence;
173
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000174 if (f->f_fp == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000175 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000176 return NULL;
177 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000178 if (args != NULL && is_intobject(args)) {
179 offset = getintvalue(args);
180 whence = 0; /* SEEK_SET */
181 }
182 else {
183 if (!getlonglongargs(args, &offset, &whence))
184 return NULL;
185 }
186 errno = 0;
187 if (fseek(f->f_fp, offset, (int)whence) != 0) {
188 if (errno == 0)
189 errno = EIO;
190 return err_errno(RuntimeError);
191 }
192 INCREF(None);
193 return None;
194}
195
196static object *
197file_tell(f, args)
198 fileobject *f;
199 object *args;
200{
201 long offset;
202 if (args != NULL || f->f_fp == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000203 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000204 return NULL;
205 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000206 errno = 0;
207 offset = ftell(f->f_fp);
208 if (offset == -1L) {
209 if (errno == 0)
210 errno = EIO;
211 return err_errno(RuntimeError);
212 }
213 return newintobject(offset);
214}
215
216static object *
217file_flush(f, args)
218 fileobject *f;
219 object *args;
220{
221 if (args != NULL || f->f_fp == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000222 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000223 return NULL;
224 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000225 errno = 0;
226 if (fflush(f->f_fp) != 0) {
227 if (errno == 0)
228 errno = EIO;
229 return err_errno(RuntimeError);
230 }
231 INCREF(None);
232 return None;
233}
234
235static object *
236file_read(f, args)
237 fileobject *f;
238 object *args;
239{
240 int n, n1, n2, n3;
241 object *v;
242
243 if (f->f_fp == NULL) {
244 err_badarg();
245 return NULL;
246 }
247 if (args == 0)
248 n = 0;
249 else {
250 if (!getintarg(args, &n))
251 return NULL;
252 if (n < 0) {
253 err_badarg();
254 return NULL;
255 }
256 }
257
258 n2 = n != 0 ? n : BUFSIZ;
259 v = newsizedstringobject((char *)NULL, n2);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000260 if (v == NULL)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000261 return NULL;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000262 n1 = 0;
263 for (;;) {
264 n3 = fread(BUF(v)+n1, 1, n2-n1, f->f_fp);
265 /* XXX Error check? */
266 if (n3 == 0)
267 break;
268 n1 += n3;
269 if (n1 == n)
270 break;
271 if (n == 0) {
272 n2 = n1 + BUFSIZ;
273 if (resizestring(&v, n2) < 0)
274 return NULL;
275 }
276 }
277 if (n1 != n2)
278 resizestring(&v, n1);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000279 return v;
280}
281
Guido van Rossumce5ba841991-03-06 13:06:18 +0000282/* Read a line.
283 Without argument, or with a zero argument, read until end of line
284 or EOF, whichever comes first.
285 With a positive argument n, read at most n bytes until end of line
286 or EOF, whichever comes first.
287 Negative and non-integer arguments are illegal.
288 When EOF is hit immediately, return an empty string.
289 A newline character is returned as the last character of the buffer
290 if it is read.
291*/
292
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000293/* XXX Should this be unified with raw_input()? */
294
295static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000296file_readline(f, args)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000297 fileobject *f;
298 object *args;
299{
Guido van Rossumce5ba841991-03-06 13:06:18 +0000300 register FILE *fp;
301 register int c;
302 register char *buf, *end;
303 int n, n1, n2;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000304 object *v;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000305
306 if ((fp = f->f_fp) == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000307 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000308 return NULL;
309 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000310
311 if (args == NULL)
312 n = 0; /* Unlimited */
313 else {
314 if (!getintarg(args, &n))
315 return NULL;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000316 if (n < 0) {
317 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000318 return NULL;
319 }
320 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000321
322 n2 = n != 0 ? n : 100;
323 v = newsizedstringobject((char *)NULL, n2);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000324 if (v == NULL)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000325 return NULL;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000326 buf = BUF(v);
327 end = buf + n2;
328
329 for (;;) {
330 if ((c = getc(fp)) == EOF || (*buf++ = c) == '\n')
331 break;
332 /* XXX Error check? */
333 if (buf == end) {
334 if (n != 0)
335 break;
336 n1 = n2;
337 n2 += 1000;
338 if (resizestring(&v, n2) < 0)
339 return NULL;
340 buf = BUF(v) + n1;
341 end = BUF(v) + n2;
342 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000343 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000344
345 n1 = buf - BUF(v);
346 if (n1 != n2)
347 resizestring(&v, n1);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000348 return v;
349}
350
351static object *
Guido van Rossumce5ba841991-03-06 13:06:18 +0000352file_readlines(f, args)
353 fileobject *f;
354 object *args;
355{
356 object *list;
357 object *line;
358
359 if ((list = newlistobject(0)) == NULL)
360 return NULL;
361 for (;;) {
362 line = file_readline(f, args);
363 if (line != NULL && getstringsize(line) == 0) {
364 DECREF(line);
365 break;
366 }
367 if (line == NULL || addlistitem(list, line) != 0) {
368 DECREF(list);
369 XDECREF(line);
370 return NULL;
371 }
372 DECREF(line);
373 }
374 return list;
375}
376
377static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000378file_write(f, args)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000379 fileobject *f;
380 object *args;
381{
382 int n, n2;
383 if (f->f_fp == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000384 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000385 return NULL;
386 }
387 if (args == NULL || !is_stringobject(args)) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000388 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000389 return NULL;
390 }
Guido van Rossumeb183da1991-04-04 10:44:06 +0000391 f->f_softspace = 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000392 errno = 0;
393 n2 = fwrite(getstringvalue(args), 1, n = getstringsize(args), f->f_fp);
394 if (n2 != n) {
395 if (errno == 0)
396 errno = EIO;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000397 err_errno(RuntimeError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000398 return NULL;
399 }
400 INCREF(None);
401 return None;
402}
403
Guido van Rossum3f5da241990-12-20 15:06:42 +0000404static struct methodlist file_methods[] = {
Guido van Rossumce5ba841991-03-06 13:06:18 +0000405 {"close", file_close},
406 {"flush", file_flush},
Guido van Rossum3f5da241990-12-20 15:06:42 +0000407 {"read", file_read},
408 {"readline", file_readline},
Guido van Rossumce5ba841991-03-06 13:06:18 +0000409 {"readlines", file_readlines},
410 {"seek", file_seek},
411 {"tell", file_tell},
412 {"write", file_write},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000413 {NULL, NULL} /* sentinel */
414};
415
416static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000417file_getattr(f, name)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000418 fileobject *f;
419 char *name;
420{
Guido van Rossum3f5da241990-12-20 15:06:42 +0000421 return findmethod(file_methods, (object *)f, name);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000422}
423
424typeobject Filetype = {
425 OB_HEAD_INIT(&Typetype)
426 0,
427 "file",
428 sizeof(fileobject),
429 0,
Guido van Rossum3f5da241990-12-20 15:06:42 +0000430 file_dealloc, /*tp_dealloc*/
431 file_print, /*tp_print*/
432 file_getattr, /*tp_getattr*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000433 0, /*tp_setattr*/
434 0, /*tp_compare*/
Guido van Rossum3f5da241990-12-20 15:06:42 +0000435 file_repr, /*tp_repr*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000436};
Guido van Rossumeb183da1991-04-04 10:44:06 +0000437
438/* Interface for the 'soft space' between print items. */
439
440int
441softspace(f, newflag)
442 object *f;
443 int newflag;
444{
445 int oldflag = 0;
446 if (f != NULL && is_fileobject(f)) {
447 oldflag = ((fileobject *)f)->f_softspace;
448 ((fileobject *)f)->f_softspace = newflag;
449 }
450 return oldflag;
451}