GNU/Linux >> Znalost Linux >  >> Linux

Jak na to:Programování v C s adresáři na Linuxu

Když se říká, že v Linuxu je všechno soubor, pak to opravdu platí. Většinu operací, které můžeme provádět se soubory, lze provádět na jiných entitách, jako je soket, potrubí, adresáře atd.

Existují určité situace, kdy může softwarový nástroj cestovat přes adresáře v systému Linux najít nebo porovnat něco. Toto je případ použití, kdy se programátor tohoto nástroje musí zabývat programováním adresářů. V tomto článku tedy probereme následující základy programování adresářů na příkladu.

  1.  Vytváření adresářů.
  2.  Čtení adresářů.
  3.  Odebírání adresářů.
  4.  Zavření adresáře.
  5.  Získání aktuálního pracovního adresáře.

Projdeme si funkce, které se používají pro každý výše uvedený krok, a nakonec uvidíme příklad, který shrne všechny operace s adresáři.

1. Vytváření adresářů

Systém Linux poskytuje následující systémové volání pro vytvoření adresářů:

#include <sys/stat.h>
#include <sys/types.h>
int mkdir(const char *pathname, mode_t mode);

Argument ‚cesta‘ se používá pro název adresáře.

Z manuálové stránky :

Režim argumentů určuje oprávnění k použití. Umask procesu jej upravuje obvyklým způsobem:oprávnění vytvořeného adresáře jsou (režim &~umask &0777). Další bity režimu vytvořeného adresáře závisí na operačním systému. Pro Linux viz níže.

Nově vytvořený adresář bude vlastnit skutečné ID uživatele procesu. Pokud má adresář obsahující soubor nastavený bit set-group-ID nebo pokud je souborový systém připojen se sémantikou skupiny BSD (mount -o bsdgroups nebo synonymně mount -o grpid), nový adresář zdědí vlastnictví skupiny od jeho rodič; jinak bude ve vlastnictví efektivní skupiny ID procesu. Pokud má nadřazený adresář nastaven bit set-group-ID, pak bude nastaven i nově vytvořený adresář.

2. Čtení adresářů

Pro čtení obsahu adresáře se používá rodina funkcí.

1. Nejprve je třeba otevřít adresářový proud. To se provádí následujícím systémovým voláním :

#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);

Z manuálové stránky :

Funkce opendir() otevře adresářový proud odpovídající názvu adresáře a vrátí ukazatel na adresářový proud. Proud je umístěn na první položce v adresáři.

2. Dále, ke čtení položek v adresáři, použije výše otevřený proud následující systémové volání:

#include
struct dirent *readdir(DIR *dirp);

Z manuálové stránky :

Funkce readdir() vrací ukazatel na direntovou strukturu představující další položku adresáře v adresářovém proudu, na který ukazuje dirp. Vrací NULL při dosažení konce adresářového proudu nebo pokud došlo k chybě.

V Linuxu je struktura direntu definována následovně:

struct dirent
{
    ino_t          d_ino;       /* inode number */
    off_t          d_off;       /* offset to the next dirent */
    unsigned short d_reclen;    /* length of this record */
    unsigned char  d_type;      /* type of file; not supported
                                   by all file system types */
    char           d_name[256]; /* filename */
};

3. Odebírání adresářů

Systém Linux poskytuje následující systémové volání pro odstranění adresářů:

#include <unistd.h>
int rmdir(const char *pathname);

Z manuálové stránky :

rmdir() odstraní adresář reprezentovaný ‚cestou‘, pokud je prázdný. POKUD adresář není prázdný, tato funkce nebude úspěšná.

4. Zavírání adresářů

Systém Linux poskytuje následující systémové volání pro uzavření adresářů:

#include <sys/types.h>
#include <dirent.h>
int closedir(DIR *dirp);

Z manuálové stránky :

Funkce closedir() zavře adresářový proud spojený s dirp. Úspěšné volání closedir() také zavře základní deskriptor souboru spojený s dirp. Po tomto volání není popisovač toku adresáře dostupný.

5. Získání aktuálního pracovního adresáře

Systém Linux poskytuje následující systémové volání pro získání CWD:

#include <unistd.h>
char *getcwd(char *buf, size_t size);

Z manuálové stránky :

Funkce getcwd() zkopíruje absolutní název cesty k aktuálnímu pracovnímu adresáři do pole, na které ukazuje buf, které má velikost délky. Tato funkce vrací řetězec zakončený nulou obsahující absolutní název cesty, který je aktuálním pracovním adresářem proces volání. Název cesty je vrácen jako výsledek funkce a prostřednictvím argumentu buf, pokud je přítomen. Pokud délka názvu absolutní cesty aktuálního pracovního adresáře, včetně ukončovacího null bajtu, překročí velikost bajtů, vrátí se NULL a errno se nastaví na ERANGE; aplikace by měla tuto chybu zkontrolovat a v případě potřeby přidělit větší vyrovnávací paměť.

6. Příklad

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

int main (int argc, char *argv[])
{
    if(2 != argc)
    {
        printf("\n Please pass in the directory name \n");
        return 1;
    }

    DIR *dp = NULL;
    struct dirent *dptr = NULL;
    // Buffer for storing the directory path
    char buff[128];
    memset(buff,0,sizeof(buff));

    //copy the path set by the user
    strcpy(buff,argv[1]);

    // Open the directory stream
    if(NULL == (dp = opendir(argv[1])) )
    {
        printf("\n Cannot open Input directory [%s]\n",argv[1]);
        exit(1);
    }
    else
    {
        // Check if user supplied '/' at the end of directory name.
        // Based on it create a buffer containing path to new directory name 'newDir'
        if(buff[strlen(buff)-1]=='/')
        {
            strncpy(buff+strlen(buff),"newDir/",7);
        }
        else
        {
            strncpy(buff+strlen(buff),"/newDir/",8);
        }

        printf("\n Creating a new directory [%s]\n",buff);
        // create a new directory
        mkdir(buff,S_IRWXU|S_IRWXG|S_IRWXO);
        printf("\n The contents of directory [%s] are as follows \n",argv[1]);
        // Read the directory contents
        while(NULL != (dptr = readdir(dp)) )
        {
            printf(" [%s] ",dptr->d_name);
        }
        // Close the directory stream
        closedir(dp);
        // Remove the new directory created by us
        rmdir(buff);
        printf("\n");
    }

    return 0;
}

Výše uvedený příklad by nyní měl být samozřejmý.

Výstup výše uvedeného příkladu je:

# ./direntry /home/himanshu/practice/linux

 Creating a new directory [/home/himanshu/practice/linux/newDir/]

 The contents of directory [/home/himanshu/practice/linux] are as follows
 [redhat]  [newDir]  [linuxKernel]  [..]  [ubuntu]  [.]

Linux
  1. Pochopení systémových volání na Linuxu pomocí strace

  2. Linux Shutdown Command (s příklady)

  3. Vytváření, mazání a správa adresářů v systému Linux

  1. Zlepšete výkon systému Linux pomocí noatime

  2. Plánování systémových úloh pomocí Cronu na Linuxu

  3. Maximální počet souborů/adresářů na Linuxu?

  1. Monitorujte svůj systém Linux ve svém terminálu pomocí procps-ng

  2. Jak přejmenovat adresář v Linuxu

  3. Jak na to:Programování v C s dočasnými soubory v Linuxu