Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 21 additions & 8 deletions file.c
Original file line number Diff line number Diff line change
Expand Up @@ -1945,13 +1945,19 @@ rb_file_socket_p(VALUE obj, VALUE fname)

/*
* call-seq:
* File.blockdev?(filepath) -> true or false
* File.blockdev?(object) -> true or false
*
* Returns +true+ if +filepath+ points to a block device, +false+ otherwise:
* Returns whether +object+ (a path or IO object)
* represents a block device (i.e., a direct-access device):
*
* File.blockdev?('/dev/sda1') # => true
* File.blockdev?(File.new('t.tmp')) # => false
* File.blockdev?('/dev/nvme0n1') # => true
* File.blockdev?('/dev/loop0') # => true
* File.blockdev?('/dev/tty') # => false
* File.blockdev?('/dev/null') # => false
* File.blockdev?('nosuch') # => false
* File.blockdev?($stdin) # => false
*
* The returned value is filesystem-dependent; on Windows, always +false+.
*/

static VALUE
Expand All @@ -1977,13 +1983,20 @@ rb_file_blockdev_p(VALUE obj, VALUE fname)

/*
* call-seq:
* File.chardev?(filepath) -> true or false
* File.chardev?(object) -> true or false
*
* Returns +true+ if +filepath+ points to a character device, +false+ otherwise.
* Returns whether +object+ (a path or IO object)
* represents a character device (i.e., a sequential-access device):
*
* File.chardev?($stdin) # => true
* File.chardev?('t.txt') # => false
* File.chardev?('/dev/tty') # => true
* File.chardev?('/dev/null') # => true
* File.chardev?($stdin) # => true
* File.chardev?('/dev/nvme0n1') # => false
* File.chardev?('/dev/loop0') # => false
* File.chardev?('nosuch') # => false
*
*
* The returned value is filesystem-dependent; on Windows, always +false+.
*/
static VALUE
rb_file_chardev_p(VALUE obj, VALUE fname)
Expand Down
61 changes: 57 additions & 4 deletions io_buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -345,13 +345,19 @@ get_io_buffer(VALUE self)
return buffer;
}

static bool
io_buffer_slice_p(struct rb_io_buffer *buffer)
{
return rb_typeddata_is_kind_of(buffer->source, &rb_io_buffer_type);
}

// Return the buffer which owns the lock count. A slice backed by another
// buffer shares that source buffer's lock count. Other external sources, such
// as strings, manage their own lifetime and do not share buffer lock state.
static struct rb_io_buffer *
io_buffer_lock_owner(struct rb_io_buffer *buffer)
{
if (rb_typeddata_is_kind_of(buffer->source, &rb_io_buffer_type)) {
if (io_buffer_slice_p(buffer)) {
return get_io_buffer(buffer->source);
}

Expand Down Expand Up @@ -1775,7 +1781,7 @@ rb_io_buffer_slice(struct rb_io_buffer *buffer, VALUE self, size_t offset, size_

// Slices retain their root buffer. If this buffer is already a slice,
// retain its root directly rather than building a chain of slices:
if (rb_typeddata_is_kind_of(buffer->source, &rb_io_buffer_type)) {
if (io_buffer_slice_p(buffer)) {
RB_OBJ_WRITE(instance, &slice->source, buffer->source);
}
else {
Expand Down Expand Up @@ -1911,11 +1917,52 @@ io_buffer_resize_copy(VALUE self, struct rb_io_buffer *buffer, size_t size)
*buffer = resized;
}

static void
io_buffer_resize_slice(struct rb_io_buffer *slice, size_t size)
{
struct rb_io_buffer *source = get_io_buffer(slice->source);

if (!io_buffer_validate(source)) {
rb_raise(rb_eIOBufferInvalidatedError, "Buffer is invalid!");
}

if (source->base == NULL || slice->base == NULL) {
rb_raise(rb_eIOBufferInvalidatedError, "Buffer is invalid!");
}

uintptr_t source_address = (uintptr_t)source->base;
uintptr_t slice_address = (uintptr_t)slice->base;

if (slice_address < source_address) {
rb_raise(rb_eIOBufferInvalidatedError, "Buffer is invalid!");
}

uintptr_t offset = slice_address - source_address;

if (offset > source->size) {
rb_raise(rb_eIOBufferInvalidatedError, "Buffer is invalid!");
}

if (size > source->size - (size_t)offset) {
rb_raise(rb_eArgError, "Resized slice exceeds its source buffer!");
}

// Validate the requested range rather than the current range so that
// shrinking a slice can restore its validity after the source shrinks.
slice->size = size;
}

void
rb_io_buffer_resize(VALUE self, size_t size)
{
struct rb_io_buffer *buffer = get_io_buffer(self);

if (io_buffer_slice_p(buffer)) {
// Resizing a slice only changes the view, not the locked allocation.
io_buffer_resize_slice(buffer, size);
return;
}

io_buffer_validate_for_reading(buffer);

if (io_buffer_locked(buffer)) {
Expand Down Expand Up @@ -1986,8 +2033,14 @@ rb_io_buffer_resize(VALUE self, size_t size)
* # #<IO::Buffer 0x0000555f5d1a1630+8 INTERNAL>
* # 0x00000000 74 65 73 74 00 00 00 00 test....
*
* External buffer (created with ::for), and locked buffer
* can not be resized.
* When the buffer is a slice, resizing changes the size of the view without
* modifying the source buffer or allocating new storage. The resized view
* must remain within the source buffer. Growing the view exposes the existing
* bytes in the source; they are not cleared. Because the source allocation
* does not change, a slice can be resized while its source is locked.
*
* External owning buffers (created with ::for), and locked owning buffers
* cannot be resized.
*/
static VALUE
io_buffer_resize(VALUE self, VALUE size)
Expand Down
4 changes: 1 addition & 3 deletions lib/rubygems/security/signer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,7 @@ def extract_name(cert) # :nodoc:
subject_alt_name = cert.extensions.find {|e| e.oid == "subjectAltName" }

if subject_alt_name
/\Aemail:/ =~ subject_alt_name.value # rubocop:disable Performance/StartWith

$' || subject_alt_name.value
subject_alt_name.value.delete_prefix("email:")
else
cert.subject
end
Expand Down
4 changes: 2 additions & 2 deletions pathname_builtin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2220,7 +2220,7 @@ class Pathname # * FileTest *
# Pathname($stdin).blockdev? # => false
# ```
#
# The returned value is OS-dependent; on Windows, almost always `false`.
# The returned value is filesystem-dependent; on Windows, always `false`.
def blockdev?() FileTest.blockdev?(@path) end

# :markup: markdown
Expand All @@ -2240,7 +2240,7 @@ def blockdev?() FileTest.blockdev?(@path) end
# Pathname('nosuch').chardev? # => false
# ```
#
# The returned value is OS-dependent; on Windows, almost always `false`.
# The returned value is filesystem-dependent; on Windows, always `false`.
def chardev?() FileTest.chardev?(@path) end

# :markup: markdown
Expand Down
Loading