hier mal der quellcode:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
void dirprint(char *dir, char *name);
void dirread(char *dir);
void regprint(char *name);
void
dirprint(char *dir, char *name) {
char buf[1024];
printf("%s/\n", name);
sprintf(buf, "%s/%s", dir, name);
dirread(buf);
}
void
dirread(char *dir) {
DIR *d;
struct dirent *e;
struct stat st;
d = opendir(dir);
while((e = readdir(d)) != NULL) {
if((strcmp(e->d_name, ".") == 0)
|| (strcmp(e->d_name, "..") == 0))
continue;
switch(e->d_type) {
case DT_REG:
regprint(e->d_name);
break;
case DT_DIR:
dirprint(dir, e->d_name);
break;
case DT_UNKNOWN:
stat(e->d_name, &st);
if(S_ISREG(st.st_mode))
regprint(e->d_name);
if(S_ISDIR(st.st_mode))
dirprint(dir, e->d_name);
/*
switch(st.st_mode & S_IFMT) {
case S_IFREG:
printf("ifreg:");
regprint(e->d_name);
break;
case S_IFDIR:
dirprint(dir, e->d_name);
break;
default:
break;
}
*/
break;
default:
break;
}
}
closedir(d);
}
void
regprint(char *name) {
puts(name);
}
int
main(int argc, char *argv[]) {
dirread(argv[1]);
return 0;
}
ich versuche das gerade so einfach und leicht verstaendlich wie moeglich
zu implementieren fuer jegliche hinweise bin ich dankbar.
gruss yoshi
> Hallo, uebe mich gerade im implementieren von so etwas wie tree, find
> etc. (brauche nur einen teil der funktionalitaet). die dirent struktur
> wird ja nicht bei allen dateisystemen mit dem typ DT_REG bzw DT_DIR
> gefuellt, so sind unter xfs extra stat aufrufe notwendig (?) hier kann
> ich dann testen ob es sich um eine regulaere datei, ordner oder etwas
> ganz anderes handelt. habe das einmal mit macros und einmal ohne
> probiert (auskommentiert) beides entdeckt bei mir die ordner nicht, was
> mache ich denn falsch? zudem werden manche ordner, bzw. dateien einfach
> uebersprungen (auf xfs).
Die Komponente d_name enthält nur den Basisnamen der Datei, nicht den
Pfad. Du must dir also zuvor den Pfad zusammenstellen, ewta mit
snprintf(buf, sizeof buf, "%s/%s", dir, e->d_name);
PS: sprintf kann einen Bufferüberlauf verursachen.
Grüße Erich
--
EFEU 3.2 is released!
Get the open source from http://efeu.cybertec.at.
Hi,
> case DT_REG:
> regprint(e->d_name);
> break;
> case DT_DIR:
> dirprint(dir, e->d_name);
> break;
> case DT_UNKNOWN:
> ....
> break;
> default:
> break;
Was machst Du z.B. mit Softlinks, Sockets, Fifo, etc.?
> ... DT_REG bzw DT_DIR gefuellt, so sind unter xfs extra
> stat aufrufe notwendig (?)
Sollte das nicht nach default erfolgen?
DT_UNKNOWN beinhaltet die anderen nicht.
Auszug aus include/linux/fs.h
/*
* File types
*
* NOTE! These match bits 12..15 of stat.st_mode
* (ie "(i_mode >> 12) & 15").
*/
#define DT_UNKNOWN 0
#define DT_FIFO 1
#define DT_CHR 2
#define DT_DIR 4
#define DT_BLK 6
#define DT_REG 8
#define DT_LNK 10
#define DT_SOCK 12
#define DT_WHT 14
#define OSYNC_METADATA (1<<0)
#define OSYNC_DATA (1<<1)
#define OSYNC_INODE (1<<2)
int generic_osync_inode(struct inode *, struct address_space *, int);
Gru�
Martin
[...]
> PS: sprintf kann einen Buffer�berlauf verursachen.
Diese Aussage ist falsch. 'sprintf' ist eine Routine in der
C-Standardbibliothek und kann aus sich heraus gar nichts tun, sondern
jemand kann etwas damit tun: ZB, wie in dem fraglichen Code,
Zeichenketten unbekannter und grundsaetzlich beliebiger Laenge in
einen reservierten Speicherbereich endlicher Groesse zu kopieren. DAS
kann einen sogenannten 'Pufferueberlauf' verursachen, naemlich das
ueberschreiben von 'Speicher-Bytes' die nicht mehr zu dem reservierten
Bereich gehoeren, sondern lediglich mit Adressen korrespondieren, die
'hinter'[*] dem reservierten Bereich liegen.
[*] Man stelle sich zu diesem Zweck eine lange Reihe kleiner
Kisten vor vor der man steht. Die 'Speicheradresse' einer
dieser Kisten entsprich dann der Entfernung (in 'Kisten'
ausgedrueckt), die diese von der ersten Kiste hat.
trotzdem danke fuer den hinweis, gruss yoshi
Rainer Weikusat <rwei...@mssgmbh.com> schrieb:
> Erich Fruehstueck <ef....@aon.at> writes:
>
> [...]
>
>> PS: sprintf kann einen Bufferüberlauf verursachen.
ich moechte nur normale dateien und ordner betrachten, alles andere
moechte ich ignorieren
>
> > ... DT_REG bzw DT_DIR gefuellt, so sind unter xfs extra
> > stat aufrufe notwendig (?)
>
> Sollte das nicht nach default erfolgen?
>
> DT_UNKNOWN beinhaltet die anderen nicht.
so wie ich das verstanden habe wird d_type auf DT_UNKNOWN gesetzt
wenn z.B. auf einem xfs eine normale datei betrachtet wird.
anders gesagt wird d_type nur auf bestimmten fs (z.B. ext3 und ext4)
sinnvoll besetzt.
ich will mir unter ext3 etc. den extra stat aufruf sparen, das
funktioniert ja auch, was nicht funktioniert ist der stat aufruf selber
(auf xfs in meinem fall).
ich mache also irgendwas mit stat falsch oder xfs kann das auch nicht,
was ich aber nicht glaube.
danke und gruss, yoshi
> ich verwende sprintf um mir den pfad zu bauen und sollte da sicherlich
> besser snprintf verwenden, aber das ist ja nich das problem welches ich
> habe - will sagen wenn ich snprintf verwende bleibt mein problem
> bestehen.
Aber stat() rufst Du ohne zusammengebauten Pfad auf. Und hier liegt das
Problem.
Daß es am fehlerhaften stat-Aufruf liegt, weißt Du ja nun.
Ich würde so vorgehen:
[snip]
> void
> dirread(char *dir) {
> DIR *d;
> struct dirent *e;
> struct stat st;
>
> d = opendir(dir);
> while((e = readdir(d)) != NULL) {
unsigned char my_dt = e->d_type;
> if((strcmp(e->d_name, ".") == 0)
> || (strcmp(e->d_name, "..") == 0))
> continue;
if (my_dt == DT_UNKNOWN) {
// hier liegt, wie gesagt, Dein Problem:
char buf[100000]; // oder so ;-)
snprintf(buf,sizeof buf, "%s/%s",
dir, name); // hier...
stat(buf, &st);
// ...und hier fehlt noch Fehlerprüfung
// dann wäre auch klar geworden, was
// falsch ist
if(S_ISREG(st.st_mode)) {
my_dt = DT_REG;
} else if if(S_ISDIR(st.st_mode)) {
my_dt = DT_DIR;
}
}
switch(my_dt) {
> case DT_REG:
> regprint(e->d_name);
> break;
> case DT_DIR:
> dirprint(dir, e->d_name);
> break;
> }
> }
> closedir(d);
> }
HTH,
Thomas
danke und gruss, yoshi
Thomas Rachel <nutznetz-drei-...@spamschutz.glglgl.net> schrieb: