Project

General

Profile

Bug #5714 ยป set_binmode_fix_r34120.patch

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

View differences:

io.c
374 374
#  endif
375 375
#endif
376 376

  
377
#define rb_sys_fail_path(path) rb_sys_fail(NIL_P(path) ? 0 : RSTRING_PTR(path))
378

  
377 379
static int io_fflush(rb_io_t *);
378 380

  
379 381
#define NEED_NEWLINE_DECORATOR_ON_READ(fptr) ((fptr)->mode & FMODE_TEXTMODE)
......
423 425
    ssize_t read_size;
424 426
    long i;
425 427
    long newlines = 0;
428
    long extra_max;
426 429
    char *p;
427 430

  
428
    if (!rb_w32_fd_is_text((fptr)->fd)) return O_BINARY;
431
    if (!rb_w32_fd_is_text(fptr->fd)) return O_BINARY;
429 432

  
430
    if ((fptr)->rbuf.len == 0 || (fptr)->mode & FMODE_DUPLEX) {
431
	setmode((fptr)->fd, O_BINARY);
432
	return O_TEXT;
433
    if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX) {
434
	return setmode(fptr->fd, O_BINARY);
433 435
    }
434 436

  
435 437
    if (io_fflush(fptr) < 0) {
436 438
	rb_sys_fail(0);
437 439
    }
438 440
    errno = 0;
439
    pos = lseek((fptr)->fd, 0, SEEK_CUR);
441
    pos = lseek(fptr->fd, 0, SEEK_CUR);
440 442
    if (pos < 0 && errno) {
441 443
	if (errno == ESPIPE)
442
	    (fptr)->mode |= FMODE_DUPLEX;
443
	setmode((fptr)->fd, O_BINARY);
444
	return O_TEXT;
444
	    fptr->mode |= FMODE_DUPLEX;
445
	return setmode(fptr->fd, O_BINARY);
445 446
    }
446
    /* add extra offset for '\r' */
447
    p = (fptr)->rbuf.ptr+(fptr)->rbuf.off;
448
    for (i = 0; i < (fptr)->rbuf.len; i++) {
447
    /* add extra offset for removed '\r' in rbuf */
448
    extra_max = pos - fptr->rbuf.len;
449
    p = fptr->rbuf.ptr + fptr->rbuf.off;
450
    for (i = 0; i < fptr->rbuf.len; i++) {
449 451
	if (*p == '\n') newlines++;
452
	if (extra_max == newlines) break;
450 453
	p++;
451 454
    }
452 455
    while (newlines >= 0) {
453
	r = lseek((fptr)->fd, pos - (fptr)->rbuf.len - newlines, SEEK_SET);
456
	r = lseek(fptr->fd, pos - fptr->rbuf.len - newlines, SEEK_SET);
454 457
	if (newlines == 0) break;
455
	if (read_size = _read((fptr)->fd, (fptr)->rbuf.ptr, (fptr)->rbuf.len + newlines)) {
456
	    if (read_size == (fptr)->rbuf.len) {
457
		lseek((fptr)->fd, r, SEEK_SET);
458
		break;
459
	    }
460
	    else {
461
		newlines--;
462
	    }
458
	if (r < 0) {
459
	    newlines--;
460
	    continue;
461
	}
462
	read_size = _read(fptr->fd, fptr->rbuf.ptr, fptr->rbuf.len + newlines);
463
	if (read_size < 0) {
464
	    rb_sys_fail_path(fptr->pathv);
465
	}
466
	if (read_size == fptr->rbuf.len) {
467
	    lseek(fptr->fd, r, SEEK_SET);
468
	    break;
469
	}
470
	else {
471
	    newlines--;
463 472
	}
464 473
    }
465
    (fptr)->rbuf.off = 0;
466
    (fptr)->rbuf.len = 0;
467
    setmode((fptr)->fd, O_BINARY);
468
    return O_TEXT;
474
    fptr->rbuf.off = 0;
475
    fptr->rbuf.len = 0;
476
    return setmode(fptr->fd, O_BINARY);
469 477
}
470 478
#define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) set_binary_mode_with_seek_cur(fptr)
471 479

  
......
484 492
#define shutdown(a,b)	0
485 493
#endif
486 494

  
487
#define rb_sys_fail_path(path) rb_sys_fail(NIL_P(path) ? 0 : RSTRING_PTR(path))
488

  
489 495
#if defined(_WIN32)
490 496
#define is_socket(fd, path)	rb_w32_is_socket(fd)
491 497
#elif !defined(S_ISSOCK)
test/ruby/test_io_m17n.rb
2314 2314
      end
2315 2315
    }
2316 2316
  end if /mswin|mingw/ =~ RUBY_PLATFORM
2317

  
2318
  def test_seek_with_setting_binmode
2319
    with_tmpdir {
2320
      str = "a\r\nb\r\nc\r\n\r\n\n\n\n\n\n\n\n"
2321
      generate_file("tmp", str)
2322
      open("tmp", "r") do |f|
2323
        assert_equal("a\n", f.gets)      # text
2324
        assert_equal("b\r\n", f.read(3)) # binary
2325
      end
2326
    }
2327
  end if /mswin|mingw/ =~ RUBY_PLATFORM
2317 2328
end