![]() |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
|
Proměnná | Obsah |
$0 | ll |
$ARGV[0] | ghost.png |
$ARGV[1] | db.sql |
$ARGV[2] | data |
$ARGV[3] | install.py |
Napíšeme si výše zmíněný program ll. Ten bude přijímat argumenty příkazového řádku. ll bude vypisovat, jakého typu je soubor (adresář, roura, atd.), práva, počet odkazů, vlastníka (uživatel i skupina), velikost, datum, čas a jméno souboru. ll tak bude napodobovat ls -l, jen nebude vyladěn do takových detailů.
Nejprve si udělejme nějakou koncepci. Postup bude následující.
Zde máme hlavní cyklus programu, který v každé iteraci vyšetří 1 předaný existující soubor.
#!/usr/bin/perl
use strict;
for (@ARGV){
next unless -e $arg;
...
}
V každém cyklu tak zpracujeme 1 argument, který bude uložen vždy v proměnné $_.
Teď budeme postupně zjišťovat informace o i-uzlech. Za prvé zde je typ souboru. To vyřešíme podprogramem zjisti_typ_souboru. Obdobně získáme i řetězec práv. V dalším sloupci máme počet odkazů na soubor. Ten není problém zjistit, protože tuto informaci máme uloženou na 4. pozici v seznamu, který vrací funkce stat. Jméno vlastníka a skupiny dostaneme voláním getpwuid resp. getgrgid. Předposledním sloupcem je velikost, kterou získáme taktéž pomocí funkce stat. A nakonec potřebujeme datum a čas. My máme pouze počet sekund od 1.1.1970. Proto musíme opět použít podprogram.
Nyní máme alespoň teoreticky veškeré potřebné údaje. Vytiskneme je funkcí printf. Oproti příkazu ls -l použijeme pro každou hodnotu pevnou šířku sloupce.
Hlavní cyklus bude na základě těchto údajů vypadat takto.
for (@ARGV){
next unless -e $arg;
my @data = stat;
my $typ_souboru = ziskej_typ_souboru($_);
my $prava = ziskej_prava($data[2]);
my $odkazu = $data[3];
my $user = getpwuid $data[4];
my $group = getgrgid $data[5];
my $velikost = $data[7];
my $cas = zjisti_cas($data[9]);
printf("%1s%9s %3s %7s %7s %10d %16s %s\n", $typ_souboru, $prava,
$odkazu, $user, $group,
$velikost, $cas, $arg);
}
Zbývá nám dopsat jednotlivé podprogramy. Začneme určením typu souboru. K tomu si připomeňme speciální operátory pro soubory. Budeme rozeznávat obyčejné soubory, adresáře, symbolické odkazy, roury, sockety, blokové a znakové soubory. V tomto podprogramu nám postačí jednoduchý switch.
sub ziskej_typ_souboru {
my($soubor) = @_;
if (-d $soubor){return "d";} #adresář
elsif (-l $soubor){return "l";} #symbolický odkaz
elsif (-f $soubor){return "-";} #obyčejný soubor
elsif (-p $soubor){return "p";} #roura
elsif (-b $soubor){return "b";} #blokový
elsif (-c $soubor){return "c";} #znakový
elsif (-S $soubor){return "s";} #socket
else {return "?";} #neznamý
}
Další na řadě máme řetězec práv. To bude vůbec nejsložitější část programu. Ohled musíme brát i na sticky bit, set UID a set GID. A co k tomu vlastně máme k dispozici? Prakticky jen příkaz stat, pomocí kterého lze zjistit desítkový formát přístupových práv.
Vše se tedy bude odehrávat v podprogramu ziskej_prava, který obdrží jako argument desítkový zápis práv.
sub ziskej_prava {
my $dec_prava = shift;
...
}
Nejdříve musíme získat osmičkový zápis přístupových práv, se kterým se bude lépe pracovat.
my $oct_prava = sprintf "%o", $dec_prava & 07777;
Dále si celý problém rozdělíme do 3 kroků. Bude to spíše manuální práce než vymýšlení algoritmů. Zde je postup.
Pokud je sticky bit, set UID nebo set GID nastaven, je zároveň hodnota $dec_prava větší než 777 a je čtyřmístná. Takže pokud lze odečíst příslušné hodnoty, uděláme to a zároveň nastavíme proměnné $sbit, $suid a $sgid. Připomeňme si, že pro set UID odečítáme 4000, pro set GID 2000 a pro sticky bit 1000.
if (length $oct_prava == 4){
if (($oct_prava - 4000) >= 0){$oct_prava -= 4000; $suid = 1};
if (($oct_prava - 2000) >= 0){$oct_prava -= 2000; $sgid = 1};
if (($oct_prava - 1000) >= 0){$oct_prava -= 1000; $sbit = 1};
}
První a nejjednodušší krok máme úspěšně za sebou, zbývají ještě 2. Protože nyní víme, že je hodnota $dec_prava vždy trojmístná, můžeme jednotlivé cifry rozdělit.
my($vlastnik, $skupina, $ostatni) = split "", $oct_prava;
Od každé z proměnných $vlastnik, $skupina a $ostatni opět budeme postupně odečítat hodnoty (právo pro čtení 4, pro zápis 2, pro spouštění 1) a zároveň přidávat práva (byla-li příslušná hodnota odečtena). V případě absence práva zapíšeme znak -.
for my $us ($vlastnik, $skupina, $ostatni){
if (($us - 4) >= 0){$us -= 4; $retezec .= "r";} else {$retezec .= "-";}
if (($us - 2) >= 0){$us -= 2; $retezec .= "w";} else {$retezec .= "-";}
if (($us - 1) >= 0){$us -= 1; $retezec .= "x";} else {$retezec .= "-";}
}
V proměnné $retezec nyní máme řetězec práv a musíme do něj zahrnout $sbit, $suid a $sgid.
Existuje-li $suid, nahradíme 3. znak řetězce za s (pokud tam už je x) nebo za S (pokud tam není). Použijeme funkci substr. Její 4. parametr - řetězec, kterým se bude (v našem případě 3. znak) nahrazovat tedy bude právě s nebo S.
if ($suid == 1){
substr $retezec, 2, 1, ... s nebo S ...;
}
Jestliže je právě na 3. pozici znak x (což zjistíme opět příkazem substr), 4. parametrem bude s. Jinými slovy - prostor pro podmínkový operátor.
if ($suid == 1){
substr $retezec, 2, 1, ((substr $retezec, 2, 1) eq "x") ? "s" : "S";
}
To samé uděláme i s set GID a sticky bit.
if ($sgid == 1){
substr $retezec, 5, 1, ((substr $retezec, 5, 1) eq "x") ? "s" : "S";
}
if ($sbit == 1){
substr $retezec, 8, 1, ((substr $retezec, 8, 1) eq "x") ? "t" : "T";
}
A na závěr vrátíme výsledný řetězec.
return $retezec;
Posledním podprogramem zjistíme datum a čas. V něm získáme všechny potřebné údaje od funkce localtime. Stačí je pouze vhodně poskládat a vrátit.
sub zjisti_cas {
my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($_[0]);
return sprintf("%4d-%02d-%02d %02d:%02d", $year + 1900, $mon, $mday,
$hour, $min)
}
To je celé. Oproti ls -l se sice ll v mnoha rysech významně liší (stačí porovnat výstupy po zadání adresáře), ale přesto nám posloužil jako názorná ukázka.
$ ./ll TEST -rws--Sr-T 1 jv users 0 2005-07-07 13:56 TEST $ ls -l TEST -rws--Sr-T 1 jv users 0 2005-08-07 13:56 TEST $
|
||||
KOMENTARZE | ||||
Tylko zarejestrowani użytkownicy mogą dopisywać komentarze.
|
1. |
Pacman linux Download: 5096x |
2. |
FreeBSD Download: 9311x |
3. |
PCLinuxOS-2010 Download: 8800x |
4. |
alcolix Download: 11190x |
5. |
Onebase Linux Download: 9910x |
6. |
Novell Linux Desktop Download: 0x |
7. |
KateOS Download: 6459x |
1. |
xinetd Download: 2623x |
2. |
RDGS Download: 937x |
3. |
spkg Download: 5247x |
4. |
LinPacker Download: 10393x |
5. |
VFU File Manager Download: 3396x |
6. |
LeftHand Mała Księgowość Download: 7484x |
7. |
MISU pyFotoResize Download: 3090x |
8. |
Lefthand CRM Download: 3760x |
9. |
MetadataExtractor Download: 0x |
10. |
RCP100 Download: 3373x |
11. |
Predaj softveru Download: 0x |
12. |
MSH Free Autoresponder Download: 0x |