View of xos/usr/lib/libc/dirent.c


XOS | Parent Directory | View | Download

/* 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 <http://www.gnu.org/licenses/>. */
 
#include <dirent.h>
 
#include "fcntl.h"
#include "unistd.h"
 
#include <stdlib.h>
#include <errno.h>
 
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;
}