Logo Search packages:      
Sourcecode: ksh version File versions

open3d.c

/***********************************************************************
*                                                                      *
*               This software is part of the ast package               *
*           Copyright (c) 1989-2007 AT&T Knowledge Ventures            *
*                      and is licensed under the                       *
*                  Common Public License, Version 1.0                  *
*                      by AT&T Knowledge Ventures                      *
*                                                                      *
*                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

#include "3d.h"

/*
 * this does the actual open, creating versions as required
 */

static int
vcreate(register const char* path, int flags, int mode)
{
      register char*    cp;
      register char*    ep;
      int         dirlen;
      int         namlen;
      int         fd;
      int         r;
      char        buf[PATH_MAX+1];

      if (!state.vmap.size || !(flags & O_CREAT))
            return OPEN(path, flags, mode);
      ep = cp = (char*)path + strlen(path);
      if (!instance(state.path.name, cp, &state.path.st, 1))
            return OPEN(path, flags, mode);
      while (cp > (char*)path && *--cp != '/');
      if (*cp == '/') cp++;
      namlen = ep - cp;

      /*
       * construct pathname for version instance name text into buf
       */

      memcpy(buf, path, dirlen = cp - path);
      memcpy(buf + dirlen, state.opaque, 4);
      *ep = '/';
      strcpy(buf + dirlen + 4, cp);
      if ((fd = OPEN(buf, flags, mode)) >= 0)
            return fd;
      if (errno != ENOTDIR && errno != ENOENT)
            return -1;
      buf[dirlen + namlen + 4] = 0;
      if (MKDIR(buf, VERMODE))
      {
            buf[dirlen + 3] = 0;
            if (MKDIR(buf, VERMODE))
            {
                  if (errno != EEXIST)
                        return -1;
                  if (LSTAT(buf, &state.path.st))
                        return -1;

                  /*
                   * check for old style opaque, can be removed soon
                   */

                  if (S_ISREG(state.path.st.st_mode) && !(state.path.st.st_mode & S_IPERM))
                  {
                        char  savebuf[8];

                        memcpy(savebuf, cp, sizeof(savebuf));
                        strcpy(cp, "....");
                        if (RENAME(buf, path))
                        {
                              errno = EEXIST;
                              return -1;
                        }
                        if (MKDIR(buf, VERMODE))
                              return -1;
                        buf[dirlen + 3] = '.';
                        buf[dirlen + 4] = 0;
                        strcpy(cp, state.opaque);
                        if (RENAME(buf, path))
                        {
                              errno = EEXIST;
                              return -1;
                        }
                        memcpy(cp, savebuf, 8);
                        buf[dirlen + 3] = 0;
                        buf[dirlen + 4] = *cp;
                  }
                  else
                  {
                        errno = EEXIST;
                        return -1;
                  }
            }
            buf[dirlen + 3] = '/';
            if (MKDIR(buf, VERMODE))
                  return -1;
      }
      buf[dirlen + namlen + 4] = '/';

      /*
       * now create the file
       */

      if ((fd = OPEN(buf, flags, mode)) < 0)
            return -1;
      strcpy(buf + dirlen + namlen + 5, state.vdefault);
      *ep = 0;
      r = RENAME(path, buf);
      if (SYMLINK(buf + dirlen, path))
            return fd;
      if (r)
      {
            strcpy(buf + dirlen + namlen + 5, ep + 1);
            LINK(buf, path);
      }
      return fd;
}

int
open3d(const char* path, int oflag, ...)
{
      register char*    sp = 0;
      register int      r;
      int         fd = -1;
      int         level;
      int         synthesize;
      mode_t            mode;
      struct stat st;
      va_list           ap;
#if FS
      Mount_t*    mp;
#endif

      va_start(ap, oflag);
      mode = (oflag & O_CREAT) ? va_arg(ap, int) : 0;
      va_end(ap);
#if FS
      if (!fscall(NiL, MSG_open, 0, path, oflag, mode, 0))
      {
            message((-1, "DEBUG: fs open fd=%d", state.ret));
            return state.ret;
      }
      mp = monitored();
#endif
      if (state.in_2d)
      {
            if ((r = OPEN((!path || *path) ? path : state.dot, oflag, mode)) < 0 || !state.call.monitor || state.in_2d == 1 || FSTAT(r, &st))
                  return r;
            goto done;
      }
      for (;;)
      {
            if (!(sp = pathreal(path, (oflag & O_CREAT) ? P_NOOPAQUE : 0, &st)))
            {
                  if (oflag & O_CREAT)
                  {
                        Path_t      save;

                        save = state.path;
                        state.real++;
                        sp = pathreal(path, P_PATHONLY|P_DOTDOT, NiL);
                        state.real--;
                        if (!sp)
                        {
                              state.path = save;
                              errno = EROFS;
                              return -1;
                        }
                        if (state.path.level && LSTAT(sp, &st))
                        {
                              if (LSTAT(state.dot, &st) || fs3d_mkdir(sp, st.st_mode & S_IPERM))
                              {
                                    state.path = save;
                                    return -1;
                              }
                              state.path = save;
                              continue;
                        }
                        state.path = save;
                        sp = 0;
                  }
                  st.st_mode = 0;
            }
            else if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode))
            {
                  r = OPEN(path, oflag, mode);
                  goto done;
            }
            break;
      }
      level = state.path.level;
      synthesize = state.path.synthesize;
#if VCS && defined(VCS_OPEN)
      VCS_OPEN(path, oflag, mode, &state.path.st);
#endif
      if ((oflag & O_CREAT) && (!sp || level || (oflag & O_EXCL)) || (sp || level) && ((oflag & O_TRUNC) || (oflag & O_ACCMODE) != O_RDONLY))
      {
            if (sp)
            {
                  if ((oflag & O_ACCMODE) != O_RDONLY)
                  {
                        if (!level) 
                        {
                              r = OPEN(sp, oflag, mode);
                              goto done;
                        }
                        if (!(oflag & O_TRUNC) && (fd = OPEN(sp, O_RDONLY, 0)) < 0)
                              return -1;
                  }
                  mode = ((S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)|(st.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)));
            }
            if (!(sp = pathreal(path, (oflag & O_CREAT) ? (P_PATHONLY|P_SAFE) : 0, NiL)))
            {
                  if (fd >= 0)
                        CLOSE(fd);
                  return -1;
            }
            if (synthesize)
                  fs3d_mkdir(state.pwd, S_IRWXU|S_IRWXG|S_IRWXO);
      }
      else if (!sp)
      {
            r = -1;
            goto done;
      }
      r = vcreate(sp, ((oflag & O_ACCMODE) == O_RDWR) ? (oflag|O_CREAT) : oflag, mode);
      if (r < 0 && errno == ENOENT && ((oflag & (O_CREAT|O_TRUNC)) || (oflag & O_ACCMODE) != O_RDONLY))
      {
            if (!(sp = pathreal(path, P_PATHONLY|P_NOOPAQUE, NiL)))
                  r = -1;
            else if (state.level <= 0 || *sp == '/')
                  r = vcreate(sp, O_CREAT|oflag, mode);
            else errno = ENOENT;
            if (r < 0 && errno == ENOENT && (sp = pathreal(path, P_DOTDOT, NiL)) && state.path.level)
            {
                  if (sp = pathreal(path, P_DOTDOT|P_PATHONLY|P_NOOPAQUE, NiL))
                        r = fs3d_mkdir(sp, S_IRWXU|S_IRWXG|S_IRWXO);
                  if (!r)
                  {
                        /*
                         * try again
                         */

                        if (!(sp = pathreal(path, P_PATHONLY|P_SAFE, NiL)))
                              r = -1;
                        else r = vcreate(sp, O_CREAT|oflag, mode);
                  }
                  else errno = ENOENT;
            }
      }
      if (r > 0)
      {
            if (level && fd >= 0)
            {
                  if (fs3d_copy(fd, r, NiL))
                  {
                        CLOSE(r);
                        CLOSE(fd);
                        return -1;
                  }
                  state.path.level = 0;
            }
            state.path.open_level = state.path.level;
            setfdview(r, state.path.open_level);
      }
      if (fd >= 0)
            CLOSE(fd);
 done:
#if FS || defined(fchdir3d)
      if (r >= 0)
      {
#if defined(fchdir3d)
            if (S_ISDIR(st.st_mode) && r < elementsof(state.file))
            {
                  Dir_t*      dp;

                  if (state.file[r].dir)
                  {
                        free(state.file[r].dir);
                        state.file[r].dir = 0;
                  }
                  if (dp = newof(0, Dir_t, 1, strlen(sp)))
                  {
                        strcpy(dp->path, sp);
                        dp->dev = st.st_dev;
                        dp->ino = st.st_ino;
                        state.file[r].dir = dp;
                  }
            }
#endif
#if FS
            level = state.path.level;
            if (state.cache)
            {
                  if (!st.st_mode)
                        FSTAT(r, &st);
                  fileinit(r, &st, mp, 1);
            }
            if (mp)
                  fscall(mp, MSG_open, r, state.path.name, oflag, st.st_mode, level);
            for (mp = state.global; mp; mp = mp->global)
                  if (fssys(mp, MSG_open))
                        fscall(mp, MSG_open, r, state.path.name, oflag, st.st_mode, level);
#endif
      }
#endif
      return r;
}

/*
 * use this open() within 3d
 * to save and restore the path state
 */

int
fs3d_open(const char* path, int oflag, mode_t mode)
{
      int   fd;
      Path_t      save;

      save = state.path;
      fd = open(path, oflag, mode);
      state.path = save;
      return fd;
}

#if !_nosys_open64

int
open643d(const char* path, int oflag, ...)
{
      mode_t            mode;
      va_list           ap;

      va_start(ap, oflag);
      mode = (oflag & O_CREAT) ? va_arg(ap, int) : 0;
      va_end(ap);
#if defined(O_LARGEFILE)
      oflag |= O_LARGEFILE;
#endif
      return open(path, oflag, mode);
}

#endif

Generated by  Doxygen 1.6.0   Back to index