Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(10)

Side by Side Diff: Modules/_io/fileio.c

Issue 18876: Problems with files opened in append mode with io module
Patch Set: Created 6 years, 4 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« Lib/test/test_fileio.py ('K') | « Lib/test/test_fileio.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* Author: Daniel Stutzbach */ 1 /* Author: Daniel Stutzbach */
2 2
3 #define PY_SSIZE_T_CLEAN 3 #define PY_SSIZE_T_CLEAN
4 #include "Python.h" 4 #include "Python.h"
5 #include "structmember.h" 5 #include "structmember.h"
6 #ifdef HAVE_SYS_TYPES_H 6 #ifdef HAVE_SYS_TYPES_H
7 #include <sys/types.h> 7 #include <sys/types.h>
8 #endif 8 #endif
9 #ifdef HAVE_SYS_STAT_H 9 #ifdef HAVE_SYS_STAT_H
10 #include <sys/stat.h> 10 #include <sys/stat.h>
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 #else 42 #else
43 #define SMALLCHUNK BUFSIZ 43 #define SMALLCHUNK BUFSIZ
44 #endif 44 #endif
45 45
46 typedef struct { 46 typedef struct {
47 PyObject_HEAD 47 PyObject_HEAD
48 int fd; 48 int fd;
49 unsigned int created : 1; 49 unsigned int created : 1;
50 unsigned int readable : 1; 50 unsigned int readable : 1;
51 unsigned int writable : 1; 51 unsigned int writable : 1;
52 unsigned int appending : 1;
52 signed int seekable : 2; /* -1 means unknown */ 53 signed int seekable : 2; /* -1 means unknown */
53 unsigned int closefd : 1; 54 unsigned int closefd : 1;
54 char finalizing; 55 char finalizing;
55 PyObject *weakreflist; 56 PyObject *weakreflist;
56 PyObject *dict; 57 PyObject *dict;
57 } fileio; 58 } fileio;
58 59
59 PyTypeObject PyFileIO_Type; 60 PyTypeObject PyFileIO_Type;
60 61
61 #define PyFileIO_Check(op) (PyObject_TypeCheck((op), &PyFileIO_Type)) 62 #define PyFileIO_Check(op) (PyObject_TypeCheck((op), &PyFileIO_Type))
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 fileio *self; 150 fileio *self;
150 151
151 assert(type != NULL && type->tp_alloc != NULL); 152 assert(type != NULL && type->tp_alloc != NULL);
152 153
153 self = (fileio *) type->tp_alloc(type, 0); 154 self = (fileio *) type->tp_alloc(type, 0);
154 if (self != NULL) { 155 if (self != NULL) {
155 self->fd = -1; 156 self->fd = -1;
156 self->created = 0; 157 self->created = 0;
157 self->readable = 0; 158 self->readable = 0;
158 self->writable = 0; 159 self->writable = 0;
160 self->appending = 0;
159 self->seekable = -1; 161 self->seekable = -1;
160 self->closefd = 1; 162 self->closefd = 1;
161 self->weakreflist = NULL; 163 self->weakreflist = NULL;
162 } 164 }
163 165
164 return (PyObject *) self; 166 return (PyObject *) self;
165 } 167 }
166 168
167 /* On Unix, open will succeed for directories. 169 /* On Unix, open will succeed for directories.
168 In Python, there should be no file objects referring to 170 In Python, there should be no file objects referring to
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 fileio *self = (fileio *) oself; 214 fileio *self = (fileio *) oself;
213 static char *kwlist[] = {"file", "mode", "closefd", "opener", NULL}; 215 static char *kwlist[] = {"file", "mode", "closefd", "opener", NULL};
214 const char *name = NULL; 216 const char *name = NULL;
215 PyObject *nameobj, *stringobj = NULL, *opener = Py_None; 217 PyObject *nameobj, *stringobj = NULL, *opener = Py_None;
216 char *mode = "r"; 218 char *mode = "r";
217 char *s; 219 char *s;
218 #ifdef MS_WINDOWS 220 #ifdef MS_WINDOWS
219 Py_UNICODE *widename = NULL; 221 Py_UNICODE *widename = NULL;
220 #endif 222 #endif
221 int ret = 0; 223 int ret = 0;
222 int rwa = 0, plus = 0, append = 0; 224 int rwa = 0, plus = 0;
223 int flags = 0; 225 int flags = 0;
224 int fd = -1; 226 int fd = -1;
225 int closefd = 1; 227 int closefd = 1;
226 int fd_is_own = 0; 228 int fd_is_own = 0;
227 #ifdef O_CLOEXEC 229 #ifdef O_CLOEXEC
228 int *atomic_flag_works = &_Py_open_cloexec_works; 230 int *atomic_flag_works = &_Py_open_cloexec_works;
229 #elif !defined(MS_WINDOWS) 231 #elif !defined(MS_WINDOWS)
230 int *atomic_flag_works = NULL; 232 int *atomic_flag_works = NULL;
231 #endif 233 #endif
232 234
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 goto bad_mode; 312 goto bad_mode;
311 rwa = 1; 313 rwa = 1;
312 self->writable = 1; 314 self->writable = 1;
313 flags |= O_CREAT | O_TRUNC; 315 flags |= O_CREAT | O_TRUNC;
314 break; 316 break;
315 case 'a': 317 case 'a':
316 if (rwa) 318 if (rwa)
317 goto bad_mode; 319 goto bad_mode;
318 rwa = 1; 320 rwa = 1;
319 self->writable = 1; 321 self->writable = 1;
322
323 #ifdef O_APPEND
AntoinePitrou 2013/08/31 21:08:11 The original "#ifdef O_APPEND" was probably misgui
324 self->appending = 1;
325 flags |= O_APPEND;
326 #endif
327
320 flags |= O_CREAT; 328 flags |= O_CREAT;
321 append = 1;
322 break; 329 break;
323 case 'b': 330 case 'b':
324 break; 331 break;
325 case '+': 332 case '+':
326 if (plus) 333 if (plus)
327 goto bad_mode; 334 goto bad_mode;
328 self->readable = self->writable = 1; 335 self->readable = self->writable = 1;
329 plus = 1; 336 plus = 1;
330 break; 337 break;
331 default: 338 default:
(...skipping 10 matching lines...) Expand all
342 flags |= O_RDWR; 349 flags |= O_RDWR;
343 else if (self->readable) 350 else if (self->readable)
344 flags |= O_RDONLY; 351 flags |= O_RDONLY;
345 else 352 else
346 flags |= O_WRONLY; 353 flags |= O_WRONLY;
347 354
348 #ifdef O_BINARY 355 #ifdef O_BINARY
349 flags |= O_BINARY; 356 flags |= O_BINARY;
350 #endif 357 #endif
351 358
352 #ifdef O_APPEND
353 if (append)
354 flags |= O_APPEND;
355 #endif
356 #ifdef MS_WINDOWS 359 #ifdef MS_WINDOWS
357 flags |= O_NOINHERIT; 360 flags |= O_NOINHERIT;
358 #elif defined(O_CLOEXEC) 361 #elif defined(O_CLOEXEC)
359 flags |= O_CLOEXEC; 362 flags |= O_CLOEXEC;
360 #endif 363 #endif
361 364
362 if (fd >= 0) { 365 if (fd >= 0) {
363 if (check_fd(fd)) 366 if (check_fd(fd))
364 goto error; 367 goto error;
365 self->fd = fd; 368 self->fd = fd;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
425 goto error; 428 goto error;
426 429
427 #if defined(MS_WINDOWS) || defined(__CYGWIN__) 430 #if defined(MS_WINDOWS) || defined(__CYGWIN__)
428 /* don't translate newlines (\r\n <=> \n) */ 431 /* don't translate newlines (\r\n <=> \n) */
429 _setmode(self->fd, O_BINARY); 432 _setmode(self->fd, O_BINARY);
430 #endif 433 #endif
431 434
432 if (PyObject_SetAttrString((PyObject *)self, "name", nameobj) < 0) 435 if (PyObject_SetAttrString((PyObject *)self, "name", nameobj) < 0)
433 goto error; 436 goto error;
434 437
435 if (append) { 438 if (self->appending) {
436 /* For consistent behaviour, we explicitly seek to the 439 /* For consistent behaviour, we explicitly seek to the
437 end of file (otherwise, it might be done only on the 440 end of file (otherwise, it might be done only on the
438 first write()). */ 441 first write()). */
439 PyObject *pos = portable_lseek(self->fd, NULL, 2); 442 PyObject *pos = portable_lseek(self->fd, NULL, 2);
440 if (pos == NULL) 443 if (pos == NULL)
441 goto error; 444 goto error;
442 Py_DECREF(pos); 445 Py_DECREF(pos);
443 } 446 }
444 447
445 goto done; 448 goto done;
(...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after
1012 1015
1013 static char * 1016 static char *
1014 mode_string(fileio *self) 1017 mode_string(fileio *self)
1015 { 1018 {
1016 if (self->created) { 1019 if (self->created) {
1017 if (self->readable) 1020 if (self->readable)
1018 return "xb+"; 1021 return "xb+";
1019 else 1022 else
1020 return "xb"; 1023 return "xb";
1021 } 1024 }
1022 if (self->readable) { 1025 if (self->appending) {
1026 if (self->readable)
1027 return "ab+";
1028 else
1029 return "ab";
1030 }
1031 else if (self->readable) {
1023 if (self->writable) 1032 if (self->writable)
1024 return "rb+"; 1033 return "rb+";
1025 else 1034 else
1026 return "rb"; 1035 return "rb";
1027 } 1036 }
1028 else 1037 else
1029 return "wb"; 1038 return "wb";
1030 } 1039 }
1031 1040
1032 static PyObject * 1041 static PyObject *
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
1257 0, /* tp_is_gc */ 1266 0, /* tp_is_gc */
1258 0, /* tp_bases */ 1267 0, /* tp_bases */
1259 0, /* tp_mro */ 1268 0, /* tp_mro */
1260 0, /* tp_cache */ 1269 0, /* tp_cache */
1261 0, /* tp_subclasses */ 1270 0, /* tp_subclasses */
1262 0, /* tp_weaklist */ 1271 0, /* tp_weaklist */
1263 0, /* tp_del */ 1272 0, /* tp_del */
1264 0, /* tp_version_tag */ 1273 0, /* tp_version_tag */
1265 0, /* tp_finalize */ 1274 0, /* tp_finalize */
1266 }; 1275 };
OLDNEW
« Lib/test/test_fileio.py ('K') | « Lib/test/test_fileio.py ('k') | no next file » | no next file with comments »

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+