ugrás a tartalomhoz

Perl alapjai VII.- Fájlműveletek

Bártházi András · 2004. Dec. 8. (Sze), 01.30
Perl alapjai VII.- Fájlműveletek
A szöveges és bináris fájlkezelés bemutatása után a mai alkalommal a fájlkezelési lehetőségekkel fogunk megismerkedni, s ennek keretében a fájlok tulajdonságainak (dátum, méret, típus, tulajdonos, jogok, stb.) lekérdezéséről, kezeléséről és megváltoztatásáról esik szó. A Perl ezekre a feladatokra néhány parancsot és függvényt ad, illetve modulokat biztosít (konkrétan a Win32 és almoduljai, illetve a File::stat modulról fogunk szót ejteni). Ennyi bevezető után neki is láthatunk az ismerkedésnek!

Fájl teszt

A Perl számos lehetőséget kínál számunkra igaz/hamis lekérdezésekre egy fájl típusú (fájl, könyvtár, szimbolikus link, csővezeték, stb.) elemmel kapcsolatosan. Ehhez egy külön operátort biztosít. Az operátor egy mínusz jelből, s egy betűből áll, a betű határozza meg a lekérdezett tulajdonságot. Ezután jön egy fájlkezelő változó, vagy magának a fájl típusú elemnek a neve. "Igazat", konkrétan 1-et kapunk vissza, ha a teszt értéke igaz, "hamisat", azaz egy üres sztringet kapunk vissza, ha a teszt értéke hamis, s definiálatlan értéket, ha nem sikerült elvégezni a tesztet.

Lássunk egy példát:

if (-e '/etc/passwd') {
  print "A jelszófájl létezik!\n";
}
A -e az "exists" rövidítése, ha létezik az adott fájl, akkor igazat, ha nem létezik, hamisat ad vissza. A következő táblázat ezeket az operátorokat sorolja fel:

-r  a fájlt olvasni tudja az effektív felhasználó
-w  a fájlt írni tudja az effektív felhasználó
-x  a fájl végrehajtható az effektív felhasználó által
-o  a fájl az effektív felhasználó tulajdonában van

-R  a fájlt olvasni tudja a valódi felhasználó
-W  a fájlt írni tudja a valódi felhasználó
-X  a fájl végrehajtható a valódi felhasználó által
-O  a fájl a valódi felhasználó tulajdonában van

-e  a fájl létezik
-z  a fájl üres (0 bájt méretű)
-s  a fájl nem üres (a fájl méretét adja vissza)

-f  a fájl egyszerű fájl
-d  a fájl egy könyvtár
-l  a fájl egy szimbolikus link
-p  a fájl egy nevesített cső, vagy a fájlkezelő egy cső
-S  a fájl egy socket
-b  a fájl egy blokk típusú speciális fájl
-c  a fájl egy karakter típusú speciális fájl
-t  a fájlkezelő egy terminálhoz nyitott

-u  a fájl setuid bitje 1
-g  a fájl setgid bitje 1
-k  a fájl sticky bitje 1
-T  a fájl szöveges (heurisztikus próba)
-B  a fájl bináris (heurisztikus próba)

-M  a fájl módosítása és a program indítása között
    eltelt idő, napokban
-A  a fájlhoz történt utolsó hozzáférés és a program indítása
    között eltelt idő, napokban
-C  a fájl inode változási ideje és a program indítása között
    eltelt idő, napokban
Magyarázatra talán az "effektív" és "valódi" felhasználó közötti eltérés szolgálhat. A kettő között akkor van különbség, mikor felhasználót váltunk a setuid, vagy csoportot a setgid eljárások segítségével, azaz valódi felhasználónk nem egyezik a beállított, effektívvel. A hozzáférés nem csak a felhasználói jogosultságok, hanem egyéb okok, például a rendelkezésre álló tárhely függvénye is. Ha jogosultságot szeretnénk csak vizsgálni, akkor a következőkben ismertetendő stat függvény lehet szolgálatunkra.

A fájlműveletekhez létezik egy speciális változó, melynek jele a _. A Perl a legutolsónak lekérdezett fájl tulajdonságait cache-eli, s ha erre a fájlra hivatkozunk, akkor nem kérdezi le újból egy fájlnak a tulajdonságait, hanem ezeket az információkat használja hozzá. Egy felhasználási módja:

if (-r $filename and -w _) {
  print "olvasni és írni is tudom: $filename\n"
}
A szöveges (-T), illetve bináris (-B) fájl operátor működési algoritmusa a fájl első blokkját használja. Ritka, vezérlő- és 127-es ASCII értéknél nagyobb kódú karaktereket keres. Amennyiben ezeknek a száma több, mint 30%, akkor a fájl binárisnak minősül, ellenkező esetben pedig szövegesnek. Ha fájlkezelőt adunk meg, s nem fájlnevet, akkor nem a fájl első blokkja, hanem az éppen aktuális puffer lesz elemezve. Üres fájl esetén, vagy ha az olvasás a fájl végénél tart, mind a két operátor igaz értékkel tér vissza.

A stat (és az lstat) függvény

A stat függvény egy fájl információit adja vissza egy 13 elemből álló lista keretében. Egy paramétert vár, mely lehet egy megnyitott fájl azonosítója, vagy egy fájlnak a neve. El is hagyható, ekkor a $_ változóban levő értéket fogja használni. Amennyiben sikertelen a lekérdezés, egy üres listát fog visszaadni. Legtöbbször a következőképpen hívjuk meg:

($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
 $atime,$mtime,$ctime,$blksize,$blocks) = stat($filename);
Az egyes elemek jelentése a következő (első oszlopban a visszaadott listában betöltött pozíció, másodikban egy angol nyelvű rövidítés, míg a harmadikban a magyarázat szerepel):

0  dev      a fájlrendszer eszközszáma
1  ino      a fájl inode száma
2  mode     a fájl típusai és jogai
3  nlink    a fájlra történő "hard" linkelések száma
4  uid      a fájl tulajdonosának sorszáma
5  gid      a fájl csoportjának sorszáma
6  rdev     eszköz azonosító, ha speciális fájlról van szó
7  size     teljes fájlméret bájtokban
8  atime    utolsó hozzáférési idő, másodpercekben az
            "epoch"-tól
9  mtime    utolsó módosítási idő, másodpercekben az
            "epoch"-tól
10 ctime    inode módosulási idő, másodpercekben az
             "epoch"-tól
11 blksize  a fájlrendszer előnyben részesített blokkmérete az
            I/O műveletekhez
12 blocks   a fájl által foglalt blokkok mérete
A fentiekből avatott szem észrevehette, hogy egyes visszaadott mezők fájlrendszer specifikusak, azaz korántsem számíthatunk rá, hogy mindig, minden operációs rendszeren megfelelő értéket kapunk vissza. Amennyiben az adott operációs rendszer, fájlrendszer támogatja az adott tulajdonságot, továbbá a Perl adott verziójában meg lett valósítva ennek a tulajdonságnak az elérése, akkor fogjuk csak a megfelelő értéket kapnunk. Ez nem jelenti azonban azt, hogy ne tenne jó szolgálatot ez a függvény! UNIX környezetben eléggé biztosak lehetünk az alapszolgáltatásokban, míg a fájlméretet és a módosítási dátumot szinte egész biztosan visszakapjuk az esetek döntő többségében.

A speciális _ változó itt is beállításra kerül, illetve használhatjuk akkor is, ha korábban egy -X művelet állította be.

Szimbolikus link esetén a vizsgálat a link által mutatott fájlon hajtódik végre - ezt nem árt tudni. Ha magának a szimbolikus linknek az adataira vagyunk kíváncsiak, akkor az egyébként a stat függvénnyel teljesen megegyező funkciójú és paraméterezésű lstat függvényt használhatjuk. Amennyiben fájlrendszerünk nem támogatja a szimbolikus linkeket, akkor az lstat működése teljes mértékben meg fog egyezni a stat-éval.

Amennyiben a visszakapott listánál egy kicsit barátságosabb felületre vágyunk, használhatjuk a File::stat modult, mely a stat és lstat függvényeket cseréli le, a visszatérési értékük így egy objektum lesz. A parancsoknak a beépítettekkel ellentétben nem lehet üres paramétert adni, továbbá az aláhúzás változót sem használhatjuk (azért van megoldás, nézzük meg a modul honlapját).

A visszakapott objektumból az értékeket az előző táblázatban megadott angol nyelvű rövidítéssel tudjuk elérni. Például:

use File::stat;
$statertek = stat($filename);
print 'A fájl mérete: '.$statertek->size."\n";

Jogosultságok és tulajdonosok állítása

A UNIX szerű jogosultságokat (ki, melyik csoport a fájl tulajdonosa, milyen jogai vannak) a stat és lstat függvények segítségével tudhatjuk meg. Beállításukra két parancs szolgál, a chmod és a chown.

A chmod a jogosultságok beállítására szolgál. Egy jogosultságkódot, továbbá fájlnevek listáját kell paraméteréül megadnunk. Használatához még a 8-as számrendszerben történő szám megadás módját kell ismernünk, melynek a lényege, hogy a konkrét szám elé egy 0-t kell írnunk. Ha egy sztring áll rendelkezésünkre, akkor az oct függvényt használhatjuk. Íme egy példa jogosultság állításra:

chmod 0755, 'teszt.pl';
Ez a "teszt.pl" fájlt tulajdonosa számára futtathatóvá, írhatóvá és olvashatóvá teszi. A fájl csoportjának és a többi felhasználónak pedig csak futtatható és olvasható lesz.

A chown parancs fájlok tulajdonosának és csoportjának beállítását teszi lehetővé. Használatához a felhasználó és a csoport sorszámát kell ismernünk. Első két paramétere a felhasználó azonosító és a csoport azonosító, a többi paramétere pedig az a fájl, vagy fájlok, mely, melyek esetében be szeretnénk állítani a tulajdonost és a csoportot.

Windows

Az előzőekben ismertetett megoldások nagy része csak UNIX szerű fájlrendszereken hatásos, Windows alatt ugyanis más a jogosultság és tulajdonos rendszer felépítése. Ebből adódóan valamilyen más megoldás után kell néznünk, ha fájlokkal szeretnénk foglalkozni, s nem elég az alapszintű támogatás.

A megoldást a Win32 nevű, illetve az ez alatti modulok fogják jelenteni. Ezek közül nézzük meg a Win32::FsType, Win32::FileTime, Win32::File és Win32::FileSecurity lehetőségeit.

Win32::FsType

Ez a függvény valójában nem egy modul, csak egy függvény a Win32 modulon belül. Feladata mindössze annyi, hogy információkkal szolgáljon a fájlrendszerrel kapcsolatosan. A kisbetű-nagybetű támogatástól kezdve a kvótákon keresztül a kódolt fájlrendszerig szolgál információkkal. A visszatérési értékében az egyes bitek egyes funkciók meglétét jelöli. Ennek függvényében a maszkok a következőképpen alakulnak:

0x00000001  kisbetű-nagybetű érzékeny fájlnevek támogatása
0x00000002  a fájlnévben megőrzi a kisbetű-nagybetű különbségeket
0x00000004  támogatja a Unicode-ot a fájlnevekben
0x00000008  megőrzi és betartatja a jogosultságokat
0x00000010  fájl alapú tömörítést támogat
0x00000020  támogatja a kvótázást
0x00000040  támogatja az sparse fájlokat
0x00000080  támogatja a reparse pontokat
0x00000100  támogatja a távoli tárolást
0x00008000  tömörített-e (pl. DiskSpace-el)
0x00010000  támogatja az objektum azonosítókat
0x00020000  támogatja a titkosított fájlrendszert

Win32::FileTime

Egy Win32::FileTime objektumtípust kínál, mely a fájlok dátumának és idejének lekérdezésére szolgál. Ezekhez három metódust kapunk, melyek rendre a fájl hozzáférési, létrehozási és módosítási dátumait adják vissza. Ezeknek az metódusoknak a year, month, wday, day, hour, minute, second és msecond paramétereket adhatjuk, vagy ha nem adunk meg egyet sem, akkor az összeset visszakapjuk - ebben a sorrendben. Pár példa:

use Win32::FileTime;

$filetime = Win32::FileTime->new( "proba.bat" );
my @AccessTime = $filetime->Access( year, month, day );
my @CreateTime = $filetime->Create( hour, minute );
my @ModifyTime = $filetime->Modify();

Win32::File

A Win32::File fájlok attribútumainak lekérdezésére és beállítására szolgál. Ezekre a funkciókra két metódust kapunk. A GetAttributes egy értéket kérdez le, a SetAttributes pedig a megadott érték alapján állítja be a fájlt. Az ARCHIVE, COMPRESSED, DIRECTORY, HIDDEN, NORMAL, OFFLINE, READONLY, SYSTEM és TEMPORARY konstansok fognak a rendelkezésünkre állni a feladathoz. Két példa:

use Win32::File;
Win32::File::GetAttributes("proba.bat", $visszateresiertek);
Win32::File::SetAttributes("proba.bat", READONLY|ARCHIVE);

Win32::FileSecurity

Végezetül vessünk egy pillantást a jogosultságok beállításának lehetőségére Windows alatt. Bővebben a modul oldalán olvashatunk ezekről, jelen cikkben csak egy gyors áttekintést adunk.

A modul segítségével lekérdezhetjük és beállíthatjuk fájlok jogosultságait, azaz konkrétan fájlokhoz rendelt felhasználói név és maszk párosok felett rendelkezhetünk, ezekhez a Get és Set metódusok használhatóak. Ezen kívül van még egy metódus, mely maszk értékek szövegekké alakítását végzi, továbbá egy másik, mely ennek fordítottját.

A következő program a paramétersorában megadott fájlok jogosultsági tulajdonságait fogja kilistázni:

use Win32::FileSecurity qw(Get EnumerateRights);
    
foreach( @ARGV ) {
    next unless -e $_ ;
    if ( Get( $_, \%hash ) ) {
        while( ($name, $mask) = each %hash ) {
            print "$name:\n\t";
            EnumerateRights( $mask, \@happy ) ;
            print join( "\n\t", @happy ), "\n";
        }
    }
    else {
        print( "Error #", int( $! ), ": $!" ) ;
    }
}

Összefoglalás

A mai cikk a fájlok kezelését folytatta, megismerkedhettünk a jogosultságok lekérdezésével, beállításával, s egyéb tulajdonságok lekérdezésével is. Következő alkalommal a könyvtárkezelést tekintjük át.
 
Bártházi András arcképe
Bártházi András
Az Emarsys-nál dolgozik vezető fejlesztőként, és az API-ért, integrációkért felelős termékmenedzserként. Szeret profi csapatban profit alkotni.
1

perl

Anonymous · 2005. Jan. 4. (K), 20.19
Folytatása lesz? :\
2

Szokott... :)

Bártházi András · 2005. Jan. 4. (K), 23.20
Szokott lenni neki. ;) Amint úgy alakul, lesz folytatása.

-boogie-
3

Lehet rossz?

Anonymous · 2006. Már. 14. (K), 10.53
egy exe kiterjesztésű fájlt vizsgáltam a stat fugvénnyel!

open ($dotnetfx,'>dotnetfx.exe');
($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,

$atime,$mtime,$ctime,$blksize,$blocks) = stat($dotnetfx);
print $dotnetfx;

És ezt kaptam!lehet elronottam valamit?!:
GLOB(0x2f4f10)
4

Mi a baj!

Anonymous · 2006. Már. 14. (K), 11.22
Megoldottam a bajt !Az a lényeg hogy csak a fájlméretet adja vissza ez szemét Windows!