1package File::ExtAttr;
2
3=head1 NAME
4
5File::ExtAttr - Perl extension for accessing extended attributes of files
6
7=head1 SYNOPSIS
8
9  use File::ExtAttr ':all';
10  use IO::File;
11
12  # Manipulate the extended attributes of files.
13  setfattr('foo.txt', 'colour', 'red') || die;
14  my $colour = getfattr('bar.txt', 'colour');
15  if (defined($colour))
16  {
17      print $colour;
18      delfattr('bar.txt', 'colour');
19  }
20
21  # Manipulate the extended attributes of a file via a file handle.
22  my $fh = new IO::File('<foo.txt') || die;
23  setfattr($fh, 'colour', 'red') || die;
24
25  $fh = new IO::File('<bar.txt') || die;
26  $colour = getfattr($fh, 'colour');
27  if (defined($colour))
28  {
29      print $colour;
30      delfattr($fh, 'colour');
31  }
32
33  # List attributes in the default namespace.
34  print "Attributes of bar.txt:\n";
35  foreach (listfattr($fh))
36  {
37    print "\t$_\n";
38  }
39
40  # Examine attributes in a namespace-aware manner.
41  my @namespaces = listfattrns($fh);
42
43  foreach my $ns (@namespaces)
44  {
45    print "Attributes in namespace '$ns': ";
46    my @attrs = listfattr($fh, { namespace => $ns });
47    print join(',', @attrs)."\n";
48  }
49
50=head1 DESCRIPTION
51
52File::ExtAttr is a Perl module providing access to the extended attributes
53of files.
54
55Extended attributes are metadata associated with a file.
56Examples are access control lists (ACLs) and other security parameters.
57But users can add their own key=value pairs.
58
59Extended attributes may not be supported by your operating system.
60This module is aimed at Linux, Unix or Unix-like operating systems
61(e.g.: Mac OS X, FreeBSD, NetBSD, Solaris).
62
63Extended attributes may also not be supported by your filesystem
64or require special options to be enabled for a particular filesystem.
65E.g.:
66
67  mount -o user_xattr /dev/hda1 /some/path
68
69=head2 Supported OSes
70
71=over 4
72
73=item Linux
74
75=item Mac OS X
76
77=item FreeBSD 5.0 and later
78
79=item NetBSD 4.0 and later
80
81=item Solaris 10 and later
82
83=back
84
85=head2 Unsupported OSes
86
87=over 4
88
89=item OpenBSD
90
91=back
92
93=head2 Namespaces
94
95Some implementations of extended attributes support namespacing.
96In those implementations, the attribute is referred to by namespace
97and attribute name.
98
99=over 4
100
101=item Linux
102
103The primary namespaces are C<user> for user programs;
104C<security>, C<system> and C<trusted> for file security/access-control.
105See L<http://www.die.net/doc/linux/man/man5/attr.5.html>
106for more details.
107
108Namespaces on Linux are described by a string, but only certain values
109are supported by filesystems. In general C<user>, C<security>, C<system>
110and C<trusted> are supported, by others may be supported --
111e.g.: C<os2> on JFS. File::Extattr will be able to access any of these.
112
113=item FreeBSD, NetBSD
114
115*BSD have two namespaces: C<user> and C<system>.
116
117Namespaces on *BSD are described by an integer. File::ExtAttr will only
118be able to access attributes in C<user> and C<system>.
119
120=item Mac OS X
121
122OS X has no support for namespaces.
123
124=item Solaris
125
126Solaris has no support for namespaces.
127
128=back
129
130=head2 Flags
131
132The functions take a hash reference as their final parameter,
133which can specify flags to modify the behaviour of the functions.
134The flags specific to a function are documented in the function's
135description.
136
137All functions support a C<namespace> flag. E.g.:
138
139  use File::ExtAttr ':all';
140  use IO::File;
141
142  # Manipulate the extended attributes of files.
143  setfattr('foo.txt', 'colour', 'red') || die;
144  my $colour = getfattr('bar.txt', 'colour', { namespace => 'user');
145
146If no namespace is specified, the default namespace will be used.
147On Linux and *BSD the default namespace will be C<user>.
148
149=cut
150
151use strict;
152use warnings;
153use Carp;
154use Scalar::Util;
155
156require Exporter;
157use AutoLoader;
158
159our @ISA = qw(Exporter);
160
161# Items to export into callers namespace by default. Note: do not export
162# names by default without a very good reason. Use EXPORT_OK instead.
163# Do not simply export all your public functions/methods/constants.
164
165# This allows declaration	use File::ExtAttr ':all';
166# If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
167# will save memory.
168our %EXPORT_TAGS = ( 'all' => [ qw(
169  getfattr
170  setfattr
171  delfattr
172  listfattr
173  listfattrns
174) ] );
175
176our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
177
178our @EXPORT = qw(
179);
180
181our $VERSION = '1.09';
182
183#this is used by getxattr(), needs documentation
184$File::ExtAttr::MAX_INITIAL_VALUELEN = 255;
185
186require XSLoader;
187XSLoader::load('File::ExtAttr', $VERSION);
188
189# Preloaded methods go here.
190
191=head1 METHODS
192
193=over 4
194
195=cut
196
197sub _is_fh
198{
199    my $file = shift;
200    my $is_fh = 0;
201
202    eval
203    {
204        # TODO: Does this work with Perl 5.005, 5.6.x?
205        # Relies on autovivification of filehandles?
206        $is_fh = 1 if ($file->isa('IO::Handle'));
207
208        # TODO: Does this work with Perl 5.005, 5.6.x?
209        # Better solution for detecting a file handle?
210        $is_fh = 1 if (openhandle($file));
211    };
212
213    return $is_fh;
214}
215
216=item getfattr([$filename | $filehandle], $attrname, [\%flags])
217
218Return the value of the attribute named C<$attrname>
219for the file named C<$filename> or referenced by the open filehandle
220C<$filehandle> (which should be an IO::Handle or subclass thereof).
221
222If no attribute is found, returns C<undef>. Otherwise gives a warning.
223
224=cut
225
226sub getfattr
227{
228    my $file = shift;
229
230    return _is_fh($file)
231        # File handle
232        ? _fgetfattr($file->fileno(), @_)
233        # Filename
234        : _getfattr($file, @_);
235}
236
237=item setfattr([$filename | $filehandle], $attrname, $attrval, [\%flags])
238
239Set the attribute named C<$attrname> with the value C<$attrval>
240for the file named C<$filename> or referenced by the open filehandle
241C<$filehandle> (which should be an IO::Handle or subclass thereof).
242
243C<%flags> allows control of whether the attribute should be created
244or should replace an existing attribute's value. If the key C<create>
245is true, setfattr will fail if the attribute already exists. If the key
246C<replace> is true, setfattr will fail if the attribute
247does not already exist. If neither is specified, then the attribute
248will be created (if necessary) or silently replaced.
249
250If the attribute could not be set, a warning is issued.
251
252Note that C<create> cannot be implemented in a race-free manner on *BSD.
253If your code relies on the C<create> behaviour, it may be insecure on *BSD.
254
255=cut
256
257sub setfattr
258{
259    my ($file, $attrname, $attrval, $flagsref) = @_;
260
261    die "Only one of the 'create' and 'replace' options can be passed to setfattr"
262      if ($flagsref->{create} && $flagsref->{replace});
263
264    return _is_fh($file)
265        # File handle
266        ? _fsetfattr($file->fileno(), $attrname, $attrval, $flagsref)
267        # Filename
268        : _setfattr($file, $attrname, $attrval, $flagsref);
269}
270
271=item delfattr([$filename | $filehandle], $attrname, [\%flags])
272
273Delete the attribute named C<$attrname> for the file named C<$filename>
274or referenced by the open filehandle C<$filehandle>
275(which should be an IO::Handle or subclass thereof).
276
277Returns true on success, otherwise false and a warning is issued.
278
279=cut
280
281sub delfattr
282{
283    my $file = shift;
284
285    return _is_fh($file)
286        # File handle
287        ? _fdelfattr($file->fileno(), @_)
288        # Filename
289        : _delfattr($file, @_);
290}
291
292=item listfattr([$filename | $filehandle], [\%flags])
293
294Return an array of the attributes on the file named C<$filename>
295or referenced by the open filehandle C<$filehandle> (which should be
296an IO::Handle or subclass thereof).
297
298Returns undef on failure and $! will be set.
299
300=cut
301
302sub listfattr
303{
304    my $file = shift;
305
306    return _is_fh($file)
307        # File handle
308        ? _listfattr('', $file->fileno(), @_)
309        # Filename
310        : _listfattr($file, -1, @_);
311}
312
313=item listfattrns([$filename | $filehandle], [\%flags])
314
315Return an array containing the namespaces of attributes on the file named
316C<$filename> or referenced by the open filehandle C<$filehandle>
317(which should be an IO::Handle or subclass thereof).
318
319Returns undef on failure and $! will be set.
320
321=cut
322
323sub listfattrns
324{
325    my $file = shift;
326
327    return _is_fh($file)
328        # File handle
329        ? _listfattrns('', $file->fileno(), @_)
330        # Filename
331        : _listfattrns($file, -1, @_);
332}
333
334=back
335
336=cut
337
338# TODO: l* functions
339
340=head1 EXPORT
341
342None by default.
343
344You can request that C<getfattr>, C<setfattr>, C<delfattr>
345and C<listfattr> be exported using the tag ":all".
346
347=head2 Exportable constants
348
349None
350
351=head1 BUGS
352
353You cannot set empty attributes on Mac OS X 10.4 and earlier.
354This is a bug in Darwin, rather than File::ExtAttr.
355
356=head1 SEE ALSO
357
358The latest version of this software should be available from its
359home page: L<http://sourceforge.net/projects/file-extattr/>
360
361L<OS2::ExtAttr> provides access to extended attributes on OS/2.
362
363Eiciel, L<http://rofi.pinchito.com/eiciel/>, is an access control list (ACL)
364editor for GNOME; the ACLs are stored in extended attributes.
365
366Various low-level APIs exist for manipulating extended attributes:
367
368=over 4
369
370=item Linux
371
372getattr(2), attr(5)
373
374L<http://www.die.net/doc/linux/man/man2/getxattr.2.html>
375
376L<http://www.die.net/doc/linux/man/man5/attr.5.html>
377
378=item OpenBSD
379
380OpenBSD 3.7 supported extended attributes, although support was never
381built into the default GENERIC kernel. Its support was documented
382in the C<extattr> man page:
383
384L<http://www.openbsd.org/cgi-bin/man.cgi?query=extattr_get_file&apropos=0&sektion=0&manpath=OpenBSD+Current&arch=i386&format=html>
385
386Support was removed in OpenBSD 3.8 -- see the CVS history
387for the include file C<sys/extattr.h>.
388
389L<http://www.openbsd.org/cgi-bin/cvsweb/src/sys/sys/Attic/extattr.h>
390
391=item FreeBSD
392
393FreeBSD >= 5.0 supports extended attributes.
394
395extattr(2)
396
397L<http://www.freebsd.org/cgi/man.cgi?query=extattr&sektion=2&apropos=0&manpath=FreeBSD+6.0-RELEASE+and+Ports>
398
399=item NetBSD
400
401NetBSD >= 3.0 supports extended attributes, but you'll need to use
402NetBSD >= 4.0 to get UFS filesystem support for them.
403
404L<http://netbsd.gw.com/cgi-bin/man-cgi?extattr_get_file+2+NetBSD-current>
405
406L<http://www.netbsd.org/Changes/changes-4.0.html#ufs>
407
408=item Mac OS X
409
410getxattr(2)
411
412L<http://developer.apple.com/documentation/Darwin/Reference/ManPages/man2/getxattr.2.html>
413
414L<http://arstechnica.com/reviews/os/macosx-10.4.ars/7>
415
416=item Solaris
417
418attropen(3C), fsattr(5)
419
420L<http://docsun.cites.uiuc.edu/sun_docs/C/solaris_9/SUNWaman/hman3c/attropen.3c.html>
421
422L<http://docsun.cites.uiuc.edu/sun_docs/C/solaris_9/SUNWaman/hman5/fsattr.5.html>
423
424Solaris also has extensible system attributes, which are used
425by Solaris's CIFS support on ZFS, and have a confusingly similar
426name to extended file attributes. These system attributes are stored
427in extended file attributes called SUNWattr_ro and SUNWattr_rw.
428See PSARC 2007/315 for more details:
429
430L<http://opensolaris.org/os/community/arc/caselog/2007/315/spec-final-txt/>
431
432=back
433
434=head1 AUTHOR
435
436Kevin M. Goess, E<lt>kgoess@ensenda.comE<gt>
437
438Richard Dawe, E<lt>richdawe@cpan.orgE<gt>
439
440=head1 COPYRIGHT AND LICENSE
441
442Copyright (C) 2005 by Kevin M. Goess
443
444Copyright (C) 2005, 2006, 2007, 2008 by Richard Dawe
445
446This library is free software; you can redistribute it and/or modify
447it under the same terms as Perl itself, either Perl version 5.8.5 or,
448at your option, any later version of Perl 5 you may have available.
449
450=cut
451
4521;
453__END__
454