From 7e6dadeb026f5e1975355e4c304502e1d63e887d Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Wed, 17 Aug 2011 16:09:05 +0000 Subject: [PATCH] Bug fix: stdio sizes > 4 TB - 32 kB caused integer rollover --- cdrskin/cdrskin_timestamp.h | 2 +- libburn/drive.c | 43 +++++++++++++++++++++---------------- libburn/libburn.h | 5 +++++ libburn/transport.h | 4 +++- 4 files changed, 34 insertions(+), 20 deletions(-) diff --git a/cdrskin/cdrskin_timestamp.h b/cdrskin/cdrskin_timestamp.h index db46c74..8ce1b60 100644 --- a/cdrskin/cdrskin_timestamp.h +++ b/cdrskin/cdrskin_timestamp.h @@ -1 +1 @@ -#define Cdrskin_timestamP "2011.08.08.121355" +#define Cdrskin_timestamP "2011.08.17.160854" diff --git a/libburn/drive.c b/libburn/drive.c index 37995d2..2491bbd 100644 --- a/libburn/drive.c +++ b/libburn/drive.c @@ -374,8 +374,13 @@ int burn_drive_grab(struct burn_drive *d, int le) if (stat_ret != -1 && S_ISREG(stbuf.st_mode) && stbuf.st_size > 0) { d->status = BURN_DISC_APPENDABLE; - d->role_5_nwa = stbuf.st_size / 2048 + - !!(stbuf.st_size % 2048); + if (stbuf.st_size / (off_t) 2048 + >= 0x7ffffff0) { + d->status = BURN_DISC_FULL; + d->role_5_nwa = 0x7ffffff0; + } else + d->role_5_nwa = stbuf.st_size / 2048 + + !!(stbuf.st_size % 2048); } else d->status = BURN_DISC_BLANK; } else { @@ -1464,13 +1469,14 @@ static int burn_drive__is_rdwr(char *fname, int *stat_ret, st_ret = stat(fname, &stbuf); if (st_ret != -1) { is_rdwr = burn_os_is_2k_seekrw(fname, 0); - if (S_ISREG(stbuf.st_mode)) + if (S_ISREG(stbuf.st_mode)) { read_size = stbuf.st_size; - else if (is_rdwr) { + ret = 1; + } else if (is_rdwr) ret = burn_os_stdio_capacity(fname, &read_size); - if (ret <= 0) - read_size = (off_t) 0x7ffffff0 * (off_t) 2048; - } + if (ret <= 0 || + read_size / (off_t) 2048 >= (off_t) 0x7ffffff0) + read_size = (off_t) 0x7ffffff0 * (off_t) 2048; } if (is_rdwr && fd >= 0) { @@ -1614,8 +1620,13 @@ int burn_drive_grab_dummy(struct burn_drive_info *drive_infos[], char *fname) (burn_drive_role_4_allowed & 8)) { d->status = BURN_DISC_APPENDABLE; d->block_types[BURN_WRITE_SAO] = 0; - d->role_5_nwa = stbuf.st_size / 2048 + - !!(stbuf.st_size % 2048); + if (stbuf.st_size / (off_t) 2048 + >= 0x7ffffff0) { + d->status = BURN_DISC_FULL; + d->role_5_nwa = 0x7ffffff0; + } else + d->role_5_nwa = stbuf.st_size / 2048 + + !!(stbuf.st_size % 2048); } else { d->status = BURN_DISC_BLANK; d->block_types[BURN_WRITE_SAO] = @@ -2713,11 +2724,7 @@ int burn_disc_get_multi_caps(struct burn_drive *d, enum burn_write_types wt, size = d->media_capacity_remaining; burn_os_stdio_capacity(d->devname, &size); burn_drive_set_media_capacity_remaining(d, size); - - /* >>> This looks wrong ! */ - /* >>> should add file size */ - o->start_range_high = size; - + o->start_range_high = d->media_capacity_remaining; o->start_alignment = 2048; /* imposting a drive, not a file */ o->might_do_sao = 4; o->might_do_tao = 2; @@ -2732,10 +2739,7 @@ int burn_disc_get_multi_caps(struct burn_drive *d, enum burn_write_types wt, /* >>> start_range_low = file size rounded to 2048 */; - /* >>> This looks wrong ! */ - /* >>> should add file size */ - o->start_range_high = size; - + o->start_range_high = d->media_capacity_remaining; o->start_alignment = 2048; /* imposting a drive, not a file */ if (s == BURN_DISC_APPENDABLE) { if (wt == BURN_WRITE_SAO || wt == BURN_WRITE_RAW) @@ -3148,10 +3152,13 @@ int burn_drive_find_by_thread_pid(struct burn_drive **d, pid_t pid, */ int burn_drive_set_media_capacity_remaining(struct burn_drive *d, off_t value) { + if (value / (off_t) 2048 > (off_t) 0x7ffffff0) + value = ((off_t) 0x7ffffff0) * (off_t) 2048; d->media_capacity_remaining = value; return 1; } + /* ts A81215 : API */ int burn_get_read_capacity(struct burn_drive *d, int *capacity, int flag) { diff --git a/libburn/libburn.h b/libburn/libburn.h index dc50332..3011a15 100644 --- a/libburn/libburn.h +++ b/libburn/libburn.h @@ -1393,6 +1393,9 @@ int burn_disc_get_msc1(struct burn_drive *d, int *start_lba); An eventual start address from burn_write_opts_set_start_byte() will be subtracted from the obtained capacity estimation. Negative results get defaulted to 0. + If the drive is actually a file in a large filesystem or a large block + device, then the capacity is curbed to a maximum of 0x7ffffff0 blocks + = 4 TB - 32 KB. @param d The drive to query. @param o If not NULL: write parameters to be set on drive before query @return number of most probably available free bytes @@ -3067,6 +3070,8 @@ int burn_random_access_write(struct burn_drive *d, off_t byte_address, can be read via burn_read_data() although some of them may never have been recorded. If tracks are recognizable then it is better to only read LBAs which are part of some track. + If the drive is actually a large file or block device, then the capacity + is curbed to a maximum of 0x7ffffff0 blocks = 4 TB - 32 KB. @param d The drive from which to read @param capacity Will return the result if valid @param flag Bitfield for control purposes: Unused yet, submit 0. diff --git a/libburn/transport.h b/libburn/transport.h index cfe8b9c..b8aa636 100644 --- a/libburn/transport.h +++ b/libburn/transport.h @@ -293,7 +293,9 @@ struct burn_drive int media_lba_limit; /* ts A81210 : Upper limit of readable data size, - 0x7fffffff = unknown */ + 0x7fffffff = unknown + 0x7ffffff0 = 32 bit overflow, or unknown stdio size + */ int media_read_capacity; /* ts B10314 : Next Writeable Adress for drive_role == 5 */