LINUXZONE






 >> Hlavní stránka

(1740/07.09.2010)


 >> Administrace

(161/05.08.2010)


 >> Literatura

(311/07.09.2010)


 >> Bezpečnost

(345/03.09.2010)


 >> Programování

(307/19.04.2010)


 >> Distribuce

(97/09.06.2010)


 >> Síťování

(86/03.06.2010)


 >> Lokalizace

(10/15.09.2004)


 >> Aplikace

(176/12.08.2010)


 >> Multimedia

(32/31.03.2006)


 >> Hardware

(45/02.03.2007)


 >> Začínáme

(228/24.06.2010)


 >> Aktuálně

(562/06.09.2010)


 >> RELAX

(209/02.09.2010)


 >> Jinde vyšlo

přehled ostatních serverů




 Přihlášení




Login:
Heslo:
 uložit v prohlížeči


Nejste-li ješte zaregistrováni, můžete tak učinit zde.





 Vyhledávání




Hledaný výraz:
v klíčových slovech
v titulku
v anotaci
v textu








 Reklama









 Servis




*   Vaše náměty a připomínky
Máte k Linuxzone.cz nějaké připomínky nebo náměty? Našli jste na stránkách chybu? Dejte nám o tom vědět pomocí formuláře nebo v diskuzi.
Komentářů: 30
*   Podpořte Linuxzone.cz
Chcete podpořit náš server umístěním odkazu nebo zveřejněním backendu? Zde najdete vše potřebné.
*   Pište pro Linuxzone.cz
Máte zájem podílet se na obsahu Linuxzone.cz ať už jako redaktoři nebo i jinak? Dejte nám o sobě vědět!





 Aktuálně z bezpečnosti




-- 
6.12.2005, 19:01
Na serveru informit.com vyšla ukázková kapitola týkající se práce s řetězci z knihy Secure Coding in C and C++. (lz)

-- 
3.12.2005, 12:34
Bugtraq: Format String Vulnerabilities in Perl Programs. (lz)

-- 
3.12.2005, 12:32
Linux Advisory Watch December 2nd 2005. (lz)

-- 
23.10.2005, 13:28
Rozhovor na téma klasické zálohování versus CDP. (lz)

-- 
23.10.2005, 13:24
Linux Advisory Watch October 21st 2005. (lz)

další >>





 Aktuálně o software




-- 
6.12.2005, 19:07
Potřebujete-li pod linuxem rozchodit bezdrát založený na čipsetech Broadcom 43xx, konečně existuje linuxový ovladač. (lz)

-- 
6.12.2005, 19:04
Byla uvolněna verze Xen 3.0.0 virtualizační technologie XEN. (lz)

-- 
6.12.2005, 18:59
Byla uvolněna verze X11R6.9/X11R7 RC 3 grafickérho rozhraní X Window System. (lz)

-- 
3.12.2005, 12:45
Co je nového okolo projektu Amanda (open source zálohovací software)? Více na osnews.com. (lz)

-- 
3.12.2005, 12:40
Jak to akuálně v linuxu vypadá s podporou SATA.. (lz)

další >>





 Aktuálně z IT




-- 
3.12.2005, 12:51
Novellu se daří prodej linuxových produktů, oproti loňskému roku se Novell dočkal výrazného nárůstu. (lz)

-- 
3.12.2005, 12:48
Třetí verzi licence GPL by měla být publikována během jara 2007. (lz)

-- 
23.10.2005, 13:20
V Peru nyní mají zákon, který umožňuje nasazení open source software ve vládní správě. (lz)

-- 
23.10.2005, 13:14
Proč se Microsoft bojí Google? (lz)

-- 
27.9.2005, 22:01
Peru má zákon podporující free software. (lz)

další >>





 Nejčtenější články




-- 
Virtualizace - Praktický průvodce

-- 
Novinky ze světa svobodného software (21/2010)

-- 
Security Digest (20/2010)

-- 
Proč by software neměl mít majitele (2/2)

-- 
Novinky ze světa svobodného software (22/2010)

-- 
Security Digest (21/2010)

-- 
Bezpečnost bezdrátové komunikace

-- 
Patentová reforma nestačí

-- 
Prodej svobodného software? (2/2)

-- 
Prodej svobodného software? (1/2)






 Nejlepší články




-- 
Security Digest (22/2010)

-- 
Virtualizace - Praktický průvodce

-- 
Security Digest (21/2010)

-- 
Novinky ze světa svobodného software (21/2010)

-- 
Security Digest (20/2010)

-- 
Novinky ze světa svobodného software (22/2010)

-- 
Prodej svobodného software? (2/2)

-- 
Proč by software neměl mít majitele (2/2)

-- 
Bezpečnost bezdrátové komunikace

-- 
Novinky ze světa svobodného software (23/2010)






 Anketa




Používáte nějaké rozšíření bezpečnostního modelu linuxového jádra?

Openwall (18%)

LIDS (12%)

Pax/Grsecurity (3%)

SELinux (6%)

RSBAC (1%)

jiné (1%)

používám standardní jádro (59%)







Linuxzone.cz - server o Linuxu pro programátory, administrátory a fanoušky.
Provozuje společnost Impossible.
ISSN: 1213-8738





Jak to chodí v jádře aneb napište si vlastní ovladač (6)

Dnes se budeme věnovat posledně zmiňovaném souborovému systému pro zařízení neboli The Device filesystemu. Ke konci budete uvedeni do problematiky race conditions a nemine vás ani ukázkový příklad.

The Device filesystem

Jedná se o souborový systém, který nám nabízí dynamickou tvorbu zařízení v adresáři /dev. Můžete namítnout, že toto již zvládáte pomocí mknod. Máte pravdu, ale co již nezvládáte je tvorba (a rušení) této hierarchie v rámci vašeho modulu. Pokud jádro podporuje The Device filesystem (dále jen devfs) můžete všechny tyto výhody využívat.

Máte možnost tvorby adresářů, zařízení, symbolických linků, atd. Problém ale nastává s kompatibilitou. Starší jádra tuto možnost oficiálně nepodporují (pro jádra 2.2.x existuje patch) a tak byste se setkali s mnoha problémy. Pokud se rozhodnete devfs použít, doporučuji zaimplementovat i starší metodu pro práci s major/minor čísly, kterou jsme si ukázali v minulém díle.

Devfs není samo o sobě moc rozšířené a to i navzdory tomu, že nabízí velké výhody. Problém je v tom, že vyvolává velkou nekompatibilitu proti již hotovým uživatelským aplikacím. Proč? Většina těchto aplikací využívá zařízení z adresáře /dev a když jim je změníme tak bohužel nefungují (ne všechny). Proto je standardně tato volba vypnutá a kdo chce experimentovat či upravovat stávající programy má samozřejmě možnosti si ji zapnout. Například mnou používaná distribuce (RedHat) toto ve svém jádru nepoužívá.

Podívejme se v krátkosti na výhody tohoto systému.

  1. možnost tvorby/rušení zařízení za běhu (včetně adresářů, linků, ...)
  2. možnost specifikacu názvu zařízení, vlastníka a přístupových práv z modulu
  3. odpadá práce s major/minor čísly

Samozřejmě systém nabízí i svoje nevýhody a tou je například zmíněná nekompatibilita s uživatelskými aplikacemi. My se na něj stejně v krátkosti podíváme ať máme základní přehled.

Použití devfs

Devfs můžeme použít pouze v případě, že jej podporuje jádro. V kladném případě je v hlavičkovém souboru linux/config.h, resp. linux/autoconf.h definováno makro CONFIG_DEVFS_FS.

Všechny deklarace pro devfs jsou v hlavičkovém souboru linux/devfs_fs_kernel.h.

devfs_handle_t

Vytvoříme-li jakýkoli objekt v devfs (adresář, link, zařízení, ...) vždy nám příslušná funkce vrátí handle (také nebudu překládat) tohoto objektu. Chceme-li s tímto objektem dále pracovat musíme tento handle použít.

Tvorba adresáře

K tvorbě adresáře nám slouží jednoduchá funkce a tou je devfs_mk_dir s následující syntaxí:

extern devfs_handle_t devfs_mk_dir (devfs_handle_t dir, \
                                  const char *name, void *info);

Prvním argumentem je rodičovský adresář v kterém bude náš adresář umístěn. Chceme-li jej umístit přímo do adresáře /dev použijeme hodnotu NULL. Dalším parametrem je name který určuje název námi vytvářeného adresáře. Poslední argument info není u této funkce využíván. Podívejme se jak tedy vytvořit hierarchickou strukturu adresářů /dev/lzdev/sound:

static devfs_handle_t lzdev, sound;

lzdev = devfs_mk_dir(NULL, "lzdev", NULL);
if (!lzdev) return -EBUSY;

sound = devfs_mk_dir(lzdev, "sound", NULL);
if (!sound)
{
   devfs_unregister(lzdev);
   return -EBUSY;
}

Trochu jsme předběhli a ukázali si jak uvolnit námi již vytvořený objekt v devfs.

Tvorba zařízení

K tomu nám slouží obdobná funkce se jménem devfs_register deklarována takto:

extern devfs_handle_t devfs_register (devfs_handle_t dir, \
       const char *name, unsigned int flags, unsigned int major,\
       unsigned int minor, umode_t mode, void *ops, void *info);

Jak sami vidíte, zase vrací devfs_handle_t, který si sebou nese informaci o vytvořeném objektu. Teď se podíváme podrobněji na všechny parametry.

  1. devfs_handle_t dir

    Specifikujeme rodičovský adresář (v případě NULL to je /dev).


  2. const char *name

    Jméno vytvářeného zařízení.


  3. unsigned int flags

    Bitová maska několika různých nastavení. Jejich seznam je uveden dále.


  4. unsigned int major, unsigned int minor

    Zde uvádíme major a minor čísla pro zařízení. V případě, že použijeme flag DEVFS_FL_AUTO_DEVNUM jsou tyto čísla nevyužita.


  5. umode_t mode

    Přístupová práva k zařízení a jeho typ. Definovány v hlavičkovém souboru linux/stat.h a patří mezi ně vám určitě známé věci jako S_IFCHR, S_IRUSR či S_IWOTH. Prostudujte si tento hlavičkový soubor a zjistíte, že při definici makra __KERNEL__ nám budou zpřístupněny další věci, které normální uživatelské aplikace nevidí.


  6. void *ops

    Tento parametr ukazuje na nám již známé file_operations. Z tohoto důvodu nepotřebujeme pracovat s minor čísly, protože správné souborové operace lze přiřadit již při vytváření tohoto zařízení.


  7. void *info

    Tento taktéž nepovinný parametr bude přiřazen do struktury file na pozici private_data při otevření vytvářeného zařízení.


Vraťme se ještě k parametru unsigned int flags a jeho možnostem.

  1. DEVFS_FL_NONE

    Hodnota 0, neboli žádné flagy nejsou nastaveny.


  2. DEVFS_FL_DEFAULT

    Toto makro je nastaveno na makro DEVFS_FL_NONE.


  3. DEVFS_FL_AUTO_OWNER

    V případě, že naše zařízení nikdo nepoužívá má nastavená práva čtení/zápis pro kohokoli. Jakmile nějaký proces toto zařízení otevře změní se vlastník na vlastníka procesu a následná změna přístupových práv dovoluje práci se zařízením pouze onomu procesu. Jakmile proces toto zařízení zavře, resp. jej přestane používat, je okamžitě zpřístupněno širému okolí.


  4. DEVFS_FL_SHOW_UNREG

    Tímto flagem zamezíme odstranění naše souboru z adresáře /dev při odregistrování zařízení.


  5. DEV_FL_HIDE

    V případě úspěšné registrace nebude toto zařízení vidět v adresáři /dev.


  6. DEV_FL_AUTO_DEVNUM

    Nastavíme-li tento flag bude nám automaticky přiděleno major/minor číslo. Toto číslo bude pro naše zařízení alokováno do dalšího restartu systému, tj. budeme-li opětovně registrovat a odregistrovávat naše zařízení tak vždy obdží stejné major/minor číslo.


  7. DEV_FL_NO_PERSISTENCE

    Nastavíme-li tento flag nebudou zachovány výše zmíněné informace při opětovném registrování a odregistrování modulu. Jedná se o přístupová práva, vlastníka, major a minor čísla.


Malá ukázka toho jak vytvořit nám již známé znakové zařízení lzdev.

devfs_h = devfs_register(
   NULL,                        // Umístění v adresáři /dev
   "lzdev",                     // Název našeho zařízení
   DEVFS_FL_AUTO_DEVNUM,        // Automaticke přiřazení major/minor
   0, 0,                        // Nepoužíté major/minor číslo
   S_IFCHR | S_IRUGO | S_IWUGO, // Znakové zařízení s právy rw-rw-rw-
   &basic_fops,                 // Základní souborové operace
   NULL);                       // Možnost nastavení filp->private data

Jak sami vidíte je to vcelku jednoduchá záležitost.

Symbolický link

Dále máme možnost vytváření linků. Někdo má například svoji CD-ROM mechaniku v počítači jako zařízení /dev/hdb a chce k ní přistupovat pomocí /dev/cdrom. Není nic jednoduššího než vytvořit symbolický link. Tuto možnost nám nabízí i devfs pomocí funkce devfs_mk_symlink s deklarací:

extern int devfs_mk_symlink (devfs_handle_t dir, const char *name,
			     unsigned int flags, const char *link,
			     devfs_handle_t *handle, void *info);

Parametry jsou analogicky odvoditelné od funkce devfs_register s tím, že parametr handle ukazuje na objekt na který má náš symbolický link odkazovat.

Rušení objektů

K tomu nám slouží funkce devfs_unregister s následující deklarací:

extern void devfs_unregister (devfs_handle_t de);

Jako parametr uvedeme handle vytvořeného objektu a rázem bude zrušen. Následující ukázka zruší výše vytvořené lzdev zařízení.

devfs_unregister(devfs_h);

Závěr devfs

Devfs nabízí mnoho dalších funkcí, ale není předmětem dalšího výkladu a tak případné zájemce odkazuji do patřičných hlavičkových souborů linux/devfs_fs_kernel.h a zdrojového kódu jádra.

K článku je připojena ukázka tvorby zařízení a nalézá se v souboru lzdevfs.c. Můžete ji prostudovat a vznést případné dotazy. Tímto končíme naše pojednání o Devfs a vrátíme se zpět ke slibovaným souborovým operacím.

Race conditions

Než si ukážeme další souborové operace je nutné se zastavit ještě u jedné věci. Tou jsou tzv. race conditions. Kdo již někdy programoval aplikaci složenou z vláken tak určitě ví o čem mluvím.

Co to je race conditions? Představme si, že naše zařízení bude otevřeno několika procesy (což je samozřejmě možné) a oba budou chtít přečíst určité kvantum dat. My máme naše data uložená v bufferu a v další proměnné je uložena aktuální pozice. Jeden proces začne data číst, posouvat ukazatel a najednou se do toho vloží proces druhý co začne s tímto ukazatelem také hýbat a data číst. Nikdy nepřečtou požadovaný konzistentní úsek data a naše zařízení nebude pracovat správně. Stejný problém nastává v případě zápisu a existuje zde spousta jiných možností.

Semafory

Jak tomu ale předejít. Jádro nabízí několik možností a my se zatím podíváme na tzv. semafory. Taková malá analogie ze všedního života. Je-li semafor (či závora) dole tak nemůžeme s autem přes přejezd a zvedne-li se závora, můžeme v klidu pokračovat. Přesně k tomuto účelu slouží naše semafory.

Deklarace všech potřebných věcí naleznete v hlavičkovém souboru asm/semaphore.h. Náš semafor je deklarován jako struktura semaphore a používá se následovně.

Semafor obsahuje číselnou hodnotu, která se při zavírání závory (semaforu) snižuje a při otevírání závory (semaforu) zvyšuje. Dostane-li se hodnota semaforu na nulu, žádný jiný proces nemůže tuto závoru dát dolů a tak mu nezbyde nic jiného než čekat tak dlouho dokud závoru (semafor) někdo nezvedne. Poté ji on sám může dát dolů a pokračovat v jízdě (běhu programu).

Asi jste zmatení a tak Vám ukážu základní funkce na obsluhu semaforů a podíváme se na ukázkový příklad.

První z nich je funkce inicializační a tou je sema_init() deklarována takto:

static inline void sema_init (struct semaphore *sem, int val)

První argument je ukazatel na náš semafor a druhý argument je počáteční hodnota semaforu. Ve velké většině se používá hodnota 1, ale existují případy kdy se dá použít i jiná (na to se podíváme jindy).

Semafor se dá dát dolů pomocí dvou funkcí down() a down_interruptible(). Jejich deklarace je následující:

static inline void down(struct semaphore * sem)
static inline int down_interruptible(struct semaphore * sem)

V prvním případě proces čeká tak dlouho, dokud se neukončí funkce down, resp. dokud nedá dolů semafor. Může se stát, že někde v kódu zapomenete zvednout semafor nahoru a tak vytvoříte nezničitelný proces. Proč? Protože proces ignoruje veškeré jemu zasílané signály.

Jak již z názvu plyne tak druhá funkce je přerušitelná. Vrací navíc hodnotu, která v případě 0 znamená úspěšné přesunutí semaforu směrem dolů. V opačném případě to znamená, že funkce byla přerušena signálem a my to musíme poslat dále. Obvyklé chování je vrácení chybového kódu -ERESTARTSYS.

Jak se semaforem nahoru? Na to existuje jednoduchá funkce up() deklarována takto:

static inline void up(struct semaphore * sem)

Ukázka

Představme si jednoduchou věc. Máme buffer, ukazatel na aktuální pozici a funkci pro zápis dat. Jak ošetřit, že se námi zapisovaná data nebudou přepisovat?

Deklarujeme si proměnnou typu struct semaphore a inicializujeme ji na hodnotu 1.

#include <asm/semaphore.h>

static struct semaphore sem;

static int __init
module_init(void)
{
  ...
  sema_init(&sem, 1);
  ...
}

Dále si představme, že máme neomezené pole buffer s aktuální pozicí uloženou v proměnné pos a píšeme funkci na zápis dat write_data().

static int
write_data(void *data, int len)
{
  if (down_interruptible(&sem))
    return -ERESTARTSYS;

  memcpy(buffer + pos, data, len);
  pos += len;

  up(&sem);

  return 0;
}

Toto je úplně smyšlená funkce, kterou nikdy na nic nepoužijete. Nám k výkladu stačí a teď si popíšeme co dělá. Na začátku se bude snažit dát semafor dolů, pokud se jí to povede zapíše data a semafor zase zvedne. Pokud se jí to nepovede, z důvodu přerušení, vrátí zápornou hodnotu a my ji pošleme dále. V opačném případě čeká tak dlouho dokud tu závoru jiný proces nezvedne. Poté ji sám dá znovu dolů a pokračuje dál.

Začnou-li tedy zapisovat dva procesy pomocí stejné funkce do stejného bufferu tak se nic nestane, protože jejich přístupy jsou oštřeny pomocí semaforu a tak jedna z nich musí počkat dokud ta první nedokončí svou práci.

Race conditions

Proč takto hrubý úvod do race conditions? K tomu je jeden prostý důvod - velmi brzy se podíváme na implementaci funkcí read/write pro naše zařízení a budeme nutně potřebovat ošetřit výše popsané situace.

K samotné problematice se v budoucnu trochu podrobněji určitě vrátíme.

Ukázka devfs

Nyní se podíváme na ukázku, která nám ukazuje jak v ovladači vytvořit námi požadovaná zařízení v adresáři /dev pomocí devfs. Ukázka je jednoduchá a komentovaná, takže nepotřebuje dalšího výkladu.

#ifdef MODULE

#include <linux/module.h>

MODULE_DESCRIPTION("LZ The device filesystem example"); 
MODULE_AUTHOR("Robert V0jta <robert@v0jta.net>");
MODULE_LICENSE("GPL");

#endif /* MODULE */

#ifndef CONFIG_DEVFS_FS
#error This module works only with The Device filesystem support
#endif

#include <linux/init.h>
#include <linux/fs.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/config.h>

// Maximalni pocet zarizeni
#define DEVICES 256

// Definuj typ lzdev_t ...
typedef struct lzdev
{
   devfs_handle_t devfs_handle;
   int devnum;
} lzdev_t;

// Vytvor promennou pro adresar /dev/lzdev
static devfs_handle_t lzdevfs_dir_handle;

// Vytvor pole pro informace o zarizenich v /dev/lzdev/
static lzdev_t lzdevs[DEVICES];

// Tato funkce je zavolana po zavreni souboru (ne vzdy), vetsinou 
// po poslednim zavreni souboru
static int
lz_release(struct inode *i, struct file *f)
{
   printk("<1>lz_release: Closing device number %d\n",
      ((lzdev_t *)f->private_data)->devnum);
   MOD_DEC_USE_COUNT;
   return 0;
}

// Tato funkce bude pouzivat pro vsechny zarizeni s major cislem. 
// V ni se rozhoduje jake operace priradime ruznym zarizenim 
// (ruznym minor cislum)
static int
lz_open(struct inode *i, struct file *f)
{
   MOD_INC_USE_COUNT;

   printk("<1>lz_open: Opening device number %d\n",
      ((lzdev_t *)f->private_data)->devnum);

   // Tady se podivame v jakem modu je nase zarizeni otevreno
      if ((f->f_mode & FMODE_READ) == FMODE_READ)
         printk("<1>lz_open: Opening device for reading%s\n",
            (f->f_mode & FMODE_WRITE) != FMODE_WRITE ? " only" : "");

   if ((f->f_mode & FMODE_WRITE) == FMODE_WRITE)
      printk("<1>lz_open: Opening device for writing%s\n",
         (f->f_mode & FMODE_READ) != FMODE_READ ? " only" : "");

   if ((f->f_flags & O_NONBLOCK) == O_NONBLOCK)
      printk("<1>lz_open: Opening device in non-blocking mode\n");

   return 0;
}

// Definice zakladni operace open na nase zarizeni
static struct file_operations basic_fops =
{
   open: lz_open,
   release: lz_release
};

// V pripade devfs musime zaregistrovat nase zarizeni
static int
lzdev_devfs_register(void)
{
   int i;
   char dev[16];

   // Vytvorime adresar /dev/lzdev
      lzdevfs_dir_handle = devfs_mk_dir(NULL, "lzdev", NULL);
      if (!lzdevfs_dir_handle)
         return -EBUSY;

      // A v nem 256 zarizeni s automatickym MAJOR, MINOR cislem
      for (i = 0 ; i < DEVICES ; i++)
         {
            lzdevs[i].devnum = i;
            snprintf(dev, sizeof(dev), "%i", i);

            lzdevs[i].devfs_handle = devfs_register(lzdevfs_dir_handle,
            dev, DEVFS_FL_AUTO_DEVNUM,
            0, 0, S_IFCHR | S_IRUGO | S_IWUGO,
            &basic_fops,
            &lzdevs[i]);
         }
}

// Pri odstranovani modulu musime nami vytvorene polozky 
// v /dev/ odstranit
static void
lzdev_devfs_unregister(void)
{
   int i;

   // Mame je vubec vytvorene?
   if (!lzdevfs_dir_handle)
      return;

   // Ano, odstran vsechny zarizeni v /dev/lzdev/
   for (i = 0; i < DEVICES ; i++)
      devfs_unregister(lzdevs[i].devfs_handle);

   // Odstran adresar /dev/lzdev
   devfs_unregister(lzdevfs_dir_handle);
}

// Funkce zaregistruje nase zarizeni, eventuelne zaroven pozada 
// o dynamicke prideleni major cisla a sdeli nam to pomoci printk()
static int __init
init_module(void)
{
   SET_MODULE_OWNER(&basic_fops);

   return lzdev_devfs_register();
}

// Funkce odregistruje nase znakove zarizeni a da nam o tom zpravu
static void __exit
cleanup_module(void)
{
   lzdev_devfs_unregister();
}

Závěr

Víme co je devfs, tušíme co to jsou race conditions a jak obsluhovat semafory. Nyní máme vědomosti na to, abychom v příštím díle začali s implementací funkcí read, write pro naše fiktivní zařízení.

Soubory

Použité ukázky v dnešním díle naleznete zde.

Další části seriálu:

Autor: Robert V0jta, 20. 11. 2002, 00:00
Sekce Programování, Komentářů: 14
Průměrné hodnocení: 3,06

o Poslat e-mailem
o Tisk článku
o Uložit do profilu


 Přispějte nám




Líbil se Vám tento článek? Můžete ho ocenit zavoláním na tel. číslo 906 460 134.
Cena hovoru za 1 minutu je 46 Kč.





 Hodnocení článku




Článek hodnotím jako:  [1] výborný   [2] dobrý   [3] průměr   [4] špatný   [5] hrůza  





 Komentáře




--

Robert V0jta, 10. 12. 2002 14:40
Re: CAT /PROC/DEVICES












--

m, 10. 12. 2002 03:26
cat /proc/devices












--

Robert V0jta, 28. 11. 2002 09:07
Re: CECKO












--

m, 28. 11. 2002 05:16
RE: cecko...












--

trn, 27. 11. 2002 15:27
cecko...












--

Robert V0jta, 27. 11. 2002 14:05
Re: MALICKOST












--

uklizec, 27. 11. 2002 13:57
malickost












--

Robert V0jta, 20. 11. 2002 13:04
Re: MALE RYPNUTI












--

Petr Dolezal, 20. 11. 2002 12:49
Male rypnuti












--

Petr Pechacek, 20. 11. 2002 10:55
Re: NEFUNGUJE LINK NA SOUBORY












--

Robert V0jta, 20. 11. 2002 10:48
Re: NEFUNGUJE LINK NA SOUBORY












--

Tomas Kasparek, 20. 11. 2002 09:32
RE: RACE CONITION












--

Petr, 20. 11. 2002 09:00
Race conditions












--

Polish, 20. 11. 2002 07:16
Nefunguje link na soubory















PŘIDAT KOMENTÁŘ ZOBRAZ VŠE >>










2002 © Impossible, s.r.o.   >> Kontaktujte redakci >> Právní upozornění >> Reklama