Exemple #1
0
static
void
try___getcwd(int dofork)
{
	void * a0 = randptr();
	size_t a1 = randsize();
	int result, pid, status;
	char buf[128];

	snprintf(buf, sizeof(buf), "__getcwd(%p, %lu)",
		(a0), (unsigned long)(a1));
	printf("%-47s", buf);

	pid = dofork ? fork() : 0;
	if (pid<0) {
		err(1, "fork");
	}
	if (pid>0) {
		waitpid(pid, &status, 0);
		return;
	}

	result = __getcwd(a0, a1);
	printf(" result %d, errno %d\n", result, errno);
	if (dofork) {
		exit(0);
	}
}
Exemple #2
0
char *
__getwd_chk (char *buf, size_t buflen)
{
  char *res = __getcwd (buf, buflen);
  if (res == NULL && errno == ERANGE)
    __chk_fail ();
  return res;
}
char *
__getcwd_chk (char *buf, size_t size, size_t buflen)
{
  if (size > buflen)
    __chk_fail ();

  return __getcwd (buf, size);
}
Exemple #4
0
// Returns the current directory
std::string GetCurrentDir() {
    char *dir;
    // Get the current working directory (getcwd uses malloc) 
    if (!(dir = __getcwd(NULL, 0))) {

        LOG_ERROR(TCOMMON, "GetCurrentDirectory failed:");
        return NULL;
    }
    std::string strDir = dir;
    free(dir);
    return strDir;
}
Exemple #5
0
// Returns the current directory
std::string GetCurrentDir()
{
  // Get the current working directory (getcwd uses malloc)
  char* dir = __getcwd(nullptr, 0);
  if (!dir)
  {
    ERROR_LOG(COMMON, "GetCurrentDirectory failed: %s", GetLastErrorMsg().c_str());
    return nullptr;
  }
  std::string strDir = dir;
  free(dir);
  return strDir;
}
// Returns the current directory
std::string GetCurrentDir()
{
	char *dir;
	// Get the current working directory (getcwd uses malloc) 
	if (!(dir = __getcwd(NULL, 0))) {

		ERROR_LOG(COMMON, "GetCurrentDirectory failed: %s",
				GetLastErrorMsg());
		return NULL;
	}
	std::string strDir = dir;
	free(dir);
	return strDir;
}
Exemple #7
0
// Returns the current directory
std::string GetCurrentDir()
{
    char *dir;
    // Get the current working directory (getcwd uses malloc)
    if (!(dir = __getcwd(nullptr, 0))) {

        LOG_ERROR(Common_Filesystem, "GetCurrentDirectory failed: %s",
                GetLastErrorMsg());
        return nullptr;
    }
    std::string strDir = dir;
    free(dir);
    return strDir;
}
Exemple #8
0
int
main(int argc, char *argv[])
{
  (void)argc;
  (void)argv;

  char buf[128];
  if(__getcwd(buf, sizeof(buf)-1)){
    printf("getcwd err: %d\n", errno);
  }
  printf("Initial directory: %s\n", buf);

  if (chdir("testdir") != 0)
    printf("chdir failed: %d\n", errno);
  printf("success!\n");

  if(__getcwd(buf, sizeof(buf)-1)){
    printf("getcwd err: %d\n", errno);
  }
  printf("Changed directory: %s\n", buf);

  return 0;
}
char *
get_current_dir_name (void)
{
  char *pwd;
  struct stat64 dotstat, pwdstat;

  pwd = getenv ("PWD");
  if (pwd != NULL
      && stat64 (".", &dotstat) == 0
      && stat64 (pwd, &pwdstat) == 0
      && pwdstat.st_dev == dotstat.st_dev
      && pwdstat.st_ino == dotstat.st_ino)
    /* The PWD value is correct.  Use it.  */
    return __strdup (pwd);

  return __getcwd ((char *) NULL, 0);
}
Exemple #10
0
char*
getwd (char *buf)
{
	char mybuf[PATH_MAX];
  
	if (buf == NULL) {
  		__set_errno (EINVAL);
  		return NULL;
  	}
  	
  	if (__getcwd (mybuf, PATH_MAX) == NULL) {
  	  __strerror_r (errno, buf, PATH_MAX);
  	  return NULL;
  	}
  	
  	return strcpy (buf, mybuf);  /* Ouch.  */
}
Exemple #11
0
char *
getcwd(char *buf, size_t size)
{
	char *allocated = NULL;

	if (buf != NULL && size == 0) {
		errno = EINVAL;
		return (NULL);
	}

	if (buf == NULL &&
	    (allocated = buf = malloc(size = PATH_MAX)) == NULL)
		return (NULL);

	if (__getcwd(buf, size) == -1) {
		free(allocated);
		return (NULL);
	}

	return (buf);
}
Exemple #12
0
char *
getcwd(char *pt, size_t size)
{
	int allocated = 0, ret;

	/*
	 * If no buffer specified by the user, allocate one as necessary.
	 */
	if (pt == NULL) {
		size = MAXPATHLEN;
		if ((pt = malloc(MAXPATHLEN)) == NULL)
			return(NULL);
		allocated = 1;
	}
	ret = __getcwd(pt, size);
	if (ret == 0)
		return (pt);
	if (allocated)
		free(pt);
	return (NULL);
}
char *
__realpath (const char *name, char *resolved)
{
  char *rpath, *dest, *extra_buf = NULL;
  const char *start, *end, *rpath_limit;
  long int path_max;
  int num_links = 0;
  size_t prefix_len;

  if (name == NULL)
    {
      /* As per Single Unix Specification V2 we must return an error if
         either parameter is a null pointer.  We extend this to allow
         the RESOLVED parameter to be NULL in case the we are expected to
         allocate the room for the return value.  */
      __set_errno (EINVAL);
      return NULL;
    }

  if (name[0] == '\0')
    {
      /* As per Single Unix Specification V2 we must return an error if
         the name argument points to an empty string.  */
      __set_errno (ENOENT);
      return NULL;
    }

#ifdef PATH_MAX
  path_max = PATH_MAX;
#else
  path_max = pathconf (name, _PC_PATH_MAX);
  if (path_max <= 0)
    path_max = 8192;
#endif

  if (resolved == NULL)
    {
      rpath = malloc (path_max);
      if (rpath == NULL)
        {
          /* It's easier to set errno to ENOMEM than to rely on the
             'malloc-posix' gnulib module.  */
          errno = ENOMEM;
          return NULL;
        }
    }
  else
    rpath = resolved;
  rpath_limit = rpath + path_max;

  /* This is always zero for Posix hosts, but can be 2 for MS-Windows
     and MS-DOS X:/foo/bar file names.  */
  prefix_len = FILE_SYSTEM_PREFIX_LEN (name);

  if (!IS_ABSOLUTE_FILE_NAME (name))
    {
      if (!__getcwd (rpath, path_max))
        {
          rpath[0] = '\0';
          goto error;
        }
      dest = strchr (rpath, '\0');
      start = name;
      prefix_len = FILE_SYSTEM_PREFIX_LEN (rpath);
    }
  else
    {
      dest = rpath;
      if (prefix_len)
        {
          memcpy (rpath, name, prefix_len);
          dest += prefix_len;
        }
      *dest++ = '/';
      if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
        {
          if (ISSLASH (name[1]) && !ISSLASH (name[2]) && !prefix_len)
            *dest++ = '/';
          *dest = '\0';
        }
      start = name + prefix_len;
    }

  for (end = start; *start; start = end)
    {
#ifdef _LIBC
      struct stat64 st;
#else
      struct stat st;
#endif
      int n;

      /* Skip sequence of multiple path-separators.  */
      while (ISSLASH (*start))
        ++start;

      /* Find end of path component.  */
      for (end = start; *end && !ISSLASH (*end); ++end)
        /* Nothing.  */;

      if (end - start == 0)
        break;
      else if (end - start == 1 && start[0] == '.')
        /* nothing */;
      else if (end - start == 2 && start[0] == '.' && start[1] == '.')
        {
          /* Back up to previous component, ignore if at root already.  */
          if (dest > rpath + prefix_len + 1)
            for (--dest; dest > rpath && !ISSLASH (dest[-1]); --dest)
              continue;
          if (DOUBLE_SLASH_IS_DISTINCT_ROOT
              && dest == rpath + 1 && !prefix_len
              && ISSLASH (*dest) && !ISSLASH (dest[1]))
            dest++;
        }
      else
        {
          size_t new_size;

          if (!ISSLASH (dest[-1]))
            *dest++ = '/';

          if (dest + (end - start) >= rpath_limit)
            {
              ptrdiff_t dest_offset = dest - rpath;
              char *new_rpath;

              if (resolved)
                {
                  __set_errno (ENAMETOOLONG);
                  if (dest > rpath + prefix_len + 1)
                    dest--;
                  *dest = '\0';
                  goto error;
                }
              new_size = rpath_limit - rpath;
              if (end - start + 1 > path_max)
                new_size += end - start + 1;
              else
                new_size += path_max;
              new_rpath = (char *) realloc (rpath, new_size);
              if (new_rpath == NULL)
                {
                  /* It's easier to set errno to ENOMEM than to rely on the
                     'realloc-posix' gnulib module.  */
                  errno = ENOMEM;
                  goto error;
                }
              rpath = new_rpath;
              rpath_limit = rpath + new_size;

              dest = rpath + dest_offset;
            }

#ifdef _LIBC
          dest = __mempcpy (dest, start, end - start);
#else
          memcpy (dest, start, end - start);
          dest += end - start;
#endif
          *dest = '\0';

#ifdef _LIBC
          if (__lxstat64 (_STAT_VER, rpath, &st) < 0)
#else
          if (lstat (rpath, &st) < 0)
#endif
            goto error;

          if (S_ISLNK (st.st_mode))
            {
              char *buf;
              size_t len;

              if (++num_links > MAXSYMLINKS)
                {
                  __set_errno (ELOOP);
                  goto error;
                }

              buf = malloca (path_max);
              if (!buf)
                {
                  errno = ENOMEM;
                  goto error;
                }

              n = __readlink (rpath, buf, path_max - 1);
              if (n < 0)
                {
                  int saved_errno = errno;
                  freea (buf);
                  errno = saved_errno;
                  goto error;
                }
              buf[n] = '\0';

              if (!extra_buf)
                {
                  extra_buf = malloca (path_max);
                  if (!extra_buf)
                    {
                      freea (buf);
                      errno = ENOMEM;
                      goto error;
                    }
                }

              len = strlen (end);
              if ((long int) (n + len) >= path_max)
                {
                  freea (buf);
                  __set_errno (ENAMETOOLONG);
                  goto error;
                }

              /* Careful here, end may be a pointer into extra_buf... */
              memmove (&extra_buf[n], end, len + 1);
              name = end = memcpy (extra_buf, buf, n);

              if (IS_ABSOLUTE_FILE_NAME (buf))
                {
                  size_t pfxlen = FILE_SYSTEM_PREFIX_LEN (buf);

                  if (pfxlen)
                    memcpy (rpath, buf, pfxlen);
                  dest = rpath + pfxlen;
                  *dest++ = '/'; /* It's an absolute symlink */
                  if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
                    {
                      if (ISSLASH (buf[1]) && !ISSLASH (buf[2]) && !pfxlen)
                        *dest++ = '/';
                      *dest = '\0';
                    }
                  /* Install the new prefix to be in effect hereafter.  */
                  prefix_len = pfxlen;
                }
              else
                {
                  /* Back up to previous component, ignore if at root
                     already: */
                  if (dest > rpath + prefix_len + 1)
                    for (--dest; dest > rpath && !ISSLASH (dest[-1]); --dest)
                      continue;
                  if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1
                      && ISSLASH (*dest) && !ISSLASH (dest[1]) && !prefix_len)
                    dest++;
                }
            }
          else if (!S_ISDIR (st.st_mode) && *end != '\0')
            {
              __set_errno (ENOTDIR);
              goto error;
            }
        }
    }
  if (dest > rpath + prefix_len + 1 && ISSLASH (dest[-1]))
    --dest;
  if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1 && !prefix_len
      && ISSLASH (*dest) && !ISSLASH (dest[1]))
    dest++;
  *dest = '\0';

  if (extra_buf)
    freea (extra_buf);

  return rpath;

error:
  {
    int saved_errno = errno;
    if (extra_buf)
      freea (extra_buf);
    if (resolved == NULL)
      free (rpath);
    errno = saved_errno;
  }
  return NULL;
}
Exemple #14
0
void
mips_syscall(struct trapframe *tf)
{
	int callno;
	int32_t retval;
	int err;

	assert(curspl==0);

	callno = tf->tf_v0;

	/*
	 * Initialize retval to 0. Many of the system calls don't
	 * really return a value, just 0 for success and -1 on
	 * error. Since retval is the value returned on success,
	 * initialize it to 0 by default; thus it's not necessary to
	 * deal with it except for calls that return other values,
	 * like write.
	 * fk: we also initialize err to be 0 (no error by default)
	 */

	retval = 0;
	err = 0;	// -- fk --


	switch (callno) {

		case SYS_reboot:
		err = sys_reboot(tf->tf_a0);
		break;

		/* Add stuff here */
		// --- fk ---
		case SYS_open:
		retval = open(tf->tf_a0, tf->tf_a1);
		break;

		case SYS_read:
		retval = read(tf->tf_a0, tf->tf_a1, tf->tf_a2);
		break;

		case SYS_write:
		retval = write(tf->tf_a0, tf->tf_a1, tf->tf_a2);
		break;

		case SYS_close:
		retval = close(tf->tf_a0);
		break;

		case SYS_lseek:
		retval = lseek(tf->tf_a0, tf->tf_a1, tf->tf_a2);
		break;

		case SYS_chdir:
		retval = chdir(tf->tf_a0);
		break;

		case SYS___getcwd:
		retval = __getcwd(tf->tf_a0, tf->tf_a1);
		break;

		case SYS_dup2:
		retval = dup2(tf->tf_a0, tf->tf_a1);
		break;
		// --- /fk ---

		default:
		kprintf("Unknown syscall %d\n", callno);
		err = ENOSYS;
		break;
	}


	// --- fk ---
	if (retval == -1){
		err = file_errno;
	}
	// --- /fk ---



	if (err) {
		/*
		 * Return the error code. This gets converted at
		 * userlevel to a return value of -1 and the error
		 * code in errno.
		 */
		tf->tf_v0 = err;
		tf->tf_a3 = 1;      /* signal an error */
	}
	else {
		/* Success. */
		tf->tf_v0 = retval;
		tf->tf_a3 = 0;      /* signal no error */
	}
	
	/*
	 * Now, advance the program counter, to avoid restarting
	 * the syscall over and over again.
	 */
	
	tf->tf_epc += 4;

	/* Make sure the syscall code didn't forget to lower spl */
	assert(curspl==0);
}
Exemple #15
0
bool Process::start() {

#ifdef WIN32

	handle_IN_Rd = NULL;
	handle_IN_Wr = NULL;
	handle_OUT_Rd = NULL;
	handle_OUT_Wr = NULL;
	handle_ERR_Rd = NULL;
	handle_ERR_Wr = NULL;

	p_stdin = -1;
	p_stdout = -1;
	p_stderr = -1;

	SECURITY_ATTRIBUTES saAttr; 

	saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
	saAttr.bInheritHandle = TRUE; 
	saAttr.lpSecurityDescriptor = NULL; 

	// Create a pipe for the child process's STDOUT. 
   if ( ! CreatePipe(&handle_OUT_Rd, &handle_OUT_Wr, &saAttr, 0) ) 
      return false; 

	// Create a pipe for the child process's STDERR. 
   if ( ! CreatePipe(&handle_ERR_Rd, &handle_ERR_Wr, &saAttr, 0) ) 
      return false; 

    // Create a pipe for the child process's STDIN. 
    if (! CreatePipe(&handle_IN_Rd, &handle_IN_Wr, &saAttr, 0)) 
        return false; 

    if (explicit_mode) {
 
        if ( ! SetHandleInformation(handle_IN_Rd, HANDLE_FLAG_INHERIT, 1) )
            return false; 

        if ( ! SetHandleInformation(handle_OUT_Wr, HANDLE_FLAG_INHERIT, 1) )
            return false; 

    } 

    // Ensure the write handle to the pipe for STDIN is not inherited.  
    if ( ! SetHandleInformation(handle_IN_Wr, HANDLE_FLAG_INHERIT, 0) )
        return false; 

    // Ensure the read handle to the pipe for STDOUT is not inherited.
    if ( ! SetHandleInformation(handle_OUT_Rd, HANDLE_FLAG_INHERIT, 0) )
        return false; 

    // Ensure the read handle to the pipe for STDERR is not inherited.
    if ( ! SetHandleInformation(handle_ERR_Rd, HANDLE_FLAG_INHERIT, 0) )
        return false; 


	STARTUPINFO siStartInfo;
	BOOL bSuccess = FALSE; 
 
	// Set up members of the PROCESS_INFORMATION structure. 
 
	ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
 

	stringstream cmdbuffer;
	int curargument = 0;
	while (arguments[curargument]) {
		cmdbuffer << "\"" << arguments[curargument] << "\" ";
		curargument++;
	}


	stringstream envbuffer;
    map<string, string>::iterator iter;
    for (iter = env.begin(); iter != env.end(); ++iter) {
        envbuffer << iter->first << string("=") << iter->second << '\0';
    }

	// Set up members of the STARTUPINFO structure. 
	// This structure specifies the STDIN and STDOUT handles for redirection.
	ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
	siStartInfo.cb = sizeof(STARTUPINFO); 
    if (!explicit_mode) {
	    siStartInfo.hStdError = handle_ERR_Wr;
	    siStartInfo.hStdOutput = handle_OUT_Wr;
	    siStartInfo.hStdInput = handle_IN_Rd;
        siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
    } else {
	    siStartInfo.hStdError = handle_ERR_Wr;
		HANDLE pHandle = GetCurrentProcess();
		HANDLE handle_IN_Rd2, handle_OUT_Wr2;
		DuplicateHandle(pHandle, handle_IN_Rd, pHandle, &handle_IN_Rd2, DUPLICATE_SAME_ACCESS, true, DUPLICATE_SAME_ACCESS);
		DuplicateHandle(pHandle, handle_OUT_Wr, pHandle, &handle_OUT_Wr2, DUPLICATE_SAME_ACCESS, true, DUPLICATE_SAME_ACCESS);
        envbuffer << string("TRAX_IN=") << handle_IN_Rd2 << '\0';
        envbuffer << string("TRAX_OUT=") << handle_OUT_Wr2 << '\0';
    }
	
    envbuffer << '\0';
	
	LPCSTR curdir = directory.empty() ? NULL : directory.c_str();

	if (!CreateProcess(NULL, (char *) cmdbuffer.str().c_str(), NULL, NULL, true, 0,
		(void *)envbuffer.str().c_str(),
		curdir, &siStartInfo, &piProcInfo )) {

		std::cout << "Error: " << GetLastError()  << std::endl;
		cleanup();
		return false;
	}

	int wrfd = _open_osfhandle((intptr_t)handle_IN_Wr, 0);
	int rdfd = _open_osfhandle((intptr_t)handle_OUT_Rd, _O_RDONLY);
	int erfd = _open_osfhandle((intptr_t)handle_ERR_Rd, _O_RDONLY);

	if (wrfd == -1 || rdfd == -1) {
		stop();
		return false;
	}

    p_stdin = wrfd;
    p_stdout = rdfd;
    p_stderr = erfd;

	if (!p_stdin || !p_stdout) {
		stop();
		return false;
	}

#else

    if (pid) return false;

    pipe(out);
    pipe(in);
    pipe(err);

    vector<string> vars;

    map<string, string>::iterator iter;
    for (iter = env.begin(); iter != env.end(); ++iter) {
       // if (iter->first == "PWD") continue;
        vars.push_back(iter->first + string("=") + iter->second);
    }

    posix_spawn_file_actions_init(&action);
    posix_spawn_file_actions_addclose(&action, out[1]);
    posix_spawn_file_actions_addclose(&action, in[0]);
    posix_spawn_file_actions_addclose(&action, err[0]);

    if (!explicit_mode) {
        posix_spawn_file_actions_adddup2(&action, out[0], 0);
        posix_spawn_file_actions_adddup2(&action, in[1], 1);
        posix_spawn_file_actions_adddup2(&action, err[1], 2);
    } else {
        posix_spawn_file_actions_adddup2(&action, err[1], 2);
        vars.push_back(string("TRAX_OUT=") + int_to_string(in[1]));
        vars.push_back(string("TRAX_IN=") + int_to_string(out[0]));
    }

    std::vector<char *> vars_c(vars.size() + 1); 

    for (std::size_t i = 0; i != vars.size(); ++i) {
        vars_c[i] = &vars[i][0];
    }

    vars_c[vars.size()] = NULL;

    string cwd = __getcwd();

    if (directory.size() > 0)
        chdir(directory.c_str());

    if (posix_spawnp(&pid, program, &action, NULL, arguments, vars_c.data())) {
        cleanup();
        pid = 0;
        if (directory.size() > 0) chdir(cwd.c_str());
        return false;
    }

    if (directory.size() > 0) chdir(cwd.c_str());

    p_stdin = out[1];
    p_stdout = in[0];
    p_stderr = err[0];

#endif

    return true;

}
Exemple #16
0
ftw_startup (const char *dir, int is_nftw, void *func, int descriptors,
	     int flags)
{
  struct ftw_data data;
  struct STAT st;
  int result = 0;
  int save_err;
  int cwdfd = -1;
  char *cwd = NULL;
  char *cp;

  /* First make sure the parameters are reasonable.  */
  if (dir[0] == '\0')
    {
      __set_errno (ENOENT);
      return -1;
    }

  data.maxdir = descriptors < 1 ? 1 : descriptors;
  data.actdir = 0;
  data.dirstreams = (struct dir_data **) alloca (data.maxdir
						 * sizeof (struct dir_data *));
  memset (data.dirstreams, '\0', data.maxdir * sizeof (struct dir_data *));

  /* PATH_MAX is always defined when we get here.  */
  data.dirbufsize = MAX (2 * strlen (dir), PATH_MAX);
  data.dirbuf = (char *) malloc (data.dirbufsize);
  if (data.dirbuf == NULL)
    return -1;
  cp = __stpcpy (data.dirbuf, dir);
  /* Strip trailing slashes.  */
  while (cp > data.dirbuf + 1 && cp[-1] == '/')
    --cp;
  *cp = '\0';

  data.ftw.level = 0;

  /* Find basename.  */
  while (cp > data.dirbuf && cp[-1] != '/')
    --cp;
  data.ftw.base = cp - data.dirbuf;

  data.flags = flags;

  /* This assignment might seem to be strange but it is what we want.
     The trick is that the first three arguments to the `ftw' and
     `nftw' callback functions are equal.  Therefore we can call in
     every case the callback using the format of the `nftw' version
     and get the correct result since the stack layout for a function
     call in C allows this.  */
  data.func = (NFTW_FUNC_T) func;

  /* Since we internally use the complete set of FTW_* values we need
     to reduce the value range before calling a `ftw' callback.  */
  data.cvt_arr = is_nftw ? nftw_arr : ftw_arr;

  /* No object known so far.  */
  data.known_objects = NULL;

  /* Now go to the directory containing the initial file/directory.  */
  if (flags & FTW_CHDIR)
    {
      /* We have to be able to go back to the current working
	 directory.  The best way to do this is to use a file
	 descriptor.  */
      cwdfd = __open (".", O_RDONLY | O_DIRECTORY);
      if (cwdfd == -1)
	{
	  /* Try getting the directory name.  This can be needed if
	     the current directory is executable but not readable.  */
	  if (errno == EACCES)
	    /* GNU extension ahead.  */
	    cwd =  __getcwd (NULL, 0);

	  if (cwd == NULL)
	    goto out_fail;
	}
      else if (data.maxdir > 1)
	/* Account for the file descriptor we use here.  */
	--data.maxdir;

      if (data.ftw.base > 0)
	{
	  /* Change to the directory the file is in.  In data.dirbuf
	     we have a writable copy of the file name.  Just NUL
	     terminate it for now and change the directory.  */
	  if (data.ftw.base == 1)
	    /* I.e., the file is in the root directory.  */
	    result = __chdir ("/");
	  else
	    {
	      char ch = data.dirbuf[data.ftw.base - 1];
	      data.dirbuf[data.ftw.base - 1] = '\0';
	      result = __chdir (data.dirbuf);
	      data.dirbuf[data.ftw.base - 1] = ch;
	    }
	}
    }

  /* Get stat info for start directory.  */
  if (result == 0)
    {
      const char *name;

      if (data.flags & FTW_CHDIR)
	{
	  name = data.dirbuf + data.ftw.base;
	  if (name[0] == '\0')
	    name = ".";
	}
      else
	name = data.dirbuf;

      if (((flags & FTW_PHYS)
	   ? LXSTAT (_STAT_VER, name, &st)
	   : XSTAT (_STAT_VER, name, &st)) < 0)
	{
	  if (!(flags & FTW_PHYS)
	      && errno == ENOENT
	      && LXSTAT (_STAT_VER, name, &st) == 0
	      && S_ISLNK (st.st_mode))
	    result = (*data.func) (data.dirbuf, &st, data.cvt_arr[FTW_SLN],
				   &data.ftw);
	  else
	    /* No need to call the callback since we cannot say anything
	       about the object.  */
	    result = -1;
	}
      else
	{
	  if (S_ISDIR (st.st_mode))
	    {
	      /* Remember the device of the initial directory in case
		 FTW_MOUNT is given.  */
	      data.dev = st.st_dev;

	      /* We know this directory now.  */
	      if (!(flags & FTW_PHYS))
		result = add_object (&data, &st);

	      if (result == 0)
		result = ftw_dir (&data, &st, NULL);
	    }
	  else
	    {
	      int flag = S_ISLNK (st.st_mode) ? FTW_SL : FTW_F;

	      result = (*data.func) (data.dirbuf, &st, data.cvt_arr[flag],
				     &data.ftw);
	    }
	}

      if ((flags & FTW_ACTIONRETVAL)
	  && (result == FTW_SKIP_SUBTREE || result == FTW_SKIP_SIBLINGS))
	result = 0;
    }

  /* Return to the start directory (if necessary).  */
  if (cwdfd != -1)
    {
      int save_err = errno;
      __fchdir (cwdfd);
      __close_nocancel_nostatus (cwdfd);
      __set_errno (save_err);
    }
  else if (cwd != NULL)
    {
      int save_err = errno;
      __chdir (cwd);
      free (cwd);
      __set_errno (save_err);
    }

  /* Free all memory.  */
 out_fail:
  save_err = errno;
  __tdestroy (data.known_objects, free);
  free (data.dirbuf);
  __set_errno (save_err);

  return result;
}
Exemple #17
0
static char *canonicalize (const char *name)
{
	char *rpath, *dest, *extra_buf = NULL;
	const char *start, *end, *rpath_limit;
	long int path_max;
	int num_links = 0, err = 0;

	if (name == NULL) {
		/* As per Single Unix Specification V2 we must return an error if
			 either parameter is a null pointer.	We extend this to allow
			 the RESOLVED parameter be NULL in case the we are expected to
			 allocate the room for the return value.	*/
		__set_errno (EINVAL);
		return NULL;
	}

	if (name[0] == '\0') {
		/* As per Single Unix Specification V2 we must return an error if
			 the name argument points to an empty string.	*/
		__set_errno (ENOENT);
		return NULL;
	}

#ifdef PATH_MAX
	path_max = PATH_MAX;
#else
	path_max = pathconf (name, _PC_PATH_MAX);
	if (path_max <= 0)
		path_max = 1024;
#endif

	rpath = (char *) __alloca (path_max);
	rpath_limit = rpath + path_max;

	if (name[0] != '/') {
		if (!__getcwd (rpath, path_max))
			goto error;
		dest = strchr (rpath, '\0');
	}
	else {
		rpath[0] = '/';
		dest = rpath + 1;
	}

	for (start = end = name; *start; start = end) {
		struct stat st;
		int n;

		/* Skip sequence of multiple path-separators.	*/
		while (*start == '/')
			++start;

		/* Find end of path component.	*/
		for (end = start; *end && *end != '/'; ++end)
			/* Nothing.	*/;

		if (end - start == 0)
			break;
		else if (end - start == 1 && start[0] == '.')
			/* nothing */;
		else if (end - start == 2 && start[0] == '.' && start[1] == '.') {
			/* Back up to previous component, ignore if at root already.	*/
			if (dest > rpath + 1)
				while ((--dest)[-1] != '/');
		}
		else {
			if (dest[-1] != '/')
				*dest++ = '/';

			if (dest + (end - start) >= rpath_limit) {
				__set_errno (ENAMETOOLONG);
				goto error;
			}

			memmove(dest, start, end - start);
			dest = (char *) dest + (end - start);
			*dest = '\0';

			/* let's try changing the semantic to always ignore
			 * underlying filesystem if path so far is in capfstab file.
			 * That way we don't get silly kernel errors when using the
			 * library.  This is easy - just move (well, just copy for
			 * now) the search_fstab check to here. If you get a match,
			 * increment err.  err doesn't actually signal a fatal error,
			 * just causes it to quit getting at underlying
			 * filesystem. -- don
			 *
			 */

			if (search_fstab(rpath)) { /* rpath is in the capfstab */
				err++;
			}
			
			/* we used to crap out in this case; now we simply note that we
			 * hit an error and stop trying to stat from now on. -- Rob
			 */

			if (!err && __lxstat (_STAT_VER, rpath, &st) < 0) {
				err++;
			}
			if (!err && (S_ISLNK (st.st_mode))) {
				char *buf = (char *) __alloca (path_max);
				size_t len;

				if (++num_links > MAXSYMLINKS) {
					__set_errno (ELOOP);
					goto error;
				}

				n = __readlink (rpath, buf, path_max);
				if (n < 0)
					goto error;
				buf[n] = '\0';

				if (!extra_buf)
					extra_buf = (char *) __alloca (path_max);

				len = strlen (end);
				if ((long int) (n + len) >= path_max) {
					__set_errno (ENAMETOOLONG);
					goto error;
				}

				/* Careful here, end may be a pointer into extra_buf... */
				memmove (&extra_buf[n], end, len + 1);
				name = end = memcpy (extra_buf, buf, n);

				if (buf[0] == '/')
					dest = rpath + 1;	/* It's an absolute symlink */
				else
					/* Back up to previous component, ignore if at root already: */
					if (dest > rpath + 1)
						while ((--dest)[-1] != '/');
			}
		}
	}
	if (dest > rpath + 1 && dest[-1] == '/')
		--dest;
	*dest = '\0';

	memcpy(canonicalize_outbuf, rpath, dest - rpath + 1);
	return(canonicalize_outbuf);

error:
	/* copy in component causing trouble */
	strcpy (canonicalize_outbuf, rpath);
	return(canonicalize_outbuf);
}
Exemple #18
0
/*
 * System call dispatcher.
 *
 * A pointer to the trapframe created during exception entry (in
 * exception-*.S) is passed in.
 *
 * The calling conventions for syscalls are as follows: Like ordinary
 * function calls, the first 4 32-bit arguments are passed in the 4
 * argument registers a0-a3. 64-bit arguments are passed in *aligned*
 * pairs of registers, that is, either a0/a1 or a2/a3. This means that
 * if the first argument is 32-bit and the second is 64-bit, a1 is
 * unused.
 *
 * This much is the same as the calling conventions for ordinary
 * function calls. In addition, the system call number is passed in
 * the v0 register.
 *
 * On successful return, the return value is passed back in the v0
 * register, or v0 and v1 if 64-bit. This is also like an ordinary
 * function call, and additionally the a3 register is also set to 0 to
 * indicate success.
 *
 * On an error return, the error code is passed back in the v0
 * register, and the a3 register is set to 1 to indicate failure.
 * (Userlevel code takes care of storing the error code in errno and
 * returning the value -1 from the actual userlevel syscall function.
 * See src/user/lib/libc/arch/mips/syscalls-mips.S and related files.)
 *
 * Upon syscall return the program counter stored in the trapframe
 * must be incremented by one instruction; otherwise the exception
 * return code will restart the "syscall" instruction and the system
 * call will repeat forever.
 *
 * If you run out of registers (which happens quickly with 64-bit
 * values) further arguments must be fetched from the user-level
 * stack, starting at sp+16 to skip over the slots for the
 * registerized values, with copyin().
 */
void
syscall(void *trapframe, unsigned long junk)
{
  curproc->rt = (curproc->rt == BACKGROUND_U ?  BACKGROUND_K : INTERACTIVE_K);
  (void)junk;
  struct trapframe *tf = (struct trapframe*)trapframe;
  
  if(!curproc->context)
    curproc->context = kmalloc(sizeof(struct trapframe));
  
  memcpy(curproc->context, tf, sizeof(struct trapframe));
  
  int callno;
  int32_t retval;
  int err;
  
  KASSERT(curthread != NULL);
  KASSERT(curthread->t_curspl == 0);
  KASSERT(curthread->t_iplhigh_count == 0);
  
  callno = tf->tf_v0;
  
  /*
   * Initialize retval to 0. Many of the system calls don't
   * really return a value, just 0 for success and -1 on
   * error. Since retval is the value returned on success,
   * initialize it to 0 by default; thus it's not necessary to
   * deal with it except for calls that return other values,
   * like write.
   */
  
  retval = 0;
  
  switch (callno) {
  case SYS_reboot:
    err = sys_reboot(tf->tf_a0);
    break;
    
  case SYS___time:
    err = sys___time((userptr_t)tf->tf_a0,
		     (userptr_t)tf->tf_a1);
    break;
    
    /* Add stuff here */
    
  case SYS__exit:
    _exit((int)tf->tf_a0);
    break;
    
  case SYS_chdir:
    err = chdir((const char*)tf->tf_a0);
    break;

  case SYS_close:
    err = close((int)tf->tf_a0,
		   &retval);
    break;

  case SYS_dup2:
    err = dup2((int)tf->tf_a0,
		  (int)tf->tf_a1,
		   &retval);
    break;
    
  case SYS_execv:
    err = execv((const char*)tf->tf_a0,
		(char **)tf->tf_a1);
    break;

  case SYS_fork:
    err = fork(&retval);
    break;

  case SYS___getcwd:
    err = __getcwd((char*)tf->tf_a0,
		   (size_t)tf->tf_a1,
		   &retval);
    break;

  case SYS_getpid:
    err = getpid(&retval);//always return 0
    break;

  case SYS_lseek:
    err = lseek((int)tf->tf_a0,
		(off_t)(tf->tf_a1 | tf->tf_a2),
		(int)tf->tf_a3,
		(off_t*)&retval);
    break;

  case SYS_open:
    err = open((const char*)tf->tf_a0,
	       (int)tf->tf_a1,
	       &retval);
    break;

  case SYS_read:
    err = read((int)tf->tf_a0,
	       (void*)tf->tf_a1,
	       (size_t)tf->tf_a2,
	       &retval);
    break;
    
  case SYS_waitpid:
    err = waitpid((pid_t)tf->tf_a0,
		  (int *)tf->tf_a1,
		  (int)tf->tf_a2,
		  &retval);
    break;

  case SYS_write:
    err = write((int)tf->tf_a0,
		(userptr_t)tf->tf_a1,
		(size_t)tf->tf_a2,
		&retval);
    break;

  default:
    kprintf("Unknown syscall %d\n", callno);
    err = ENOSYS;
    break;
  }


  if (err) {
		/*
		 * Return the error code. This gets converted at
		 * userlevel to a return value of -1 and the error
		 * code in errno.
		 */
		tf->tf_v0 = err;
		tf->tf_a3 = 1;      /* signal an error */
	}
	else {
		/* Success. */
		tf->tf_v0 = retval;
		tf->tf_a3 = 0;      /* signal no error */
	}

	/*
	 * Now, advance the program counter, to avoid restarting
	 * the syscall over and over again.
	 */

	tf->tf_epc += 4;

	/* Make sure the syscall code didn't forget to lower spl */
	KASSERT(curthread->t_curspl == 0);
	/* ...or leak any spinlocks */
	KASSERT(curthread->t_iplhigh_count == 0);
	curproc->rt = (curproc->rt == BACKGROUND_K ?  BACKGROUND_U : INTERACTIVE_U);
}
Exemple #19
0
char *getcwd(char *buf, size_t size)
{
	return (__getcwd(buf, size) < 0) ? NULL : buf;
}
Exemple #20
0
char *
__realpath (const char *name, char *resolved)
{
  char *rpath, *dest, *extra_buf = NULL;
  const char *start, *end, *rpath_limit;
  long int path_max;
#ifdef S_ISLNK
  int num_links = 0;
#endif

  if (name == NULL)
    {
      /* As per Single Unix Specification V2 we must return an error if
	 either parameter is a null pointer.  We extend this to allow
	 the RESOLVED parameter to be NULL in case the we are expected to
	 allocate the room for the return value.  */
      __set_errno (EINVAL);
      return NULL;
    }

  if (name[0] == '\0')
    {
      /* As per Single Unix Specification V2 we must return an error if
	 the name argument points to an empty string.  */
      __set_errno (ENOENT);
      return NULL;
    }

#ifdef PATH_MAX
  path_max = PATH_MAX;
#else
  path_max = pathconf (name, _PC_PATH_MAX);
  if (path_max <= 0)
    path_max = 1024;
#endif

  if (resolved == NULL)
    {
      rpath = malloc (path_max);
      if (rpath == NULL)
	return NULL;
    }
  else
    rpath = resolved;
  rpath_limit = rpath + path_max;

  if (name[0] != '/')
    {
      if (!__getcwd (rpath, path_max))
	{
	  rpath[0] = '\0';
	  goto error;
	}
      dest = strchr (rpath, '\0');
    }
  else
    {
      rpath[0] = '/';
      dest = rpath + 1;
    }

  for (start = end = name; *start; start = end)
    {
#ifdef _LIBC
      struct stat64 st;
#else
      struct stat st;
#endif

      /* Skip sequence of multiple path-separators.  */
      while (*start == '/')
	++start;

      /* Find end of path component.  */
      for (end = start; *end && *end != '/'; ++end)
	/* Nothing.  */;

      if (end - start == 0)
	break;
      else if (end - start == 1 && start[0] == '.')
	/* nothing */;
      else if (end - start == 2 && start[0] == '.' && start[1] == '.')
	{
	  /* Back up to previous component, ignore if at root already.  */
	  if (dest > rpath + 1)
	    while ((--dest)[-1] != '/');
	}
      else
	{
	  size_t new_size;

	  if (dest[-1] != '/')
	    *dest++ = '/';

	  if (dest + (end - start) >= rpath_limit)
	    {
	      ptrdiff_t dest_offset = dest - rpath;
	      char *new_rpath;

	      if (resolved)
		{
		  __set_errno (ENAMETOOLONG);
		  if (dest > rpath + 1)
		    dest--;
		  *dest = '\0';
		  goto error;
		}
	      new_size = rpath_limit - rpath;
	      if (end - start + 1 > path_max)
		new_size += end - start + 1;
	      else
		new_size += path_max;
	      new_rpath = (char *) realloc (rpath, new_size);
	      if (new_rpath == NULL)
		goto error;
	      rpath = new_rpath;
	      rpath_limit = rpath + new_size;

	      dest = rpath + dest_offset;
	    }

#ifdef _LIBC
	  dest = __mempcpy (dest, start, end - start);
#else
	  memcpy (dest, start, end - start);
	  dest += end - start;
#endif
	  *dest = '\0';

#ifdef _LIBC
	  if (__lxstat64 (_STAT_VER, rpath, &st) < 0)
#else
	  if (lstat (rpath, &st) < 0)
#endif
	    goto error;

#ifdef S_ISLNK
	  if (S_ISLNK (st.st_mode))
	    {
	      char *buf;
	      size_t len;
	      int n;

	      if (++num_links > MAXSYMLINKS)
		{
		  __set_errno (ELOOP);
		  goto error;
		}

	      buf = allocsa (path_max);
	      if (!buf)
		{
		  errno = ENOMEM;
		  goto error;
		}

	      n = __readlink (rpath, buf, path_max);
	      if (n < 0)
		{
		  int saved_errno = errno;
		  freesa (buf);
		  errno = saved_errno;
		  goto error;
		}
	      buf[n] = '\0';

	      if (!extra_buf)
		{
		  extra_buf = allocsa (path_max);
		  if (!extra_buf)
		    {
		      freesa (buf);
		      errno = ENOMEM;
		      goto error;
		    }
		}

	      len = strlen (end);
	      if ((long int) (n + len) >= path_max)
		{
		  freesa (buf);
		  __set_errno (ENAMETOOLONG);
		  goto error;
		}

	      /* Careful here, end may be a pointer into extra_buf... */
	      memmove (&extra_buf[n], end, len + 1);
	      name = end = memcpy (extra_buf, buf, n);

	      if (buf[0] == '/')
		dest = rpath + 1;	/* It's an absolute symlink */
	      else
		/* Back up to previous component, ignore if at root already: */
		if (dest > rpath + 1)
		  while ((--dest)[-1] != '/');
	    }
#endif
	}
    }
  if (dest > rpath + 1 && dest[-1] == '/')
    --dest;
  *dest = '\0';

  if (extra_buf)
    freesa (extra_buf);

  return resolved ? memcpy (resolved, rpath, dest - rpath + 1) : rpath;

error:
  {
    int saved_errno = errno;
    if (extra_buf)
      freesa (extra_buf);
    if (resolved)
      strcpy (resolved, rpath);
    else
      free (rpath);
    errno = saved_errno;
  }
  return NULL;
}
char *csExpandName (const char *iName)
{
  char outname [CS_MAXPATHLEN + 1];
  int inp = 0, outp = 0, namelen = strlen (iName);
  while ((outp < CS_MAXPATHLEN)
      && (inp < namelen))
  {
    char tmp [CS_MAXPATHLEN + 1];
    int ptmp = 0;
    while ((inp < namelen) && (!IS_PATH_SEPARATOR(iName[inp]) ))
      tmp [ptmp++] = iName [inp++];
    tmp [ptmp] = 0;

    if ((ptmp > 0)
     && (outp == 0)
#if defined (CS_PLATFORM_DOS) || defined (CS_PLATFORM_WIN32)
     && ((inp >= namelen)
      || (iName [inp] != ':'))
#endif
        )
    {
      if (getcwd (outname, sizeof (outname)) == 0)
      {
        csPrintfErr ("csExpandName(): getcwd() error for %s (errno = %d)!\n",
          outname, errno);
        return 0;
      }
      outp = strlen (outname);
      if (strcmp (tmp, "."))
        outname [outp++] = CS_PATH_SEPARATOR;
    } /* endif */

#if defined (CS_PLATFORM_DOS) || defined (CS_PLATFORM_WIN32)
    // If path starts with '/' (root), get current drive
    if ((ptmp == 0)
     && (outp == 0))
    {
      getcwd (outname, sizeof (outname));
      if (outname [1] == ':')
        outp = 2;
    } /* endif */
#endif

    if (strcmp (tmp, "..") == 0)
    {
      while ((outp > 0)
          && ((outname [outp - 1] == '/')
           || (outname [outp - 1] == CS_PATH_SEPARATOR)
#if defined (CS_PLATFORM_DOS) || defined (CS_PLATFORM_WIN32)
           || (outname [outp - 1] == ':')
#endif
             )
            )
        outp--;
      while ((outp > 0)
          && (outname [outp - 1] != '/')
          && (outname [outp - 1] != CS_PATH_SEPARATOR)
#if defined (CS_PLATFORM_DOS) || defined (CS_PLATFORM_WIN32)
          && (outname [outp - 1] != ':')
#endif
            )
        outp--;
    }
    else if (strcmp (tmp, ".") == 0)
    {
      // do nothing
    }
    else if (strcmp (tmp, "~") == 0)
    {
      // strip all output path; start from scratch
      strcpy (outname, "~/");
      outp = 2;
    }
    else
    {
      memcpy (&outname [outp], tmp, ptmp);
      outp += ptmp;
      if (inp < namelen)
      {
#if defined (CS_PLATFORM_DOS) || defined (CS_PLATFORM_WIN32)
        if ((inp == 1)
         && (iName [inp] == ':'))
          if ((iName [inp + 1] == '/')
           || (iName [inp + 1] == CS_PATH_SEPARATOR))
            outname [outp++] = ':';
          else
            outp += __getcwd (iName [inp - 1], outname + outp - 1,
	      sizeof (outname) - outp + 1) - 1;
        if ((outname [outp - 1] != '/')
         && (outname [outp - 1] != CS_PATH_SEPARATOR))
#endif
        outname [outp++] = CS_PATH_SEPARATOR;
      }
    } /* endif */
    while ((inp < namelen)
        && ((iName [inp] == '/')
         || (iName [inp] == CS_PATH_SEPARATOR)
#if defined (CS_PLATFORM_DOS) || defined (CS_PLATFORM_WIN32)
         || (iName [inp] == ':')
#endif
           )
          )
      inp++;
  } /* endwhile */

  char *ret = new char [outp + 1];
  memcpy (ret, outname, outp);
  ret [outp] = 0;
  return ret;
}
Exemple #22
0
char *
getcwd(char *buf, size_t size)
{
	_gfs_hook_debug_v(fputs("Hooking getcwd\n", stderr));
	return (__getcwd(buf, size));
}
Exemple #23
0
static char *
canonicalize (const char *name, char *resolved)
{
  char *rpath, *dest, *extra_buf = NULL;
  const char *start, *end, *rpath_limit;
  long int path_max;
  int num_links = 0, old_errno;

  if (name == NULL)
    {
      /* As per Single Unix Specification V2 we must return an error if
	 either parameter is a null pointer.  We extend this to allow
	 the RESOLVED parameter to be NULL in case the we are expected to
	 allocate the room for the return value.  */
      __set_errno (EINVAL);
      return NULL;
    }

  if (name[0] == '\0')
    {
      /* As per Single Unix Specification V2 we must return an error if
	 the name argument points to an empty string.  */
      __set_errno (ENOENT);
      return NULL;
    }
#ifdef __WIN32__
	{
	char *lpFilePart;
	int len;
//  fprintf(stderr, "name: %s\n", name);
	rpath = resolved ? __builtin_alloca (MAX_PATH) : malloc (MAX_PATH);
//	unix2winpath (name);
//  fprintf(stderr, "name: %s\n", name);
	len = GetFullPathName(name, MAX_PATH, rpath, &lpFilePart);
	/* GetFullPathName returns bogus paths for *nix-style paths, like
	* /foo/bar - it just prepends current drive to them. Keep them
	* intact (they need to be for relocation to work!).
	*/
	if (name[0] == '/') {
		strncpy (rpath, name, MAX_PATH - 1);
		rpath[MAX_PATH - 1] = '\0';
		len = strlen (rpath);
	}
//  fprintf(stderr, "rpath: %s\n", rpath);
	if (len == 0) {
		//set_werrno;
		return NULL;
	}
	if (len > MAX_PATH)	{
		if (resolved)
			__set_errno(ENAMETOOLONG);
		else {
			rpath = realloc(rpath, len + 2);
			GetFullPathName(name, len, rpath, &lpFilePart);
//  fprintf(stderr, "rpath: %s\n", rpath);
		}
	}
//	if ( ISDIRSEP(name[strlen(name)]) && !ISDIRSEP(rpath[len]) ) {
//		rpath[len] = '\\';
//		rpath[len + 1] = 0;
//	}
	old_errno = errno;
	//if (!access (rpath, D_OK) && !ISDIRSEP(rpath[len - 1]) ){
	if (!access (rpath, R_OK) && !ISDIRSEP(rpath[len - 1]) ){
		rpath[len] = '\\';
		rpath[len + 1] = 0;
	}
	errno = old_errno;
	win2unixpath (rpath);
//  fprintf(stderr, "rpath: %s\n", rpath);
	return resolved ? strcpy(resolved, rpath) : rpath ;
	}
#else /* __WIN32__ */

#ifdef PATH_MAX
  path_max = PATH_MAX;
#else
  path_max = pathconf (name, _PC_PATH_MAX);
  if (path_max <= 0)
    path_max = 1024;
#endif

  rpath = resolved ? __builtin_alloca (path_max) : malloc (path_max);
  rpath_limit = rpath + path_max;

  if (name[0] != '/')
    {
      if (!__getcwd (rpath, path_max))
	{
	  rpath[0] = '\0';
	  goto error;
	}
      dest = strchr (rpath, '\0');
    }
  else
    {
      rpath[0] = '/';
      dest = rpath + 1;
    }

  for (start = end = name; *start; start = end)
    {
#ifdef _LIBC
      struct stat64 st;
#else
      struct stat st;
#endif
      int n;

      /* Skip sequence of multiple path-separators.  */
      while (*start == '/')
	++start;

      /* Find end of path component.  */
      for (end = start; *end && *end != '/'; ++end)
	/* Nothing.  */;

      if (end - start == 0)
	break;
      else if (end - start == 1 && start[0] == '.')
	/* nothing */;
      else if (end - start == 2 && start[0] == '.' && start[1] == '.')
	{
	  /* Back up to previous component, ignore if at root already.  */
	  if (dest > rpath + 1)
	    while ((--dest)[-1] != '/');
	}
      else
	{
	  size_t new_size;

	  if (dest[-1] != '/')
	    *dest++ = '/';

	  if (dest + (end - start) >= rpath_limit)
	    {
	      ptrdiff_t dest_offset = dest - rpath;

	      if (resolved)
		{
		  __set_errno (ENAMETOOLONG);
		  if (dest > rpath + 1)
		    dest--;
		  *dest = '\0';
		  goto error;
		}
	      new_size = rpath_limit - rpath;
	      if (end - start + 1 > path_max)
		new_size += end - start + 1;
	      else
		new_size += path_max;
	      rpath = realloc (rpath, new_size);
	      rpath_limit = rpath + new_size;
	      if (rpath == NULL)
		return NULL;

	      dest = rpath + dest_offset;
	    }

#ifdef _LIBC
	  dest = __mempcpy (dest, start, end - start);
#else
	  memcpy (dest, start, end - start);
	  dest += end - start;
#endif
	  *dest = '\0';

#ifdef _LIBC
	  if (__lxstat64 (_STAT_VER, rpath, &st) < 0)
#else
	  if (lstat (rpath, &st) < 0)
#endif
	    goto error;

#if HAVE_READLINK
	  if (S_ISLNK (st.st_mode))
	    {
	      char *buf = __builtin_alloca (path_max);
	      size_t len;

	      if (++num_links > MAXSYMLINKS)
		{
		  __set_errno (ELOOP);
		  goto error;
		}

	      n = __readlink (rpath, buf, path_max);
	      if (n < 0)
		goto error;
	      buf[n] = '\0';

	      if (!extra_buf)
		extra_buf = __builtin_alloca (path_max);

	      len = strlen (end);
	      if ((long int) (n + len) >= path_max)
		{
		  __set_errno (ENAMETOOLONG);
		  goto error;
		}

	      /* Careful here, end may be a pointer into extra_buf... */
	      memmove (&extra_buf[n], end, len + 1);
	      name = end = memcpy (extra_buf, buf, n);

	      if (buf[0] == '/')
		dest = rpath + 1;	/* It's an absolute symlink */
	      else
		/* Back up to previous component, ignore if at root already: */
		if (dest > rpath + 1)
		  while ((--dest)[-1] != '/');
	    }
#endif
	}
    }
  if (dest > rpath + 1 && dest[-1] == '/')
    --dest;
  *dest = '\0';

  return resolved ? memcpy (resolved, rpath, dest - rpath + 1) : rpath;

error:
  if (resolved)
    strcpy (resolved, rpath);
  else
    free (rpath);
  return NULL;

#endif /* __WIN32__ */
}
Exemple #24
0
char *
getcwd(char *pt, size_t size)
{
	struct dirent *dp;
	DIR *dir = NULL;
	dev_t dev;
	ino_t ino;
	int first;
	char *bpt;
	struct stat s;
	dev_t root_dev;
	ino_t root_ino;
	size_t ptsize;
	int save_errno;
	char *ept, c;
	int fd;

	/*
	 * If no buffer specified by the user, allocate one as necessary.
	 * If a buffer is specified, the size has to be non-zero.  The path
	 * is built from the end of the buffer backwards.
	 */
	if (pt) {
		ptsize = 0;
		if (!size) {
			errno = EINVAL;
			return (NULL);
		}
		if (size == 1) {
			errno = ERANGE;
			return (NULL);
		}
		ept = pt + size;
	} else {
		if ((pt = malloc(ptsize = PATH_MAX)) == NULL)
			return (NULL);
		ept = pt + ptsize;
	}
	if (__getcwd(pt, ept - pt) == 0) {
		if (*pt != '/') {
			bpt = pt;
			ept = pt + strlen(pt) - 1;
			while (bpt < ept) {
				c = *bpt;
				*bpt++ = *ept;
				*ept-- = c;
			}
		}
		return (pt);
	}
	bpt = ept - 1;
	*bpt = '\0';

	/* Save root values, so know when to stop. */
	if (stat("/", &s))
		goto err;
	root_dev = s.st_dev;
	root_ino = s.st_ino;

	errno = 0;			/* XXX readdir has no error return. */

	for (first = 1;; first = 0) {
		/* Stat the current level. */
		if (dir != NULL ? _fstat(_dirfd(dir), &s) : lstat(".", &s))
			goto err;

		/* Save current node values. */
		ino = s.st_ino;
		dev = s.st_dev;

		/* Check for reaching root. */
		if (root_dev == dev && root_ino == ino) {
			*--bpt = '/';
			/*
			 * It's unclear that it's a requirement to copy the
			 * path to the beginning of the buffer, but it's always
			 * been that way and stuff would probably break.
			 */
			bcopy(bpt, pt, ept - bpt);
			if (dir)
				(void) closedir(dir);
			return (pt);
		}

		/* Open and stat parent directory. */
		fd = _openat(dir != NULL ? _dirfd(dir) : AT_FDCWD,
				"..", O_RDONLY | O_CLOEXEC);
		if (fd == -1)
			goto err;
		if (dir)
			(void) closedir(dir);
		if (!(dir = fdopendir(fd)) || _fstat(_dirfd(dir), &s)) {
			_close(fd);
			goto err;
		}

		/*
		 * If it's a mount point, have to stat each element because
		 * the inode number in the directory is for the entry in the
		 * parent directory, not the inode number of the mounted file.
		 */
		save_errno = 0;
		if (s.st_dev == dev) {
			for (;;) {
				if (!(dp = readdir(dir)))
					goto notfound;
				if (dp->d_fileno == ino)
					break;
			}
		} else
			for (;;) {
				if (!(dp = readdir(dir)))
					goto notfound;
				if (ISDOT(dp))
					continue;

				/* Save the first error for later. */
				if (fstatat(_dirfd(dir), dp->d_name, &s,
				    AT_SYMLINK_NOFOLLOW)) {
					if (!save_errno)
						save_errno = errno;
					errno = 0;
					continue;
				}
				if (s.st_dev == dev && s.st_ino == ino)
					break;
			}

		/*
		 * Check for length of the current name, preceding slash,
		 * leading slash.
		 */
		while (bpt - pt < dp->d_namlen + (first ? 1 : 2)) {
			size_t len, off;

			if (!ptsize) {
				errno = ERANGE;
				goto err;
			}
			off = bpt - pt;
			len = ept - bpt;
			if ((pt = reallocf(pt, ptsize *= 2)) == NULL)
				goto err;
			bpt = pt + off;
			ept = pt + ptsize;
			bcopy(bpt, ept - len, len);
			bpt = ept - len;
		}
		if (!first)
			*--bpt = '/';
		bpt -= dp->d_namlen;
		bcopy(dp->d_name, bpt, dp->d_namlen);
	}

notfound:
	/*
	 * If readdir set errno, use it, not any saved error; otherwise,
	 * didn't find the current directory in its parent directory, set
	 * errno to ENOENT.
	 */
	if (!errno)
		errno = save_errno ? save_errno : ENOENT;
	/* FALLTHROUGH */
err:
	save_errno = errno;

	if (ptsize)
		free(pt);
	if (dir)
		(void) closedir(dir);

	errno = save_errno;
	return (NULL);
}
Exemple #25
0
/* Determine the directories we are looking for data in.  */
void
internal_function
__gconv_get_path (void)
{
  struct path_elem *result;
  __libc_lock_define_initialized (static, lock);

  __libc_lock_lock (lock);

  /* Make sure there wasn't a second thread doing it already.  */
  result = (struct path_elem *) __gconv_path_elem;
  if (result == NULL)
    {
      /* Determine the complete path first.  */
      char *gconv_path;
      size_t gconv_path_len;
      char *elem;
      char *oldp;
      char *cp;
      int nelems;
      char *cwd;
      size_t cwdlen;

      if (__gconv_path_envvar == NULL)
	{
	  /* No user-defined path.  Make a modifiable copy of the
	     default path.  */
	  gconv_path = strdupa (default_gconv_path);
	  gconv_path_len = sizeof (default_gconv_path);
	  cwd = NULL;
	  cwdlen = 0;
	}
      else
	{
	  /* Append the default path to the user-defined path.  */
	  size_t user_len = strlen (__gconv_path_envvar);

	  gconv_path_len = user_len + 1 + sizeof (default_gconv_path);
	  gconv_path = alloca (gconv_path_len);
	  __mempcpy (__mempcpy (__mempcpy (gconv_path, __gconv_path_envvar,
					   user_len),
				":", 1),
		     default_gconv_path, sizeof (default_gconv_path));
	  cwd = __getcwd (NULL, 0);
	  cwdlen = strlen (cwd);
	}
      assert (default_gconv_path[0] == '/');

      /* In a first pass we calculate the number of elements.  */
      oldp = NULL;
      cp = strchr (gconv_path, ':');
      nelems = 1;
      while (cp != NULL)
	{
	  if (cp != oldp + 1)
	    ++nelems;
	  oldp = cp;
	  cp =  strchr (cp + 1, ':');
	}

      /* Allocate the memory for the result.  */
      result = (struct path_elem *) malloc ((nelems + 1)
					    * sizeof (struct path_elem)
					    + gconv_path_len + nelems
					    + (nelems - 1) * (cwdlen + 1));
      if (result != NULL)
	{
	  char *strspace = (char *) &result[nelems + 1];
	  int n = 0;

	  /* Separate the individual parts.  */
	  __gconv_max_path_elem_len = 0;
	  elem = __strtok_r (gconv_path, ":", &gconv_path);
	  assert (elem != NULL);
	  do
	    {
	      result[n].name = strspace;
	      if (elem[0] != '/')
		{
		  assert (cwd != NULL);
		  strspace = __mempcpy (strspace, cwd, cwdlen);
		  *strspace++ = '/';
		}
	      strspace = __stpcpy (strspace, elem);
	      if (strspace[-1] != '/')
		*strspace++ = '/';

	      result[n].len = strspace - result[n].name;
	      if (result[n].len > __gconv_max_path_elem_len)
		__gconv_max_path_elem_len = result[n].len;

	      *strspace++ = '\0';
	      ++n;
	    }
	  while ((elem = __strtok_r (NULL, ":", &gconv_path)) != NULL);

	  result[n].name = NULL;
	  result[n].len = 0;
	}

      __gconv_path_elem = result ?: (struct path_elem *) &empty_path_elem;

      if (cwd != NULL)
	free (cwd);
    }