/* Copyright (C) 2008 Emmanuel Varoquaux This file is part of XOS. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include "fcntl.h" #include "unistd.h" #include #include struct __DIR { int fd; /* descripteur de fichier */ off_t offset; /* position dans le fichier */ struct dirent entry; /* espace de stockage pour une struct dirent */ }; static void init_dir(DIR *dirp, int fd) { dirp->fd = fd; dirp->offset = 0; } /* Definit l'attribut close-on-exec pour le descripteur de fichier sous-jacent. */ DIR __attribute__ ((weak, visibility ("default"))) *opendir(const char *dirname) { int fd; struct stat statbuf; int errnum; int flags; DIR *dirp; if ((fd = __open(dirname, O_RDONLY)) == -1) return NULL; if (__fstat(fd, &statbuf) == -1) { errnum = errno; goto error_close; } if (!S_ISDIR(statbuf.st_mode)) { errnum = ENOTDIR; goto error_close; } if ((flags = __fcntl(fd, F_GETFD)) == -1) { errnum = errno; goto error_close; } flags |= FD_CLOEXEC; if (__fcntl(fd, F_SETFD, flags) == -1) { errnum = errno; goto error_close; } if (!(dirp = malloc(sizeof (struct __DIR)))) { errnum = errno; goto error_close; } init_dir(dirp, fd); return dirp; error_close: __close(fd); errno = errnum; return NULL; } /* Laisse inchangee la configuration de l'attribut close-on-exec pour le * descripteur de fichier fd. */ DIR __attribute__ ((weak, visibility ("default"))) *fdopendir(int fd) { struct stat statbuf; DIR *dirp; if (__fstat(fd, &statbuf) == -1) return NULL; if (!S_ISDIR(statbuf.st_mode)) { errno = ENOTDIR; return NULL; } if (!(dirp = malloc(sizeof (struct __DIR)))) return NULL; init_dir(dirp, fd); return dirp; } int __attribute__ ((weak, visibility ("default"))) closedir(DIR *dirp) { int fd; fd = dirp->fd; free(dirp); if (__close(fd) == -1) return -1; return 0; } struct dirent __attribute__ ((weak, visibility ("default"))) *readdir(DIR *dirp) { ssize_t n; if ((n = __read(dirp->fd, dirp->entry.d_name, NAME_MAX + 1)) <= 0) /* erreur ou fin de fichier */ return NULL; dirp->offset += n; return &dirp->entry; } void __attribute__ ((weak, visibility ("default"))) seekdir(DIR *dirp, long loc) { __lseek(dirp->fd, loc, SEEK_SET); dirp->offset = loc; } long __attribute__ ((weak, visibility ("default"))) telldir(DIR *dirp) { return dirp->offset; } void __attribute__ ((weak, visibility ("default"))) rewinddir(DIR *dirp) { __lseek(dirp->fd, 0, SEEK_SET); dirp->offset = 0; } int __attribute__ ((weak, visibility ("default"))) dirfd(DIR *dirp) { return dirp->fd; }