Follow up on extended attributes

Timothe Litt via curl-users <[email protected]>
Newsgroups gmane.comp.web.curl.general
Message-ID <[email protected]>
As I noted in an earlier reply, etags belong with file data and extended 
attributes, where available, are a good place to keep them.  Better than 
dotfiles, but less portable (which is why I suggested dotfiles.)

Since many people don't know about extended attributes, here is a toy 
demo program that creates, deletes, and lists them.

The Perl module supports a number of (but not all the) useful 
filesystem, so its source code may be helpful if anyone wants to go that 
way with curl.  Windows is a notable exception, but NTFS streams are a 
reasonable substitute.  Note that the module has a bug that will keep 
this demo from working - my fork (on github 
<https://github.com/tlhackque/file-extattr>) has a patch.

e.g.

$ touch myfile
$  ~/ext myfile curl-etag abc-def-hk  # Add an attribute
$ ls -l myfile
-rw-r--r-- 1 litt litt 0 Jan 15 10:44 myfile
$ ~/ext myfile                                       # List all attributes
     curl-etag : "abc-def-hk"

Note that the file is still zero-length; the attribute is stored in the 
filesystem metadata, not the file.

FYI, NTFS "streams" are documented here 
<https://learn.microsoft.com/en-us/windows/win32/fileio/file-streams>and 
here <https://learn.microsoft.com/en-us/windows/win32/fileio/using-streams>.

Enjoy.

|#!/usr/bin/perl||
||
||use warnings;||
||use strict;||
||
||use File::ExtAttr( qw/:all/);||
||
||# Toy demo program for extended file attributes.||
||# The Perl module "File::Extattr" supports several common file systems.||
||
||unless( @ARGV ) {||
||    print <<"XXX" ;||
||ext - this help||
||
||ext file - list file attributes of file||
||
||ext file attr - delete attr||
||
||ext file attr val - create or replace attr=val||
||
||ext file attr val create - create attr=value||(can't exist)

||ext file attr val replace - replace attr=value (must exist)||
||||XXX||
||      exit;||
||}||
||
||open( my $fh, '<', $ARGV[0] ) or die( "$ARGV[0]: $!\n");||||
||
||if( @ARGV >= 3 ) {||
||    my @op = @ARGV == 4? $ARGV[3] eq 'replace'? ( replace => 1 ) : 
(create => 1) : ();||
||    unless( setfattr( $fh, $ARGV[1], $ARGV[2], { namespace => 'user', 
@op } ) ) {||
||        print "    set, '$ARGV[1]' => '$ARGV[2]' : $!\n";||
||    }||
||} elsif( @ARGV == 2 ) {||
||    unless( delfattr( $fh, $ARGV[1], { namespace => 'user' } ) ) {||
||        print "    del: failed\n";||
||    }||
||} elsif( @ARGV == 1 ) {||
||    foreach my $attr ( listfattr( $fh, { namespace => 'user' } ) ) {||
||        my $val = getfattr( $fh, $attr, {namespace => 'user' } );||
||        if( defined $val ) {||
||            print "    $attr : \"$val\"\n";||
||        } else {||
||            print "    $attr : $!\n";||
||        }||
||    }||
||}||
|||

-- 
Timothe Litt
ACM Distinguished Engineer
--------------------------
This communication may not represent the ACM or my employer's views,
if any, on the matters discussed.

-- 
Unsubscribe: https://lists.haxx.se/listinfo/curl-users
Etiquette:   https://curl.se/mail/etiquette.html
OpenPGP_signature (application/pgp-signature, 495 B) - not displayed
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.