Project

General

Profile

Bug #5714 » set_binmode_fix_r34120.patch

h.shirosaki (Hiroshi Shirosaki), 12/25/2011 11:17 PM

View differences:

io.c
# endif
#endif
#define rb_sys_fail_path(path) rb_sys_fail(NIL_P(path) ? 0 : RSTRING_PTR(path))
static int io_fflush(rb_io_t *);
#define NEED_NEWLINE_DECORATOR_ON_READ(fptr) ((fptr)->mode & FMODE_TEXTMODE)
......
ssize_t read_size;
long i;
long newlines = 0;
long extra_max;
char *p;
if (!rb_w32_fd_is_text((fptr)->fd)) return O_BINARY;
if (!rb_w32_fd_is_text(fptr->fd)) return O_BINARY;
if ((fptr)->rbuf.len == 0 || (fptr)->mode & FMODE_DUPLEX) {
setmode((fptr)->fd, O_BINARY);
return O_TEXT;
if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX) {
return setmode(fptr->fd, O_BINARY);
}
if (io_fflush(fptr) < 0) {
rb_sys_fail(0);
}
errno = 0;
pos = lseek((fptr)->fd, 0, SEEK_CUR);
pos = lseek(fptr->fd, 0, SEEK_CUR);
if (pos < 0 && errno) {
if (errno == ESPIPE)
(fptr)->mode |= FMODE_DUPLEX;
setmode((fptr)->fd, O_BINARY);
return O_TEXT;
fptr->mode |= FMODE_DUPLEX;
return setmode(fptr->fd, O_BINARY);
}
/* add extra offset for '\r' */
p = (fptr)->rbuf.ptr+(fptr)->rbuf.off;
for (i = 0; i < (fptr)->rbuf.len; i++) {
/* add extra offset for removed '\r' in rbuf */
extra_max = pos - fptr->rbuf.len;
p = fptr->rbuf.ptr + fptr->rbuf.off;
for (i = 0; i < fptr->rbuf.len; i++) {
if (*p == '\n') newlines++;
if (extra_max == newlines) break;
p++;
}
while (newlines >= 0) {
r = lseek((fptr)->fd, pos - (fptr)->rbuf.len - newlines, SEEK_SET);
r = lseek(fptr->fd, pos - fptr->rbuf.len - newlines, SEEK_SET);
if (newlines == 0) break;
if (read_size = _read((fptr)->fd, (fptr)->rbuf.ptr, (fptr)->rbuf.len + newlines)) {
if (read_size == (fptr)->rbuf.len) {
lseek((fptr)->fd, r, SEEK_SET);
break;
}
else {
newlines--;
}
if (r < 0) {
newlines--;
continue;
}
read_size = _read(fptr->fd, fptr->rbuf.ptr, fptr->rbuf.len + newlines);
if (read_size < 0) {
rb_sys_fail_path(fptr->pathv);
}
if (read_size == fptr->rbuf.len) {
lseek(fptr->fd, r, SEEK_SET);
break;
}
else {
newlines--;
}
}
(fptr)->rbuf.off = 0;
(fptr)->rbuf.len = 0;
setmode((fptr)->fd, O_BINARY);
return O_TEXT;
fptr->rbuf.off = 0;
fptr->rbuf.len = 0;
return setmode(fptr->fd, O_BINARY);
}
#define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) set_binary_mode_with_seek_cur(fptr)
......
#define shutdown(a,b) 0
#endif
#define rb_sys_fail_path(path) rb_sys_fail(NIL_P(path) ? 0 : RSTRING_PTR(path))
#if defined(_WIN32)
#define is_socket(fd, path) rb_w32_is_socket(fd)
#elif !defined(S_ISSOCK)
test/ruby/test_io_m17n.rb
end
}
end if /mswin|mingw/ =~ RUBY_PLATFORM
def test_seek_with_setting_binmode
with_tmpdir {
str = "a\r\nb\r\nc\r\n\r\n\n\n\n\n\n\n\n"
generate_file("tmp", str)
open("tmp", "r") do |f|
assert_equal("a\n", f.gets) # text
assert_equal("b\r\n", f.read(3)) # binary
end
}
end if /mswin|mingw/ =~ RUBY_PLATFORM
end
(6-6/6)