Skip to content

Commit 66ac6d1

Browse files
committed
new interface for creating uninitalized or zero stat objects
1 parent 9dfe177 commit 66ac6d1

File tree

6 files changed

+63
-9
lines changed

6 files changed

+63
-9
lines changed

Changes

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
Revision history for {{$dist->name}}
22

33
{{$NEXT}}
4+
- Passing no arguments to new will now return an
5+
uninitialized stat object (gh#9, gh#10)
6+
- Passing undef to clone will now return a stat
7+
object with the memory set to all zeros,
8+
previously the behavior was undefined and could
9+
crash (gh#10)
410

511
0.02 2021-05-31 05:48:05 -0600
612
- Work around possible bug in Perl stat function

README.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,12 @@ $ffi->attach( my_cfunction => ['stat'] => 'void' );
4646
```perl
4747
my $stat = FFI::C::Stat->new(*HANDLE, %options);
4848
my $stat = FFI::C::Stat->new($filename, %options);
49+
my $stat = FFI::C::Stat->new;
4950
```
5051

5152
You can create a new instance of this class by calling the new method and passing in
52-
either a file or directory handle, or by passing in the filename path.
53+
either a file or directory handle, or by passing in the filename path. If you do
54+
not pass anything then an uninitialized stat will be returned.
5355

5456
Options:
5557

@@ -91,6 +93,10 @@ $ffi->attach( my_cfunction => [] => 'opaque' => sub {
9193
});
9294
```
9395

96+
The behavior of passing in `undef` prior to version 0.03 was undefined and could cause a
97+
crash. In version 0.03 and later passing in `undef` will return a stat object with all
98+
of the bits set to zero (0).
99+
94100
# PROPERTIES
95101

96102
## dev
@@ -203,7 +209,7 @@ Graham Ollis <[email protected]>
203209

204210
# COPYRIGHT AND LICENSE
205211

206-
This software is copyright (c) 2021 by Graham Ollis.
212+
This software is copyright (c) 2021-2023 by Graham Ollis.
207213

208214
This is free software; you can redistribute it and/or modify it under
209215
the same terms as the Perl 5 programming language system itself.

dist.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name = FFI-C-Stat
22
author = Graham Ollis <[email protected]>
33
license = Perl_5
44
copyright_holder = Graham Ollis
5-
copyright_year = 2021-2022
5+
copyright_year = 2021-2023
66
version = 0.02
77

88
[@Author::Plicease]

ffi/stat.c

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,27 @@ stat___fstat(int fd)
5454
}
5555

5656
struct stat *
57-
stat__clone(struct stat *self)
57+
stat___new(void)
5858
{
59-
struct stat *other;
60-
other = malloc(sizeof(struct stat));
61-
memcpy(other, self, sizeof(struct stat));
62-
return other;
59+
struct stat *self;
60+
self = malloc(sizeof(struct stat));
61+
return self;
62+
}
63+
64+
struct stat *
65+
stat__clone(struct stat *other)
66+
{
67+
struct stat *self;
68+
self = malloc(sizeof(struct stat));
69+
if(other == NULL)
70+
{
71+
memset(self, 0, sizeof(struct stat));
72+
}
73+
else
74+
{
75+
memcpy(self, other, sizeof(struct stat));
76+
}
77+
return self;
6378
}
6479

6580
dev_t

lib/FFI/C/Stat.pm

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,19 @@ $ffi->mangler(sub { "stat__$_[0]" });
5454
$ffi->attach( '_stat' => ['string'] => 'opaque' );
5555
$ffi->attach( '_fstat' => ['int', ] => 'opaque' );
5656
$ffi->attach( '_lstat' => ['string'] => 'opaque' );
57+
$ffi->attach( '_new' => [] => 'opaque' );
5758

5859
=head1 CONSTRUCTORS
5960
6061
=head2 new
6162
6263
my $stat = FFI::C::Stat->new(*HANDLE, %options);
6364
my $stat = FFI::C::Stat->new($filename, %options);
65+
my $stat = FFI::C::Stat->new;
6466
6567
You can create a new instance of this class by calling the new method and passing in
66-
either a file or directory handle, or by passing in the filename path.
68+
either a file or directory handle, or by passing in the filename path. If you do
69+
not pass anything then an uninitialized stat will be returned.
6770
6871
Options:
6972
@@ -87,6 +90,8 @@ sub new
8790
{ $ptr = _fstat(fileno($file)) }
8891
elsif(!is_ref($file) && defined $file)
8992
{ $ptr = $options{symlink} ? _lstat($file) : _stat($file) }
93+
elsif(!defined $file)
94+
{ $ptr = _new() }
9095
else
9196
{ Carp::croak("Tried to stat something whch is neither a glob reference nor a plain string") }
9297

@@ -120,6 +125,10 @@ Perl:
120125
return FFI::C::Stat->clone($ptr);
121126
});
122127
128+
The behavior of passing in C<undef> prior to version 0.03 was undefined and could cause a
129+
crash. In version 0.03 and later passing in C<undef> will return a stat object with all
130+
of the bits set to zero (0).
131+
123132
=cut
124133

125134
$ffi->attach( clone => ['opaque'] => 'opaque' => sub {

t/ffi_c_stat.t

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,15 @@ is(
7171
'clone a stat',
7272
);
7373

74+
is(
75+
FFI::C::Stat->clone(undef),
76+
object {
77+
call [ isa => 'FFI::C::Stat' ] => T();
78+
call $_ => D() for @props;
79+
},
80+
'clone undef',
81+
);
82+
7483
{
7584
my $other = FFI::C::Stat->new('corpus/xx.txt');
7685
is(
@@ -122,4 +131,13 @@ if($Config{d_symlink} eq 'define')
122131

123132
unlink 'testlink';
124133

134+
is(
135+
FFI::C::Stat->new,
136+
object {
137+
call [ isa => 'FFI::C::Stat' ] => T();
138+
call $_ => D() for @props;
139+
},
140+
'create uninitalized stat',
141+
);
142+
125143
done_testing;

0 commit comments

Comments
 (0)