Logo Search packages:      
Sourcecode: ksh version File versions  Download package

dir3d.c

/***********************************************************************
*                                                                      *
*               This software is part of the ast package               *
*          Copyright (c) 1989-2007 AT&T Intellectual Property          *
*                      and is licensed under the                       *
*                  Common Public License, Version 1.0                  *
*                    by AT&T Intellectual Property                     *
*                                                                      *
*                A copy of the License is available at                 *
*            http://www.opensource.org/licenses/cpl1.0.txt             *
*         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
*                                                                      *
*              Information and Software Systems Research               *
*                            AT&T Research                             *
*                           Florham Park NJ                            *
*                                                                      *
*                 Glenn Fowler <gsf@research.att.com>                  *
*                  David Korn <dgk@research.att.com>                   *
*                   Eduardo Krell <ekrell@adexus.cl>                   *
*                                                                      *
***********************************************************************/
#pragma prototyped

/*
 * 3d directory(3)
 *
 * NOTE: there are 3 limitations to this implementation
 *
 *     (1) opendir() allocates one file descriptor for each directory
 *         view and these remain open until closedir()
 *
 *     (2) telldir() offsets are encoded with the directory view level
 *         and TELLDIR() offset, and the directory view level takes
 *         TABBITS bits, so TELLDIR() offsets are limited to (32-TABBITS)
 *         bits, but that would be one big physical directory
 *
 *    (3) if dirent.d_type supported then directory stat.st_nlink is
 *        inflated to foil viewpath subdirectory counting that would
 *        ship lower view subdirs not reflected in the top level st_nlink
 */

#define _def_map_ast    1
#define _std_strtol     1

#define getdirentries   ______getdirentries
#define sbrk            ______sbrk
#define strmode         ______strmode

#include <ast_std.h>

#undef      getdirentries
#undef      sbrk
#undef      strmode

#include "dir_3d.h"

#if !_dir_ok
#undef      dirent
#define dirent    DIRdirent
#endif

#undef      strtol
#undef      strtoul
#undef      strtoll
#undef      strtoull

static int  intercepted;

DIR*
opendir3d(const char* apath)
{
      register char*    path;
      register DIR*     dirp = 0;
      register int      n;
      int         oerrno;
      long        visits = 0;
      struct stat st;

      if (dirp = (DIR*)state.freedirp)
            state.freedirp = 0;
      else if (!(dirp = newof(0, DIR, 1, 0)))
            return 0;
      intercepted++;
      dirp->fd = -1;
      dirp->viewp = dirp->view;
      n = state.in_2d;
      if (path = pathreal(apath, P_SLASH, NiL))
            state.in_2d = 2;
      else
            path = (char*)apath;
      dirp->viewp->dirp = OPENDIR(path);
      state.in_2d = n;
      if (!dirp->viewp->dirp)
      {
            state.freedirp = (void*)dirp;
            intercepted = 0;
            return 0;
      }
      dirp->boundary = state.boundary;
      if (state.in_2d)
      {
            dirp->overlay = 0;
            (dirp->viewp++)->opaque = 0;
            dirp->viewp->dirp = 0;
      }
      else
      {
            oerrno = errno;
            n = strlen(path);
            path[n] = '/';
            strcpy(path + n + 1, state.opaque);
            dirp->viewp->level = state.path.level;
            state.in_2d++;
            (dirp->viewp++)->opaque = LSTAT(path, &st) ? 0 : st.st_ino;
            state.in_2d--;
            path[n] = 0;
            while (pathnext(state.path.name, NiL, &visits))
            {
                  state.in_2d = 2;
                  dirp->viewp->dirp = OPENDIR(state.path.name);
                  state.in_2d = 0;
                  if (dirp->viewp->dirp)
                  {
                        n = strlen(state.path.name);
                        state.path.name[n] = '/';
                        strcpy(state.path.name + n + 1, state.opaque);
                        dirp->viewp->level = state.path.level;
                        (dirp->viewp++)->opaque = LSTAT(state.path.name, &st) ? 0 : st.st_ino;
                        state.path.name[n] = 0;
                  }
            }
            errno = oerrno;
            (dirp->viewp--)->dirp = 0;
            if (dirp->viewp <= dirp->view)
                  dirp->overlay = 0;
            else if (!(dirp->overlay = hashalloc(NiL, HASH_set, HASH_ALLOCATE, 0)))
            {
                  closedir(dirp);
                  intercepted = 0;
                  return 0;
            }
      }
      dirp->viewp = dirp->view;
      CHEATDIR(dirp);
      intercepted = 0;
      return dirp;
}

int
closedir3d(register DIR* dirp)
{
      if (dirp)
      {
            if (intercepted++)
            {
                  intercepted--;
                  return CLOSEDIR(dirp);
            }
            for (dirp->viewp = dirp->view; dirp->viewp->dirp; dirp->viewp++)
                  CLOSEDIR(dirp->viewp->dirp);
            if (dirp->overlay)
                  hashfree(dirp->overlay);
            if (!state.freedirp)
                  state.freedirp = (void*)dirp;
            else
                  free((char*)dirp);
            intercepted--;
      }
      return 0;
}

struct dirent*
readdir3d(register DIR* dirp)
{
      register struct DIRdirent*    dp;
      register Dir_physical_t*      covered;

      if (intercepted++)
      {
            intercepted--;
            return READDIR(dirp);
      }
      for (;;)
      {
            while (!(dp = (struct DIRdirent*)READDIR(dirp->viewp->dirp)))
            {
                  if (!(++dirp->viewp)->dirp)
                  {
                        intercepted--;
                        return 0;
                  }
                  CHEATDIR(dirp);
            }
#ifdef D_FILENO
            if (!state.in_2d)
            {
                  register char*    s = dp->d_name;

                  /*
                   * skip opaque and hidden entries
                   */

                  if (*s++ == '.' && *s++ == '.' && *s++ == '.')
                  {
                        /*
                         * the following for old opaque
                         */

                        if (!*s && !dirp->viewp->opaque)
                              dirp->viewp->opaque = D_FILENO(dp);
                        continue;
                  }
            }
#endif

            /*
             * NOTE: this (slimey) method assumes READDIR() returns . first
             */

            if (dirp->overlay && (!dirp->boundary || dp->d_name[0] != '.' || dp->d_name[1]))
            {
                  if ((covered = (Dir_physical_t*)hashget(dirp->overlay, dp->d_name)) && covered < dirp->viewp)
                        continue;
                  if ((dirp->viewp + 1)->dirp)
                        hashput(dirp->overlay, 0, (char*)dirp->viewp);
            }
#ifdef D_FILENO
            if (D_FILENO(dp) == dirp->viewp->opaque)
                  continue;
#endif
            intercepted--;
            return (struct dirent*)dp;
      }
      /*NOTREACHED*/
}

#undef      seekdir

#define OFFBITS         (CHAR_BIT*sizeof(long)-TABBITS)
#define SETPOS(l,o)     ((((long)(l))<<OFFBITS)|GETOFF(o))
#define GETOFF(p) ((p)&((((long)1)<<OFFBITS)-1))
#define GETLEV(p) (((p)>>OFFBITS)&((((long)1)<<TABBITS)-1))

void
seekdir3d(register DIR* dirp, long pos)
{
      register int      n;
      int         lev;

      if (intercepted++)
      {
            intercepted--;
            SEEKDIR(dirp, pos);
            return;
      }
      if (pos)
      {
            lev = GETLEV(pos);
            pos = GETOFF(pos);
            for (n = 0; dirp->view[n].dirp; n++)
                  if (lev == dirp->view[n].level)
                        break;
      }
      else
      {
            n = 0;
            hashfree(dirp->overlay);
            dirp->overlay = hashalloc(NiL, HASH_set, HASH_ALLOCATE, 0);
      }
      if (dirp->view[n].dirp)
      {
            SEEKDIR(dirp->view[n].dirp, pos);
            dirp->viewp = &dirp->view[n];
            CHEATDIR(dirp);
            while (dirp->view[++n].dirp)
                  SEEKDIR(dirp->view[n].dirp, 0L);
      }
      intercepted--;
}

#undef      telldir

long
telldir3d(DIR* dirp)
{
      if (intercepted++)
      {
            intercepted--;
            return TELLDIR(dirp);
      }
      return SETPOS(dirp->viewp->level, TELLDIR(dirp->viewp->dirp));
}

#undef      rewinddir

void
rewinddir3d(register DIR* dirp)
{
      seekdir(dirp, 0L);
}

#if !_nosys_readdir64

struct dirent64*
readdir643d(register DIR* dirp)
{
      register struct dirent64*     dp;
      register Dir_physical_t*      covered;

      if (intercepted++)
      {
            intercepted--;
            return READDIR64(dirp);
      }
      for (;;)
      {
            while (!(dp = READDIR64(dirp->viewp->dirp)))
            {
                  if (!(++dirp->viewp)->dirp)
                  {
                        intercepted--;
                        return 0;
                  }
                  CHEATDIR(dirp);
            }
#ifdef D_FILENO
            if (!state.in_2d)
            {
                  register char*    s = dp->d_name;

                  /*
                   * skip opaque and hidden entries
                   */

                  if (*s++ == '.' && *s++ == '.' && *s++ == '.')
                  {
                        /*
                         * the following for old opaque
                         */

                        if (!*s && !dirp->viewp->opaque)
                              dirp->viewp->opaque = D_FILENO(dp);
                        continue;
                  }
            }
#endif

            /*
             * NOTE: this (slimey) method assumes READDIR() returns . first
             */

            if (dirp->overlay && (!dirp->boundary || dp->d_name[0] != '.' || dp->d_name[1]))
            {
                  if ((covered = (Dir_physical_t*)hashget(dirp->overlay, dp->d_name)) && covered < dirp->viewp)
                        continue;
                  if ((dirp->viewp + 1)->dirp)
                        hashput(dirp->overlay, 0, (char*)dirp->viewp);
            }
#ifdef D_FILENO
            if (D_FILENO(dp) == dirp->viewp->opaque)
                  continue;
#endif
            intercepted--;
            return dp;
      }
      /*NOTREACHED*/
}

#undef      seekdir

#define OFFBITS64 (CHAR_BIT*sizeof(off64_t)-TABBITS)
#define SETPOS64(l,o)   ((((off64_t)(l))<<OFFBITS)|GETOFF(o))
#define GETOFF64(p)     ((p)&((((off64_t)1)<<OFFBITS)-1))
#define GETLEV64(p)     (((p)>>OFFBITS)&((((off64_t)1)<<TABBITS)-1))

void
seekdir643d(register DIR* dirp, off64_t pos)
{
      register int      n;
      int         lev;

      if (intercepted++)
      {
            intercepted--;
            SEEKDIR64(dirp, pos);
            return;
      }
      if (pos)
      {
            lev = GETLEV(pos);
            pos = GETOFF(pos);
            for (n = 0; dirp->view[n].dirp; n++)
                  if (lev == dirp->view[n].level)
                        break;
      }
      else
      {
            n = 0;
            if (dirp->overlay)
            {
                  hashfree(dirp->overlay);
                  dirp->overlay = hashalloc(NiL, HASH_set, HASH_ALLOCATE, 0);
            }
      }
      if (dirp->view[n].dirp)
      {
            SEEKDIR64(dirp->view[n].dirp, pos);
            dirp->viewp = &dirp->view[n];
            CHEATDIR(dirp);
            while (dirp->view[++n].dirp)
                  SEEKDIR64(dirp->view[n].dirp, (off64_t)0);
      }
      intercepted--;
}

#undef      telldir

off64_t
telldir643d(DIR* dirp)
{
      if (intercepted)
            return TELLDIR64(dirp);
      return SETPOS(dirp->viewp->level, TELLDIR64(dirp->viewp->dirp));
}

#undef      rewinddir

void
rewinddir643d(register DIR* dirp)
{
      rewinddir(dirp);
}

#endif

#if !_mangle_syscall && (!_lib_opendir || !_hdr_dirent)

#include "dirlib.h"

#undef      _dir_ok

#define DIR       DIRDIR
#undef      DIRDIR
#define opendir         OPENDIR
#if defined(SYS3D_opendir)
#undef      OPENDIR
#endif
#define readdir         READDIR
#if defined(SYS3D_readdir)
#undef      READDIR
#endif
#define seekdir         SEEKDIR
#if defined(SYS3D_seekdir)
#undef      SEEKDIR
#endif
#define telldir         TELLDIR
#if defined(SYS3D_telldir)
#undef      TELLDIR
#endif
#define closedir  CLOSEDIR
#if defined(SYS3D_closedir)
#undef      CLOSEDIR
#endif

#define id        sys_id
#define freedirp  sys_freedirp

#ifndef     DIRBLKSIZ
#ifdef      DIRBLK
#define DIRBLKSIZ DIRBLK
#else
#ifdef      DIRBUF
#define DIRBLKSIZ DIRBUF
#else
#define DIRBLKSIZ 8192
#endif
#endif
#endif

#include "getdents.c"
#include "opendir.c"
#include "readdir.c"
#include "telldir.c"
#include "seekdir.c"

#if !_nosys_readdir64

#undef      dirent
#define dirent          dirent64
#undef      getdents
#define getdents  getdents64
#define DIR       DIRDIR
#undef      DIRDIR
#undef      readdir
#define readdir         READDIR64
#if defined(SYS3D_readdir64)
#undef      READDIR64
#endif

#if !_nosys_seekdir64
#undef      seekdir
#define seekdir         SEEKDIR64
#if defined(SYS3D_seekdir64)
#undef      SEEKDIR64
#endif
#endif

#if !_nosys_telldir64
#undef      telldir
#define telldir         TELLDIR64
#if defined(SYS3D_telldir64)
#undef      TELLDIR64
#endif
#endif

#include "readdir.c"

#if !_nosys_telldir64
#include "telldir.c"
#endif

#if !_nosys_seekdir64
#include "seekdir.c"
#endif

#endif

#endif

Generated by  Doxygen 1.6.0   Back to index