Permission-Check von Dateien mit Perl
heilo
- cgi
0 Tobias Weisserth0 Klaus Mock0 heilo0 Klaus Mock0 Calocybe0 Klaus Mock0 heilo
Hallo Leute!
Also, ich arbeite schon seit ungefähr zwei Jahren mit Perl. Momentan versuche ich gerade einen Dateimanager zu programmieren, damit ich die HP auch aus dem Browser heraus editieren kann. Nachdem ich endlich ferig wurde habe ich folgende riesengroße problematik entdeckt: Der Manager unterscheidet nicht zwischen lesegeschützten und "offenen" Dateien, was es jedem ermöglicht Passwörter auszulesen oder ähnliche Dinge zu machen. Ich suchte nun nach einer Lösung die Permissions der Datei zu überprüfen, damit der Manager zwischen den verschiedenen rechten unterscheidet (er soll die Datei nur anzeigen, wenn OTHERS das lese- UND schreib-Recht haben). Nun bin ich auf den Befehl stat() auf perldoc.com gestoßen. Dort gibt es eine Möglichkeit die Permissions auszulesen und sie in eine Variable ($mode) zu speichern. Da aber der Inhalt dieser Variable nur aus komischen Zahlen besteht die mir nichts sagen, würde ich gerne wissen ob irgendjemand eine Idee hat, wie man die Permissions einer Datei auslesen kann und diese beispielsweise in eine Liste (ungefähr so: (Owner,User,Group)) zu speichern.
Vielen dank schon im voraus, heilo
Hallo heilo,
Schreib doch gerade mal ein Beispiel dieser "komischer" Zahlen, die Du ausgelesen hast. Vielleicht kann man sie doch benutzen ;-)
Gruß,
Tobias
Hallo,
Schreib doch gerade mal ein Beispiel dieser "komischer" Zahlen, die Du ausgelesen hast. Vielleicht kann man sie doch benutzen ;-)
Ich schätze mal da kommen Werte wie 16832,16877,33188,33152,33261 usw. vor.
Die (ausführliche) Antwort auf das Ursprungsposting wäre etwas langweilig, da es da eine wunderbare Stelle gibt, wo alles nachgelesen werden kann
perldoc -f stat
Es lohnt sich, auch das nach den ersten Zeilen zu lesen;-)
Grüße
Klaus
»»Werte wie 16832,16877,33188,33152,33261
perldoc -f stat
Es lohnt sich, auch das nach den ersten Zeilen zu lesen;-)
hi klaus,
Erstmal vielen Dank für die schnellen Antworten; es sind tatsächlich solche Zahlen. Ich habe die ganze stat()-Beschreibung ein paar mal durchgelesen, und war danach immer noch verwirrter als vorher. Hab' ich das nun richtig verstanden ich muss einfach vor die variable die diese zahl beinhält diesen -f Operator setzten? Muss ich dazu vorher noch use File::stat machen?
bin immer noch ratlos :-(
heilo
ps.: die url is die die ich durchgelesen hab' (is das die richtige?)
Hallo,
Ich habe die ganze stat()-Beschreibung ein paar mal durchgelesen, und war danach immer noch verwirrter als vorher.
Ok, villeicht kann ich doch noch etwas Licht in die Angelegenheit bringen.
(Anm.: das was da jetzt kommt, ist eigentlich aus der Unixwelt, andere Perlports, wie für Windows (NT/2k) emulieren AFAIK das nur)
$mode = (stat($filename))[2];
Liefert also den Filemode zurück, das ist schon mal klar.
In $mode stehen jetzt zweierlei Dinger, erstens der Dateityp, zweitens die Dateirechte.
Beschränken wir uns mal auf die Dateirechte.
Mit
$permissions = $mode & 07777;
'filterst' Du den Dateityp raus. Das erfolgt durch eine Bitoperation (& bzw. AND), das heißt nur jene Bits, welche in 07777 und $mode gesetzt sind, werden auch in $permission übernommen, die restlichen Bits von $mode werden 'ignoriert'.
(näheres zu Bitoperationen findest Du in jedem guten EDV-Einsteigerbuch).
Jetzt solltest Du noch wissen, was eine Oktalzahl ist. Das ist eine Zahl mit der Basis 8 anstelle 10 für Dezimalzahlen oder 16 für Hexadezimalzahlen. Jede Ziffer einer Oktalzahl wird durch drei Bits repräsentiert.
Das ist für die Dateirechte wunderbar, da hier für Besitzer, Gruppe [1] und Other (=Alle) jeweils die Rechte Lesen, Schreiben und Ausführen angegeben werden können, also auch drei Rechte pro 'Gruppe'. Die vierte Gruppe beinhaltet Setuid/Setgid/Stickiness, aber das lassen wir mal beiseite.
Nochmals zurück zu $permissions. Durch das Ausmaskieren mit 07777 bleibt eine 4-stellige Oktalzahl übrig. Auch das passt herrlich mit unseren Dateirechten zusammen, da da ja vier Definitionen notwendig sind (user,group,other und Setuid/Setgid/Stickiness [wie heißen die eigentlich, hmm Stickibits, denk ich]).
Wenn Du jetzt $permission als Oktalzahl ausgibst (printf("%04o",$permission);), dann kriegst Du meist folgende Werte:
0755
0600
0777
0644
oder was auch immer.
Nehmen wir uns 0755 vor, und zwar von Links nach Rechts.
Die erste (0) steht für die 'Stickibits'. Es sind keine gesetzt.
Die zweite (7) repräsentiert die Rechte des Besitzers der Datei. Wenn Du oktal 7 in eine Binärzahl umwandeln würdest, ergäbe das 111, wobei die einzelnen Bits , wieder von Links nach Rechts gelesen, für die Rechte Lesen, Schreiben und Ausführen stehen.
Jedes gesetzte Bit (1) heißt hier, daß der Besitzer das entsprechende Recht erteilt bekommen hat. In diesem konkreten Fall hat der Besitzer also alle Rechte.
Die dritte (5) steht für die Gruppenrechte, und ist wieder wie beim Besitzer zu interpretieren, also hat die (zugeordnete) Gruppe die Rechte Lesen und Ausführen (oktal 5 == binär 101).
Die vierte (5) steht für die Rechte aller anderen (other) und ist, wie bei der Gruppe auch auf Lesen und Ausführen gesetzt.
Soweit zu den Internas.
Weil allerdings das Ermitteln von Dateirechten durch dieses maskieren und bitweise lesen etwas unübersichtlich werden würde, gibts da ab Perl 5.6 ein Modul, welches standardmäßich bei allen Perlports mit 'geliefert' wird (ein sog. Core-Modul), mit dem das Ganze einfacher abzufragen ist.
use Fcntl ':mode';
$mode = (stat($filename))[2];
$user_rights = ($mode & S_IRWXU) >> 6;
$user_read = ($mode & S_IRUSR) >> 6;
$user_write = ($mode & S_IWUSR) >> 6;
$user_execute = ($mode & S_IXUSR) >> 6;
$group_rights = ($mode & S_IRWXG) >> 3;
$group_read = ($mode & S_IRGRP) >> 3;
$group_write = ($mode & S_IWGRP) >> 3;
$group_execute = ($mode & S_IXGRP) >> 3;
$other_rights = ($mode & S_IRWXO);
$other_read = ($mode & S_IROTH);
$other_write = ($mode & S_IWOTH);
$other_execute = ($mode & S_IXOTH);
Du könntest z.B. eine Ausgabe, wie es unter Unix (ls -l) üblich ist zusammenbasteln:
#!/usr/bin/perl
use Fcntl ':mode';
opendir(DIRHDL,'.');
@files = readdir(DIRHDL);
foreach $file (@files)
{
$mode = (stat($file))[2];
$permissions = '';
$permissions .= ($mode & S_IRUSR)?'r':'-';
$permissions .= ($mode & S_IWUSR)?'w':'-';
$permissions .= ($mode & S_IXUSR)?'x':'-';
$permissions .= ($mode & S_IRGRP)?'r':'-';
$permissions .= ($mode & S_IWGRP)?'w':'-';
$permissions .= ($mode & S_IXGRP)?'x':'-';
$permissions .= ($mode & S_IROTH)?'r':'-';
$permissions .= ($mode & S_IWOTH)?'w':'-';
$permissions .= ($mode & S_IXOTH)?'x':'-';
print "$permissions $file \n";
}
Das Dumme an diesem Beispiel ist nur, daß es Perl 5.6 voraussetzt. Bei älteren Versionen kannst Du aber afgrund der obigen Erklärungen sicherlich etwas ähnliches nachbauen.
Hab' ich das nun richtig verstanden ich muss einfach vor die variable die diese zahl beinhält diesen -f Operator setzten?
Äh, ich vermute Du meinst das -f von 'perldoc -f'. Nein, das hat was mit dem 'Programm' perldoc zu tun, nicht mit Deinem Problem.
Grüße
Klaus
[1] Unter Unix wird jeder Datei ein Besitzer und eine Gruppe zugeordnet, deren ID mit (stat($filename))[4] bzw. (stat($filename))[5] ausgelesen werden kann. Mit diesen Werten kann dann mittels 'getpwuid' bzw. 'getgrgid' deren Daten ermittelt werden. (Aber das kann bei Nicht-Unixports von Perl nicht als zuverlässig gegeben angenommen werden)
Hi Klaus!
use Fcntl ':mode';
$mode = (stat($filename))[2];>>6 schiebt die Bits um 6 stellen nach links, um so die gleichen
Werte für user,group und other zu erhalten
$user_rights = ($mode & S_IRWXU) >> 6;
$user_read = ($mode & S_IRUSR) >> 6;
$user_write = ($mode & S_IWUSR) >> 6;
$user_execute = ($mode & S_IXUSR) >> 6;
für group wird nur um 3 Bits verschoben
$group_rights = ($mode & S_IRWXG) >> 3;
$group_read = ($mode & S_IRGRP) >> 3;
$group_write = ($mode & S_IWGRP) >> 3;
$group_execute = ($mode & S_IXGRP) >> 3;
hier wird nichts mehr geschoben, weil das sowieso schon links ist
$other_rights = ($mode & S_IRWXO);
$other_read = ($mode & S_IROTH);
$other_write = ($mode & S_IWOTH);
$other_execute = ($mode & S_IXOTH);
Warum shiftest Du hier gruppenweise nach rechts? Sehe nicht so ganz den Punkt. Wenn Du der Reihe nach um 8, 7, 6, 5, 4, 3, 2, 1, 0 shiften wuerdest, wuerde ich es einsehen, weil dann das betreffende Bit jeweils an der Stelle der 1 steht und man die u.U ausgeben will. Aber so, ist doch fuer einen boolschen Test egal, an welcher Stelle die 1 steht oder auch nicht.
So long
Hallo,
Warum shiftest Du hier gruppenweise nach rechts? [...]
Wie saget Puh, der Bär so treffend? "Am Anfang machte es noch Sinn, aber auf dem Weg mußte ihm was dazwsichen gekommen sein."
Du hast recht, auf der ganzen Linie.
Grüße
Klaus
Also, wirklich vielen Dank für diese Aausführlichen Antworten!
Jetzt is mir der Knoten aufgegangen!
Jetzt funktioniert alles so wie ich es wollte.
Also nochmals vielen Dank!
-heilo-
:-) keep grinning