Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

Win32::FileSecurity weirdness

by keymon (Beadle)
on Oct 03, 2005 at 05:53 UTC ( [id://496824]=perlquestion: print w/replies, xml ) Need Help??

keymon has asked for the wisdom of the Perl Monks concerning the following question:

Dear monks,
I am trying to do a simple thing: change the permissions on a directory tree under WinXP to a standard value. So I started with Win32::FileSecurity module, and the idea was simple: I'll read in the permissions from 2 files (for directories and files), and using File::Find, just traverse the tree and if the permissions don't match, just Set() them to the wanted ones. Easy, right? But no.....

The script is pasted below. Here's the weird thing. The hash %dhash contains key-value pairs, like these:

        BUILTIN\Administrators => 270467583
        NT AUTHORITY\SYSTEM => 270467583
        Everyone => 1245631
I copy these values into a separate hash, called %hash (sorry about the naming). After the call to Set, the keys in all of my hashes get changed from something like this "BUILTIN\Administrators" to "BUILTIN Administrators". Naturally, the Set() fails in the next iteration. But I am really confused as to why strings that are not even a part of the manipulation (keys in %dhash and %fhash) are being modified?

-- confused in win32land


Code is below. It isn't a shining beacon of good coding, but I've lost half of my hair today, so my head indeed is shining right now...
#! C:\Perl\bin\perl.exe -w use strict; use File::Find (); use vars qw/*name *dir *prune/; *name = *File::Find::name; *dir = *File::Find::dir; *prune = *File::Find::prune; use Win32::FileSecurity qw(Get Set MakeMask); sub wanted; my %dhash; my %fhash; die "Usage: $0 <path>\n" unless (@ARGV); die "Need dmask.txt file\n" unless (-r "C:\\dmask.txt"); die "Need fmask.txt file\n" unless (-r "C:\\fmask.txt"); open(IN,"<", 'c:\dmask.txt') || die "dmask.txt: $!\n"; while (<IN>) { chomp; my ($id,@mask) = split(/\t/); $dhash{$id} = MakeMask(@mask); } close(IN); open(IN,"<", 'c:\fmask.txt') || die "fmask.txt: $!\n"; while (<IN>) { chomp; my ($id,@mask) = split(/\t/); $fhash{$id} = MakeMask(@mask); } close(IN); # Traverse desired filesystems File::Find::find({wanted => \&wanted}, $ARGV[0]); exit; sub wanted { my %hash; if (-d $name) { if ( Get( $name, \%hash ) ) { my $fix = 0; foreach my $id (keys %dhash) { if ((! exists($hash{$id})) or ($hash{$ +id} != $dh ash{$id})) { $hash{$id} = $dhash{$id}; $fix = 1; } } if ($fix != 0) { Set( $name, \%hash); } } else { print( "Error #", int( $! ), ": $!" ) ; } } elsif (-f $name) { if ( Get( $name, \%hash ) ) { my $fix = 0; foreach my $id (keys %fhash) { if ((! exists($hash{$id})) or ($hash{$ +id} != $fh ash{$id})) { $hash{$id} = $fhash{$id}; $fix = 1; } } if ($fix != 0) { Set( $name, \%hash); } } else { print( "Error #", int( $! ), ": $!" ) ; } } }

Replies are listed 'Best First'.
Re: Win32::FileSecurity weirdness
by Thelonius (Priest) on Oct 03, 2005 at 09:39 UTC
    This is a serious bug in Win32::FileSecurity. In FileSecurity.xs, Set iterates over the passed hash (reference) and then does this on the key:
    if ( lpszTemp = strchr( lpszAccount, '\\' ) ) { lpszServer = lpszAccount ; *lpszTemp = '\0' ; lpszAccount = lpszTemp + 1 ;
    (It does this in order to call LookupAccountNameA((LPCSTR) lpszServer, (LPCSTR) lpszAccount, ...).

    This is just wrong. Please file a bug report at http://rt.cpan.org/NoAuth/Bugs.html?Dist=libwin32.

    Hashes share key values, which is how this affects the other hashes. I don't see any workaround for this without fixing Win32::FileSecurity.xs

      Can anyone recommend a workaround?
Re: Win32::FileSecurity weirdness
by keymon (Beadle) on Oct 03, 2005 at 15:12 UTC
    Thanks for the tip, Thelonius . I managed a workaround thusly:
    - I make a backup copy of the permission hashes, storing them in lowercase using lc.
    - When filling the %hash hash inside the wanted sub, I uppercase the keys, thereby forcing a copy. Luckily(!), Win32 is case-insensitive, so this works.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://496824]
Approved by sk
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others taking refuge in the Monastery: (2)
As of 2024-04-26 01:38 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found