示例#1
0
int directory_on_path (const char *dir)
{
	char *cwd = NULL;
	char *path = getenv ("PATH");
	char *pathtok;
	const char *element;
	int ret = 0;

	if (!path)
		/* Eh? Oh well. */
		return 0;

	pathtok = path = xstrdup (path);

	for (element = strsep (&pathtok, ":"); element;
	     element = strsep (&pathtok, ":")) {
		if (!*element) {
			if (!cwd)
				cwd = xgetcwd ();
			element = cwd;
		}

		if (STREQ (element, dir)) {
			ret = 1;
			break;
		}
	}

	free (path);
	if (cwd)
		free (cwd);
	return ret;
}
示例#2
0
/* Start the recorder */
static void
recorder_start(void)
{
    /* Alas, while we'd like to use mkstemp it is not portable,
       and doing the autoconfiscation (and providing fallbacks) is more
       than we want to cope with.  So we have to be content with using a
       default name.  Throw in the pid so at least parallel builds might
       work (Debian bug 575731).  */
    string cwd;
    char pid_str[MAX_INT_LENGTH];

    /* Windows (MSVC) seems to have no pid_t, so instead of storing the
       value returned by getpid() we immediately consume it.  */
    sprintf (pid_str, "%ld", (long) getpid());
    recorder_name = concat3(kpse_program_name, pid_str, ".fls");

    /* If an output directory was specified, use it instead of cwd.  */
    if (output_directory) {
        string temp = concat3(output_directory, DIR_SEP_STRING, recorder_name);
        free(recorder_name);
        recorder_name = temp;
    }

    recorder_file = xfopen(recorder_name, FOPEN_W_MODE);

    cwd = xgetcwd();
    fprintf(recorder_file, "PWD %s\n", cwd);
    free(cwd);
}
示例#3
0
static int guess_repository_type(const char *git_dir)
{
	const char *slash;
	char *cwd;
	int cwd_is_git_dir;

	/*
	 * "GIT_DIR=. git init" is always bare.
	 * "GIT_DIR=`pwd` git init" too.
	 */
	if (!strcmp(".", git_dir))
		return 1;
	cwd = xgetcwd();
	cwd_is_git_dir = !strcmp(git_dir, cwd);
	free(cwd);
	if (cwd_is_git_dir)
		return 1;
	/*
	 * "GIT_DIR=.git or GIT_DIR=something/.git is usually not.
	 */
	if (!strcmp(git_dir, ".git"))
		return 0;
	slash = strrchr(git_dir, '/');
	if (slash && !strcmp(slash, "/.git"))
		return 0;

	/*
	 * Otherwise it is often bare.  At this point
	 * we are just guessing.
	 */
	return 1;
}
示例#4
0
static int resolve_relative_url(int argc, const char **argv, const char *prefix)
{
	char *remoteurl = NULL;
	char *remote = get_default_remote();
	const char *up_path = NULL;
	char *res;
	const char *url;
	struct strbuf sb = STRBUF_INIT;

	if (argc != 2 && argc != 3)
		die("resolve-relative-url only accepts one or two arguments");

	url = argv[1];
	strbuf_addf(&sb, "remote.%s.url", remote);
	free(remote);

	if (git_config_get_string(sb.buf, &remoteurl))
		/* the repository is its own authoritative upstream */
		remoteurl = xgetcwd();

	if (argc == 3)
		up_path = argv[2];

	res = relative_url(remoteurl, url, up_path);
	puts(res);
	free(res);
	free(remoteurl);
	return 0;
}
示例#5
0
char *
normalize_filename (const char *name)
{
  char *copy = NULL;

  if (IS_RELATIVE_FILE_NAME (name))
    {
      /* Set COPY to the absolute file name if possible.

         FIXME: There should be no need to get the absolute file name.
         getcwd is slow, it might fail, and it does not necessarily
         return a canonical name even when it succeeds.  Perhaps we
         can use dev+ino pairs instead of names?  */
      copy = xgetcwd ();
      if (copy)
        {
          size_t copylen = strlen (copy);
          bool need_separator = ! (DOUBLE_SLASH_IS_DISTINCT_ROOT
                                   && copylen == 2 && ISSLASH (copy[1]));
          copy = xrealloc (copy, copylen + need_separator + strlen (name) + 1);
          copy[copylen] = DIRECTORY_SEPARATOR;
          strcpy (copy + copylen + need_separator, name);
        }
      else
        WARN ((0, errno, _("Cannot get working directory")));
    }

  if (! copy)
    copy = xstrdup (name);
  normalize_filename_x (copy);
  return copy;
}
示例#6
0
void enter_archive(const char *name, struct_panel *panel, int update_config)
{
  char *saved_work_dir=xgetcwd(NULL);
  #ifdef debug_printf
  printf("Entering into '%s'\n", name);
  #endif
  (void)chdir(panel->path); /* Переходим в каталог где лежит архив */
  if (get_archive_list(name, panel->archive_list))
  {
    char *text;
    if(update_config)
    {
      panel->archive_depth++;
      strcpy(panel->archive_stack[panel->archive_depth], name);
      if ( panel == &top_panel )
        write_archive_stack("top_panel.archive_stack", &top_panel);
      else
        write_archive_stack("bottom_panel.archive_stack", &bottom_panel);
      (void)chdir(saved_work_dir); /* Переходим в каталог откуда нас дёрнули */
    }
    update(panel); /* Строим список */
    move_selection("1", panel); /* Переходим на первый же файл в списке, чтобы не прокручивать */
    text=xconcat_path_file(panel->archive_stack[panel->archive_depth],panel->archive_cwd);
    gtk_label_set_text (GTK_LABEL(panel->path_label), text); /* Пишем имя архива с путём в поле снизу */
    free(text);
  }
  free(saved_work_dir);
}
void		pwd(t_server *serv, char *cmd)
{
  char		*path;
  char		*shortpath;
  int		i;
  int		j;

  (void)cmd;
  i = 0;
  j = 0;
  path = NULL;
  path = xgetcwd(".", path);
  shortpath = xmalloc(PATH_MAX);
  memset(shortpath, 0, PATH_MAX);
  while (path[i])
    {
      if (path[i] != serv->root[i])
	shortpath[j++] = path[i];
      i++;
    }
  if (shortpath[0] == 0)
    shortpath[0] = '/';
  memset(path, 0, PATH_MAX);
  sprintf(path, "257 %s\r\n", shortpath);
  swrite(serv->cfd, path);
  free(path);
  free(shortpath);
}
示例#8
0
文件: save-cwd.c 项目: dscho/msys
int
save_cwd (struct saved_cwd *cwd)
{
  static int have_working_fchdir = 1;

  cwd->desc = -1;
  cwd->name = NULL;

  if (have_working_fchdir)
    {
#if HAVE_FCHDIR
      cwd->desc = open (".", O_RDONLY | O_DIRECTORY);
      if (cwd->desc < 0)
	{
	  error (0, errno, "cannot open current directory");
	  return 1;
	}

# if __sun__ || sun
      /* On SunOS 4, fchdir returns EINVAL if accounting is enabled,
	 so we have to fall back to chdir.  */
      if (fchdir (cwd->desc))
	{
	  if (errno == EINVAL)
	    {
	      close (cwd->desc);
	      cwd->desc = -1;
	      have_working_fchdir = 0;
	    }
	  else
	    {
	      error (0, errno, "current directory");
	      close (cwd->desc);
	      cwd->desc = -1;
	      return 1;
	    }
	}
# endif /* __sun__ || sun */
#else
# define fchdir(x) (abort (), 0)
      have_working_fchdir = 0;
#endif
    }

  if (!have_working_fchdir)
    {
      cwd->name = xgetcwd ();
      if (cwd->name == NULL)
	{
	  error (0, errno, "cannot get current directory");
	  return 1;
	}
    }
  return 0;
}
示例#9
0
static int pathsearch (const char *name, const mode_t bits)
{
	char *cwd = NULL;
	char *path = getenv ("PATH");
	char *pathtok;
	const char *element;
	struct stat st;
	int ret = 0;

	if (!path)
		/* Eh? Oh well. */
		return 0;

	if (strchr (name, '/')) {
		/* Qualified name; look directly. */
		if (stat (name, &st) == -1)
			return 0;
		if (S_ISREG (st.st_mode) && (st.st_mode & bits))
			return 1;
		return 0;
	}

	pathtok = path = xstrdup (path);

	/* Unqualified name; iterate over $PATH looking for it. */
	for (element = strsep (&pathtok, ":"); element;
	     element = strsep (&pathtok, ":")) {
		char *filename;

		if (!*element) {
			if (!cwd)
				cwd = xgetcwd ();
			element = cwd;
		}

		filename = xasprintf ("%s/%s", element, name);
		if (stat (filename, &st) == -1) {
			free (filename);
			continue;
		}

		free (filename);

		if (S_ISREG (st.st_mode) && (st.st_mode & bits)) {
			ret = 1;
			break;
		}
	}

	free (path);
	if (cwd)
		free (cwd);
	return ret;
}
示例#10
0
文件: git.c 项目: Ferryworld/git
static void save_env_before_alias(void)
{
	int i;

	assert(save_restore_env_balance == 0);
	save_restore_env_balance = 1;
	orig_cwd = xgetcwd();
	for (i = 0; i < ARRAY_SIZE(env_names); i++) {
		orig_env[i] = getenv(env_names[i]);
		orig_env[i] = xstrdup_or_null(orig_env[i]);
	}
}
示例#11
0
文件: misc.c 项目: Happuri/various
/* Return the absolute path that represents the working
   directory referenced by IDX.

   If wd is empty, then there were no -C options given, and
   chdir_args() has never been called, so we simply return the
   process's actual cwd.  (Note that in this case IDX is ignored,
   since it should always be 0.) */
static const char *
tar_getcdpath (int idx)
{
  if (!wd)
    {
      static char *cwd;
      if (!cwd)
	cwd = xgetcwd ();
      return cwd;
    }
  return wd[idx].abspath;
}
示例#12
0
文件: dir.c 项目: AnithaPandiyan/git
int is_inside_dir(const char *dir)
{
	char *cwd;
	int rc;

	if (!dir)
		return 0;

	cwd = xgetcwd();
	rc = (dir_inside_of(cwd, dir) >= 0);
	free(cwd);
	return rc;
}
示例#13
0
文件: git.c 项目: Grdflo/git-core
static void save_env(void)
{
	int i;
	if (saved_environment)
		return;
	saved_environment = 1;
	orig_cwd = xgetcwd();
	for (i = 0; i < ARRAY_SIZE(env_names); i++) {
		orig_env[i] = getenv(env_names[i]);
		if (orig_env[i])
			orig_env[i] = xstrdup(orig_env[i]);
	}
}
示例#14
0
int
save_cwd (struct saved_cwd *cwd)
{
  static int have_working_fchdir = 1;

  cwd->desc = -1;
  cwd->name = NULL;

  if (have_working_fchdir)
    {
#if HAVE_FCHDIR
      cwd->desc = open (".", O_RDONLY | O_DIRECTORY);
      if (cwd->desc < 0)
	return 1;

# if __sun__ || sun
      /* On SunOS 4 and IRIX 5.3, fchdir returns EINVAL when auditing
	 is enabled, so we have to fall back to chdir.  */
      if (fchdir (cwd->desc))
	{
	  if (errno == EINVAL)
	    {
	      close (cwd->desc);
	      cwd->desc = -1;
	      have_working_fchdir = 0;
	    }
	  else
	    {
	      int saved_errno = errno;
	      close (cwd->desc);
	      cwd->desc = -1;
	      errno = saved_errno;
	      return 1;
	    }
	}
# endif /* __sun__ || sun */
#else
# define fchdir(x) (abort (), 0)
      have_working_fchdir = 0;
#endif
    }

  if (!have_working_fchdir)
    {
      cwd->name = xgetcwd ();
      if (cwd->name == NULL)
	return 1;
    }
  return 0;
}
示例#15
0
文件: misc.c 项目: Happuri/various
/* DIR is the operand of a -C option; add it to vector of chdir targets,
   and return the index of its location.  */
int
chdir_arg (char const *dir)
{
  char *absdir;

  if (wd_count == wd_alloc)
    {
      if (wd_alloc == 0)
	wd_alloc = 2;
      wd = x2nrealloc (wd, &wd_alloc, sizeof *wd);

      if (! wd_count)
	{
	  wd[wd_count].name = ".";
	  wd[wd_count].abspath = xgetcwd ();
	  wd[wd_count].fd = AT_FDCWD;
	  wd_count++;
	}
    }

  /* Optimize the common special case of the working directory,
     or the working directory as a prefix.  */
  if (dir[0])
    {
      while (dir[0] == '.' && ISSLASH (dir[1]))
	for (dir += 2;  ISSLASH (*dir);  dir++)
	  continue;
      if (! dir[dir[0] == '.'])
	return wd_count - 1;
    }


  /* If the given name is absolute, use it to represent this directory;
     otherwise, construct a name based on the previous -C option.  */
  if (IS_ABSOLUTE_FILE_NAME (dir))
    absdir = xstrdup (dir);
  else if (wd[wd_count - 1].abspath)
    {
      namebuf_t nbuf = namebuf_create (wd[wd_count - 1].abspath);
      namebuf_add_dir (nbuf, dir);
      absdir = namebuf_finish (nbuf);
    }
  else
    absdir = 0;

  wd[wd_count].name = dir;
  wd[wd_count].abspath = absdir;
  wd[wd_count].fd = 0;
  return wd_count++;
}
示例#16
0
int
save_cwd (struct saved_cwd *cwd)
{
    cwd->name = NULL;

    cwd->desc = open (".", O_RDONLY);
    if (cwd->desc < 0)
    {
        cwd->name = xgetcwd ();
        return cwd->name ? 0 : -1;
    }

    return 0;
}
示例#17
0
int enter_archive(const char *name, struct_panel *panel, int update_config)
{
  char *saved_work_dir=xgetcwd(NULL);
  TRACE("Entering into '%s'\n", name);
  if (chdir(panel->path) == -1) /* Переходим в каталог где лежит архив */
  {
    char *message;
    asprintf(&message, UNABLE_TO_CHANGE_DIRECTORY_TO, panel->path, strerror(errno));
    Message(ERROR, message);
    free (message);
    return FALSE;
  }

  if (access(name, R_OK) == -1 )
  {
    char *message;
    asprintf(&message, UNABLE_TO_ACCESS_FILE, name, strerror(errno));
    Message(ERROR, message);
    free (message);
    return FALSE;
  }

  int res = FALSE;
  if (archive_supported(name))
  {
    char *text;
    if(update_config)
    {
      panel->archive_depth++;
      strcpy(panel->archive_stack[panel->archive_depth], name);
      if ( panel == &top_panel )
        write_archive_stack("top_panel.archive_stack", &top_panel);
      else
        write_archive_stack("bottom_panel.archive_stack", &bottom_panel);
      (void)chdir(saved_work_dir); /* Переходим в каталог откуда нас дёрнули */
    }
    panel->archive_list=archive_list_get(name);
    update(panel); /* Строим список */
    move_selection("0", panel); /* Переходим на первый же файл в списке */
    text=xconcat_path_file(panel->archive_stack[panel->archive_depth],panel->archive_cwd);
    gtk_label_set_text (GTK_LABEL(panel->path_label), text); /* Пишем имя архива с путём в поле снизу */
    free(text);
    res = TRUE;
  } else {
    TRACE("Archive is unsupported: %s", name);
  }
  free(saved_work_dir);
  return res;
}
示例#18
0
int
save_cwd (struct saved_cwd *cwd)
{
  cwd->name = NULL;

  cwd->desc = open (".", O_SEARCH);
  if (!GNULIB_FCNTL_SAFER)
    cwd->desc = fd_safer (cwd->desc);
  if (cwd->desc < 0)
    {
      cwd->name = xgetcwd ();
      return cwd->name ? 0 : -1;
    }

  set_cloexec_flag (cwd->desc, true);
  return 0;
}
char *bb_simplify_path(const char *path)
{
	char *s, *start, *p;

	if (path[0] == '/')
		start = bb_xstrdup(path);
	else {
		s = xgetcwd(NULL);
		start = concat_path_file(s, path);
		free(s);
	}
	p = s = start;

	do {
		if (*p == '/') {
			if (*s == '/') {	/* skip duplicate (or initial) slash */
				continue;
			} else if (*s == '.') {
				if (s[1] == '/' || s[1] == 0) {	/* remove extra '.' */
					continue;
				} else if ((s[1] == '.') && (s[2] == '/' || s[2] == 0)) {
					++s;
					if (p > start) {
						while (*--p != '/');	/* omit previous dir */
					}
					continue;
				}
			}
		}
		*++p = *s;
	} while (*++s);

	if ((p == start) || (*p != '/')) {	/* not a trailing slash */
		++p;					/* so keep last character */
	}
	*p = 0;

	return start;
}
示例#20
0
static char *
curdir (void)
{
  static char *path = 0;
  extern char *xgetcwd (void);
  free (path);
  path = xgetcwd ();
  if (!path)
    return (char *) "";
  if (path[1] != '\0')		/* special case for root dir. */
    {
      char *tmp = realloc (path, strlen (path) + 2);	/* '/' + '\0' */
      if (!tmp)
	{
	  free (path);
	  return (char *) "";
	}
      strcat (tmp, "/");
      path = tmp;
    }
  /* For guest account, skip / since it's chrooted */
  return (cred.guest ? path + 1 : path);
}
示例#21
0
文件: git.c 项目: benpeart/git
static int handle_options(const char ***argv, int *argc, int *envchanged)
{
	const char **orig_argv = *argv;

	while (*argc > 0) {
		const char *cmd = (*argv)[0];
		if (cmd[0] != '-')
			break;

		/*
		 * For legacy reasons, the "version" and "help"
		 * commands can be written with "--" prepended
		 * to make them look like flags.
		 */
		if (!strcmp(cmd, "--help") || !strcmp(cmd, "--version"))
			break;

		/*
		 * Check remaining flags.
		 */
		if (skip_prefix(cmd, "--exec-path", &cmd)) {
			if (*cmd == '=')
				git_set_exec_path(cmd + 1);
			else {
				puts(git_exec_path());
				exit(0);
			}
		} else if (!strcmp(cmd, "--html-path")) {
			puts(system_path(GIT_HTML_PATH));
			exit(0);
		} else if (!strcmp(cmd, "--man-path")) {
			puts(system_path(GIT_MAN_PATH));
			exit(0);
		} else if (!strcmp(cmd, "--info-path")) {
			puts(system_path(GIT_INFO_PATH));
			exit(0);
		} else if (!strcmp(cmd, "-p") || !strcmp(cmd, "--paginate")) {
			use_pager = 1;
		} else if (!strcmp(cmd, "-P") || !strcmp(cmd, "--no-pager")) {
			use_pager = 0;
			if (envchanged)
				*envchanged = 1;
		} else if (!strcmp(cmd, "--no-replace-objects")) {
			check_replace_refs = 0;
			setenv(NO_REPLACE_OBJECTS_ENVIRONMENT, "1", 1);
			if (envchanged)
				*envchanged = 1;
		} else if (!strcmp(cmd, "--git-dir")) {
			if (*argc < 2) {
				fprintf(stderr, _("no directory given for --git-dir\n" ));
				usage(git_usage_string);
			}
			setenv(GIT_DIR_ENVIRONMENT, (*argv)[1], 1);
			if (envchanged)
				*envchanged = 1;
			(*argv)++;
			(*argc)--;
		} else if (skip_prefix(cmd, "--git-dir=", &cmd)) {
			setenv(GIT_DIR_ENVIRONMENT, cmd, 1);
			if (envchanged)
				*envchanged = 1;
		} else if (!strcmp(cmd, "--namespace")) {
			if (*argc < 2) {
				fprintf(stderr, _("no namespace given for --namespace\n" ));
				usage(git_usage_string);
			}
			setenv(GIT_NAMESPACE_ENVIRONMENT, (*argv)[1], 1);
			if (envchanged)
				*envchanged = 1;
			(*argv)++;
			(*argc)--;
		} else if (skip_prefix(cmd, "--namespace=", &cmd)) {
			setenv(GIT_NAMESPACE_ENVIRONMENT, cmd, 1);
			if (envchanged)
				*envchanged = 1;
		} else if (!strcmp(cmd, "--work-tree")) {
			if (*argc < 2) {
				fprintf(stderr, _("no directory given for --work-tree\n" ));
				usage(git_usage_string);
			}
			setenv(GIT_WORK_TREE_ENVIRONMENT, (*argv)[1], 1);
			if (envchanged)
				*envchanged = 1;
			(*argv)++;
			(*argc)--;
		} else if (skip_prefix(cmd, "--work-tree=", &cmd)) {
			setenv(GIT_WORK_TREE_ENVIRONMENT, cmd, 1);
			if (envchanged)
				*envchanged = 1;
		} else if (!strcmp(cmd, "--super-prefix")) {
			if (*argc < 2) {
				fprintf(stderr, _("no prefix given for --super-prefix\n" ));
				usage(git_usage_string);
			}
			setenv(GIT_SUPER_PREFIX_ENVIRONMENT, (*argv)[1], 1);
			if (envchanged)
				*envchanged = 1;
			(*argv)++;
			(*argc)--;
		} else if (skip_prefix(cmd, "--super-prefix=", &cmd)) {
			setenv(GIT_SUPER_PREFIX_ENVIRONMENT, cmd, 1);
			if (envchanged)
				*envchanged = 1;
		} else if (!strcmp(cmd, "--bare")) {
			char *cwd = xgetcwd();
			is_bare_repository_cfg = 1;
			setenv(GIT_DIR_ENVIRONMENT, cwd, 0);
			free(cwd);
			setenv(GIT_IMPLICIT_WORK_TREE_ENVIRONMENT, "0", 1);
			if (envchanged)
				*envchanged = 1;
		} else if (!strcmp(cmd, "-c")) {
			if (*argc < 2) {
				fprintf(stderr, _("-c expects a configuration string\n" ));
				usage(git_usage_string);
			}
			git_config_push_parameter((*argv)[1]);
			(*argv)++;
			(*argc)--;
		} else if (!strcmp(cmd, "--literal-pathspecs")) {
			setenv(GIT_LITERAL_PATHSPECS_ENVIRONMENT, "1", 1);
			if (envchanged)
				*envchanged = 1;
		} else if (!strcmp(cmd, "--no-literal-pathspecs")) {
			setenv(GIT_LITERAL_PATHSPECS_ENVIRONMENT, "0", 1);
			if (envchanged)
				*envchanged = 1;
		} else if (!strcmp(cmd, "--glob-pathspecs")) {
			setenv(GIT_GLOB_PATHSPECS_ENVIRONMENT, "1", 1);
			if (envchanged)
				*envchanged = 1;
		} else if (!strcmp(cmd, "--noglob-pathspecs")) {
			setenv(GIT_NOGLOB_PATHSPECS_ENVIRONMENT, "1", 1);
			if (envchanged)
				*envchanged = 1;
		} else if (!strcmp(cmd, "--icase-pathspecs")) {
			setenv(GIT_ICASE_PATHSPECS_ENVIRONMENT, "1", 1);
			if (envchanged)
				*envchanged = 1;
		} else if (!strcmp(cmd, "--no-optional-locks")) {
			setenv(GIT_OPTIONAL_LOCKS_ENVIRONMENT, "0", 1);
			if (envchanged)
				*envchanged = 1;
		} else if (!strcmp(cmd, "--shallow-file")) {
			(*argv)++;
			(*argc)--;
			set_alternate_shallow_file((*argv)[0], 1);
			if (envchanged)
				*envchanged = 1;
		} else if (!strcmp(cmd, "-C")) {
			if (*argc < 2) {
				fprintf(stderr, _("no directory given for -C\n" ));
				usage(git_usage_string);
			}
			if ((*argv)[1][0]) {
				if (chdir((*argv)[1]))
					die_errno("cannot change to '%s'", (*argv)[1]);
				if (envchanged)
					*envchanged = 1;
			}
			(*argv)++;
			(*argc)--;
		} else if (skip_prefix(cmd, "--list-cmds=", &cmd)) {
			if (!strcmp(cmd, "parseopt")) {
				struct string_list list = STRING_LIST_INIT_DUP;
				int i;

				list_builtins(&list, NO_PARSEOPT);
				for (i = 0; i < list.nr; i++)
					printf("%s ", list.items[i].string);
				string_list_clear(&list, 0);
				exit(0);
			} else {
				exit(list_cmds(cmd));
			}
		} else {
			fprintf(stderr, _("unknown option: %s\n"), cmd);
			usage(git_usage_string);
		}

		(*argv)++;
		(*argc)--;
	}
	return (*argv) - orig_argv;
}
示例#22
0
文件: canonicalize.c 项目: 8l/csolve
char *
canonicalize_filename_mode (const char *name, canonicalize_mode_t can_mode)
{
  char *rname, *dest, *extra_buf = NULL;
  char const *start;
  char const *end;
  char const *rname_limit;
  size_t extra_len = 0;
  Hash_table *ht = NULL;
  int saved_errno;

  if (name == NULL)
    {
      errno = EINVAL;
      return NULL;
    }

  if (name[0] == '\0')
    {
      errno = ENOENT;
      return NULL;
    }

  if (name[0] != '/')
    {
      rname = xgetcwd ();
      if (!rname)
        return NULL;
      dest = strchr (rname, '\0');
      if (dest - rname < PATH_MAX)
        {
          char *p = xrealloc (rname, PATH_MAX);
          dest = p + (dest - rname);
          rname = p;
          rname_limit = rname + PATH_MAX;
        }
      else
        {
          rname_limit = dest;
        }
    }
  else
    {
      rname = xmalloc (PATH_MAX);
      rname_limit = rname + PATH_MAX;
      rname[0] = '/';
      dest = rname + 1;
      if (DOUBLE_SLASH_IS_DISTINCT_ROOT && name[1] == '/')
        *dest++ = '/';
    }

  for (start = name; *start; start = end)
    {
      /* Skip sequence of multiple file name separators.  */
      while (*start == '/')
        ++start;

      /* Find end of 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 > rname + 1)
            while ((--dest)[-1] != '/');
          if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1
              && *dest == '/')
            dest++;
        }
      else
        {
          struct stat st;

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

          if (dest + (end - start) >= rname_limit)
            {
              ptrdiff_t dest_offset = dest - rname;
              size_t new_size = rname_limit - rname;

              if (end - start + 1 > PATH_MAX)
                new_size += end - start + 1;
              else
                new_size += PATH_MAX;
              rname = xrealloc (rname, new_size);
              rname_limit = rname + new_size;

              dest = rname + dest_offset;
            }

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

          if (lstat (rname, &st) != 0)
            {
              saved_errno = errno;
              if (can_mode == CAN_EXISTING)
                goto error;
              if (can_mode == CAN_ALL_BUT_LAST)
                {
                  if (end[strspn (end, "/")] || saved_errno != ENOENT)
                    goto error;
                  continue;
                }
              st.st_mode = 0;
            }

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

              /* Detect loops.  We cannot use the cycle-check module here,
                 since it's actually possible to encounter the same symlink
                 more than once in a given traversal.  However, encountering
                 the same symlink,NAME pair twice does indicate a loop.  */
              if (seen_triple (&ht, name, &st))
                {
                  if (can_mode == CAN_MISSING)
                    continue;
                  saved_errno = ELOOP;
                  goto error;
                }

              buf = areadlink_with_size (rname, st.st_size);
              if (!buf)
                {
                  if (can_mode == CAN_MISSING && errno != ENOMEM)
                    continue;
                  saved_errno = errno;
                  goto error;
                }

              n = strlen (buf);
              len = strlen (end);

              if (!extra_len)
                {
                  extra_len =
                    ((n + len + 1) > PATH_MAX) ? (n + len + 1) : PATH_MAX;
                  extra_buf = xmalloc (extra_len);
                }
              else if ((n + len + 1) > extra_len)
                {
                  extra_len = n + len + 1;
                  extra_buf = xrealloc (extra_buf, extra_len);
                }

              /* 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 = rname + 1;     /* It's an absolute symlink */
                  if (DOUBLE_SLASH_IS_DISTINCT_ROOT && buf[1] == '/')
                    *dest++ = '/';
                }
              else
                {
                  /* Back up to previous component, ignore if at root
                     already: */
                  if (dest > rname + 1)
                    while ((--dest)[-1] != '/');
                  if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1
                      && *dest == '/')
                    dest++;
                }

              free (buf);
            }
          else
            {
              if (!S_ISDIR (st.st_mode) && *end && (can_mode != CAN_MISSING))
                {
                  saved_errno = ENOTDIR;
                  goto error;
                }
            }
        }
    }
  if (dest > rname + 1 && dest[-1] == '/')
    --dest;
  if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1 && *dest == '/')
    dest++;
  *dest = '\0';
  if (rname_limit != dest + 1)
    rname = xrealloc (rname, dest - rname + 1);

  free (extra_buf);
  if (ht)
    hash_free (ht);
  return rname;

error:
  free (extra_buf);
  free (rname);
  if (ht)
    hash_free (ht);
  errno = saved_errno;
  return NULL;
}
示例#23
0
文件: setup.c 项目: jiangxilong/git
static const char *setup_explicit_git_dir(const char *gitdirenv,
					  struct strbuf *cwd,
					  int *nongit_ok)
{
	const char *work_tree_env = getenv(GIT_WORK_TREE_ENVIRONMENT);
	const char *worktree;
	char *gitfile;
	int offset;

	if (PATH_MAX - 40 < strlen(gitdirenv))
		die("'$%s' too big", GIT_DIR_ENVIRONMENT);

	gitfile = (char*)read_gitfile(gitdirenv);
	if (gitfile) {
		gitfile = xstrdup(gitfile);
		gitdirenv = gitfile;
	}

	if (!is_git_directory(gitdirenv)) {
		if (nongit_ok) {
			*nongit_ok = 1;
			free(gitfile);
			return NULL;
		}
		die("Not a git repository: '%s'", gitdirenv);
	}

	if (check_repository_format_gently(gitdirenv, nongit_ok)) {
		free(gitfile);
		return NULL;
	}

	/* #3, #7, #11, #15, #19, #23, #27, #31 (see t1510) */
	if (work_tree_env)
		set_git_work_tree(work_tree_env);
	else if (is_bare_repository_cfg > 0) {
		if (git_work_tree_cfg) {
			/* #22.2, #30 */
			warning("core.bare and core.worktree do not make sense");
			work_tree_config_is_bogus = 1;
		}

		/* #18, #26 */
		set_git_dir(gitdirenv);
		free(gitfile);
		return NULL;
	}
	else if (git_work_tree_cfg) { /* #6, #14 */
		if (is_absolute_path(git_work_tree_cfg))
			set_git_work_tree(git_work_tree_cfg);
		else {
			char *core_worktree;
			if (chdir(gitdirenv))
				die_errno("Could not chdir to '%s'", gitdirenv);
			if (chdir(git_work_tree_cfg))
				die_errno("Could not chdir to '%s'", git_work_tree_cfg);
			core_worktree = xgetcwd();
			if (chdir(cwd->buf))
				die_errno("Could not come back to cwd");
			set_git_work_tree(core_worktree);
			free(core_worktree);
		}
	}
	else if (!git_env_bool(GIT_IMPLICIT_WORK_TREE_ENVIRONMENT, 1)) {
		/* #16d */
		set_git_dir(gitdirenv);
		free(gitfile);
		return NULL;
	}
	else /* #2, #10 */
		set_git_work_tree(".");

	/* set_git_work_tree() must have been called by now */
	worktree = get_git_work_tree();

	/* both get_git_work_tree() and cwd are already normalized */
	if (!strcmp(cwd->buf, worktree)) { /* cwd == worktree */
		set_git_dir(gitdirenv);
		free(gitfile);
		return NULL;
	}

	offset = dir_inside_of(cwd->buf, worktree);
	if (offset >= 0) {	/* cwd inside worktree? */
		set_git_dir(real_path(gitdirenv));
		if (chdir(worktree))
			die_errno("Could not chdir to '%s'", worktree);
		strbuf_addch(cwd, '/');
		free(gitfile);
		return cwd->buf + offset;
	}

	/* cwd outside worktree */
	set_git_dir(gitdirenv);
	free(gitfile);
	return NULL;
}
示例#24
0
char *
grub_find_device (const char *dir, dev_t dev)
{
  DIR *dp;
  char *saved_cwd;
  struct dirent *ent;

  if (! dir)
    dir = "/dev";

  dp = opendir (dir);
  if (! dp)
    return 0;

  saved_cwd = xgetcwd ();

  grub_util_info ("changing current directory to %s", dir);
  if (chdir (dir) < 0)
    {
      free (saved_cwd);
      closedir (dp);
      return 0;
    }

  while ((ent = readdir (dp)) != 0)
    {
      struct stat st;

      /* Avoid:
	 - dotfiles (like "/dev/.tmp.md0") since they could be duplicates.
	 - dotdirs (like "/dev/.static") since they could contain duplicates.  */
      if (ent->d_name[0] == '.')
	continue;

      if (lstat (ent->d_name, &st) < 0)
	/* Ignore any error.  */
	continue;

      if (S_ISLNK (st.st_mode)) {
#ifdef __linux__
	if (strcmp (dir, "mapper") == 0 || strcmp (dir, "/dev/mapper") == 0) {
	  /* Follow symbolic links under /dev/mapper/; the canonical name
	     may be something like /dev/dm-0, but the names under
	     /dev/mapper/ are more human-readable and so we prefer them if
	     we can get them.  */
	  if (stat (ent->d_name, &st) < 0)
	    continue;
	} else
#endif /* __linux__ */
	/* Don't follow other symbolic links.  */
	continue;
      }

      if (S_ISDIR (st.st_mode))
	{
	  /* Find it recursively.  */
	  char *res;

	  res = grub_find_device (ent->d_name, dev);

	  if (res)
	    {
	      if (chdir (saved_cwd) < 0)
		grub_util_error ("%s",
				 _("cannot restore the original directory"));

	      free (saved_cwd);
	      closedir (dp);
	      return res;
	    }
	}

#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__)
      if (S_ISCHR (st.st_mode) && st.st_rdev == dev)
#else
      if (S_ISBLK (st.st_mode) && st.st_rdev == dev)
#endif
	{
#ifdef __linux__
	  /* Skip device names like /dev/dm-0, which are short-hand aliases
	     to more descriptive device names, e.g. those under /dev/mapper */
	  if (ent->d_name[0] == 'd' &&
	      ent->d_name[1] == 'm' &&
	      ent->d_name[2] == '-' &&
	      ent->d_name[3] >= '0' &&
	      ent->d_name[3] <= '9')
	    continue;
#endif

	  /* Found!  */
	  char *res;
	  char *cwd;

	  cwd = xgetcwd ();
	  res = xmalloc (strlen (cwd) + strlen (ent->d_name) + 3);
	  sprintf (res, 
#if defined(__NetBSD__) || defined(__OpenBSD__)
		   /* Convert this block device to its character (raw) device.  */
		   "%s/r%s",
#else
		   /* Keep the device name as it is.  */
		   "%s/%s",
#endif
		   cwd, ent->d_name);
	  strip_extra_slashes (res);
	  free (cwd);

	  /* /dev/root is not a real block device keep looking, takes care
	     of situation where root filesystem is on the same partition as
	     grub files */

	  if (strcmp(res, "/dev/root") == 0)
	    {
	      free (res);
	      continue;
	    }

	  if (chdir (saved_cwd) < 0)
	    grub_util_error ("%s", _("cannot restore the original directory"));

	  free (saved_cwd);
	  closedir (dp);
	  return res;
	}
    }

  if (chdir (saved_cwd) < 0)
    grub_util_error ("%s", _("cannot restore the original directory"));

  free (saved_cwd);
  closedir (dp);
  return 0;
}
示例#25
0
int cmd_rev_parse(int argc, const char **argv, const char *prefix)
{
	int i, as_is = 0, verify = 0, quiet = 0, revs_count = 0, type = 0;
	int did_repo_setup = 0;
	int has_dashdash = 0;
	int output_prefix = 0;
	unsigned char sha1[20];
	unsigned int flags = 0;
	const char *name = NULL;
	struct object_context unused;

	if (argc > 1 && !strcmp("--parseopt", argv[1]))
		return cmd_parseopt(argc - 1, argv + 1, prefix);

	if (argc > 1 && !strcmp("--sq-quote", argv[1]))
		return cmd_sq_quote(argc - 2, argv + 2);

	if (argc > 1 && !strcmp("-h", argv[1]))
		usage(builtin_rev_parse_usage);

	for (i = 1; i < argc; i++) {
		if (!strcmp(argv[i], "--")) {
			has_dashdash = 1;
			break;
		}
	}

	/* No options; just report on whether we're in a git repo or not. */
	if (argc == 1) {
		setup_git_directory();
		git_config(git_default_config, NULL);
		return 0;
	}

	for (i = 1; i < argc; i++) {
		const char *arg = argv[i];

		if (!strcmp(arg, "--local-env-vars")) {
			int i;
			for (i = 0; local_repo_env[i]; i++)
				printf("%s\n", local_repo_env[i]);
			continue;
		}
		if (!strcmp(arg, "--resolve-git-dir")) {
			const char *gitdir = argv[++i];
			if (!gitdir)
				die("--resolve-git-dir requires an argument");
			gitdir = resolve_gitdir(gitdir);
			if (!gitdir)
				die("not a gitdir '%s'", argv[i]);
			puts(gitdir);
			continue;
		}

		/* The rest of the options require a git repository. */
		if (!did_repo_setup) {
			prefix = setup_git_directory();
			git_config(git_default_config, NULL);
			did_repo_setup = 1;
		}

		if (!strcmp(arg, "--git-path")) {
			if (!argv[i + 1])
				die("--git-path requires an argument");
			puts(git_path("%s", argv[i + 1]));
			i++;
			continue;
		}
		if (as_is) {
			if (show_file(arg, output_prefix) && as_is < 2)
				verify_filename(prefix, arg, 0);
			continue;
		}
		if (!strcmp(arg,"-n")) {
			if (++i >= argc)
				die("-n requires an argument");
			if ((filter & DO_FLAGS) && (filter & DO_REVS)) {
				show(arg);
				show(argv[i]);
			}
			continue;
		}
		if (starts_with(arg, "-n")) {
			if ((filter & DO_FLAGS) && (filter & DO_REVS))
				show(arg);
			continue;
		}

		if (*arg == '-') {
			if (!strcmp(arg, "--")) {
				as_is = 2;
				/* Pass on the "--" if we show anything but files.. */
				if (filter & (DO_FLAGS | DO_REVS))
					show_file(arg, 0);
				continue;
			}
			if (!strcmp(arg, "--default")) {
				def = argv[++i];
				if (!def)
					die("--default requires an argument");
				continue;
			}
			if (!strcmp(arg, "--prefix")) {
				prefix = argv[++i];
				if (!prefix)
					die("--prefix requires an argument");
				startup_info->prefix = prefix;
				output_prefix = 1;
				continue;
			}
			if (!strcmp(arg, "--revs-only")) {
				filter &= ~DO_NOREV;
				continue;
			}
			if (!strcmp(arg, "--no-revs")) {
				filter &= ~DO_REVS;
				continue;
			}
			if (!strcmp(arg, "--flags")) {
				filter &= ~DO_NONFLAGS;
				continue;
			}
			if (!strcmp(arg, "--no-flags")) {
				filter &= ~DO_FLAGS;
				continue;
			}
			if (!strcmp(arg, "--verify")) {
				filter &= ~(DO_FLAGS|DO_NOREV);
				verify = 1;
				continue;
			}
			if (!strcmp(arg, "--quiet") || !strcmp(arg, "-q")) {
				quiet = 1;
				flags |= GET_SHA1_QUIETLY;
				continue;
			}
			if (opt_with_value(arg, "--short", &arg)) {
				filter &= ~(DO_FLAGS|DO_NOREV);
				verify = 1;
				abbrev = DEFAULT_ABBREV;
				if (!arg)
					continue;
				abbrev = strtoul(arg, NULL, 10);
				if (abbrev < MINIMUM_ABBREV)
					abbrev = MINIMUM_ABBREV;
				else if (40 <= abbrev)
					abbrev = 40;
				continue;
			}
			if (!strcmp(arg, "--sq")) {
				output_sq = 1;
				continue;
			}
			if (!strcmp(arg, "--not")) {
				show_type ^= REVERSED;
				continue;
			}
			if (!strcmp(arg, "--symbolic")) {
				symbolic = SHOW_SYMBOLIC_ASIS;
				continue;
			}
			if (!strcmp(arg, "--symbolic-full-name")) {
				symbolic = SHOW_SYMBOLIC_FULL;
				continue;
			}
			if (opt_with_value(arg, "--abbrev-ref", &arg)) {
				abbrev_ref = 1;
				abbrev_ref_strict = warn_ambiguous_refs;
				if (arg) {
					if (!strcmp(arg, "strict"))
						abbrev_ref_strict = 1;
					else if (!strcmp(arg, "loose"))
						abbrev_ref_strict = 0;
					else
						die("unknown mode for --abbrev-ref: %s",
						    arg);
				}
				continue;
			}
			if (!strcmp(arg, "--all")) {
				for_each_ref(show_reference, NULL);
				continue;
			}
			if (skip_prefix(arg, "--disambiguate=", &arg)) {
				for_each_abbrev(arg, show_abbrev, NULL);
				continue;
			}
			if (!strcmp(arg, "--bisect")) {
				for_each_ref_in("refs/bisect/bad", show_reference, NULL);
				for_each_ref_in("refs/bisect/good", anti_reference, NULL);
				continue;
			}
			if (opt_with_value(arg, "--branches", &arg)) {
				handle_ref_opt(arg, "refs/heads/");
				continue;
			}
			if (opt_with_value(arg, "--tags", &arg)) {
				handle_ref_opt(arg, "refs/tags/");
				continue;
			}
			if (skip_prefix(arg, "--glob=", &arg)) {
				handle_ref_opt(arg, NULL);
				continue;
			}
			if (opt_with_value(arg, "--remotes", &arg)) {
				handle_ref_opt(arg, "refs/remotes/");
				continue;
			}
			if (skip_prefix(arg, "--exclude=", &arg)) {
				add_ref_exclusion(&ref_excludes, arg);
				continue;
			}
			if (!strcmp(arg, "--show-toplevel")) {
				const char *work_tree = get_git_work_tree();
				if (work_tree)
					puts(work_tree);
				continue;
			}
			if (!strcmp(arg, "--show-prefix")) {
				if (prefix)
					puts(prefix);
				else
					putchar('\n');
				continue;
			}
			if (!strcmp(arg, "--show-cdup")) {
				const char *pfx = prefix;
				if (!is_inside_work_tree()) {
					const char *work_tree =
						get_git_work_tree();
					if (work_tree)
						printf("%s\n", work_tree);
					continue;
				}
				while (pfx) {
					pfx = strchr(pfx, '/');
					if (pfx) {
						pfx++;
						printf("../");
					}
				}
				putchar('\n');
				continue;
			}
			if (!strcmp(arg, "--git-dir")) {
				const char *gitdir = getenv(GIT_DIR_ENVIRONMENT);
				char *cwd;
				int len;
				if (gitdir) {
					puts(gitdir);
					continue;
				}
				if (!prefix) {
					puts(".git");
					continue;
				}
				cwd = xgetcwd();
				len = strlen(cwd);
				printf("%s%s.git\n", cwd, len && cwd[len-1] != '/' ? "/" : "");
				free(cwd);
				continue;
			}
			if (!strcmp(arg, "--git-common-dir")) {
				const char *pfx = prefix ? prefix : "";
				puts(prefix_filename(pfx, strlen(pfx), get_git_common_dir()));
				continue;
			}
			if (!strcmp(arg, "--is-inside-git-dir")) {
				printf("%s\n", is_inside_git_dir() ? "true"
						: "false");
				continue;
			}
			if (!strcmp(arg, "--is-inside-work-tree")) {
				printf("%s\n", is_inside_work_tree() ? "true"
						: "false");
				continue;
			}
			if (!strcmp(arg, "--is-bare-repository")) {
				printf("%s\n", is_bare_repository() ? "true"
						: "false");
				continue;
			}
			if (!strcmp(arg, "--shared-index-path")) {
				if (read_cache() < 0)
					die(_("Could not read the index"));
				if (the_index.split_index) {
					const unsigned char *sha1 = the_index.split_index->base_sha1;
					puts(git_path("sharedindex.%s", sha1_to_hex(sha1)));
				}
				continue;
			}
			if (skip_prefix(arg, "--since=", &arg)) {
				show_datestring("--max-age=", arg);
				continue;
			}
			if (skip_prefix(arg, "--after=", &arg)) {
				show_datestring("--max-age=", arg);
				continue;
			}
			if (skip_prefix(arg, "--before=", &arg)) {
				show_datestring("--min-age=", arg);
				continue;
			}
			if (skip_prefix(arg, "--until=", &arg)) {
				show_datestring("--min-age=", arg);
				continue;
			}
			if (show_flag(arg) && verify)
				die_no_single_rev(quiet);
			continue;
		}

		/* Not a flag argument */
		if (try_difference(arg))
			continue;
		if (try_parent_shorthands(arg))
			continue;
		name = arg;
		type = NORMAL;
		if (*arg == '^') {
			name++;
			type = REVERSED;
		}
		if (!get_sha1_with_context(name, flags, sha1, &unused)) {
			if (verify)
				revs_count++;
			else
				show_rev(type, sha1, name);
			continue;
		}
		if (verify)
			die_no_single_rev(quiet);
		if (has_dashdash)
			die("bad revision '%s'", arg);
		as_is = 1;
		if (!show_file(arg, output_prefix))
			continue;
		verify_filename(prefix, arg, 1);
	}
	if (verify) {
		if (revs_count == 1) {
			show_rev(type, sha1, name);
			return 0;
		} else if (revs_count == 0 && show_default())
			return 0;
		die_no_single_rev(quiet);
	} else
		show_default();
	return 0;
}
示例#26
0
static void
read_directory_file (void)
{
  char *strp;
  FILE *fp;
  char buf[512];		/* FIXME: use a symbol */
  static char *path = NULL;

  if (path == NULL)
    path = xmalloc (PATH_MAX);
  time (&time_now);
  if (listed_incremental_option[0] != '/'
#if DOSWIN
      /* The case of DOSWIN absolute file name with a drive letter.  */
      && !(listed_incremental_option[0] && listed_incremental_option[1] == ':')
#endif
      )
    {
      char *current_directory = xgetcwd ();

      if (!current_directory)
	FATAL_ERROR ((0, 0, _("Could not get current directory")));

      listed_incremental_option
	= concat_with_slash (current_directory, listed_incremental_option);
    }
  fp = fopen (listed_incremental_option, "r");
  if (fp == 0 && errno != ENOENT)
    {
      ERROR ((0, errno, _("Cannot open %s"), listed_incremental_option));
      return;
    }
  if (!fp)
    return;
  fgets (buf, sizeof (buf), fp);

  /* FIXME: Using newer_ctime_option as a first time flag looks fairly dubious
     to me!  So, using -N with incremental might be buggy just because of the
     next few lines.  I saw a few unexplained, almost harsh advices from FSF
     people about *not* using -N with incremental dumps, and here might lie
     (part of) the reason.  */
  if (!newer_ctime_option)
    {
      time_option_threshold = atol (buf);
      newer_ctime_option = true;
    }

  while (fgets (buf, sizeof (buf), fp))
    {
      dev_t device_number;
      ino_t inode_number;

      strp = &buf[strlen (buf)];
      if (strp[-1] == '\n')
	strp[-1] = '\0';
      /* FIXME: For files ending with an incomplete line, maybe a NUL might
	 be missing, here...  */

      strp = buf;
      device_number = atol (strp);
      while (ISDIGIT (*strp))
	strp++;
      inode_number = atol (strp);
      while (ISSPACE (*strp))
	strp++;
      while (ISDIGIT (*strp))
	strp++;
      strp++;
      unquote_string (strp);
      note_directory (strp, device_number, inode_number, NULL);
    }
  if (fclose (fp) == EOF)
    ERROR ((0, errno, "%s", listed_incremental_option));
}
示例#27
0
int
main ()
{
  int i;
  int dfd;
  char *cwd;
  int result;

  /* Clean up any trash from prior testsuite runs.  */
  ASSERT (system ("rm -rf " BASE "*") == 0);

  /* Test basic link functionality, without mentioning symlinks.  */
  result = test_link (do_link, false);
  dfd1 = open (".", O_RDONLY);
  ASSERT (0 <= dfd1);
  ASSERT (test_link (do_link, false) == result);
  dfd2 = dfd1;
  ASSERT (test_link (do_link, false) == result);
  dfd1 = AT_FDCWD;
  ASSERT (test_link (do_link, false) == result);
  flag = 0;
  ASSERT (test_link (do_link, false) == result);
  dfd1 = dfd2;
  ASSERT (test_link (do_link, false) == result);
  dfd2 = AT_FDCWD;
  ASSERT (test_link (do_link, false) == result);
  ASSERT (close (dfd1) == 0);
  dfd1 = AT_FDCWD;
  ASSERT (test_link (do_link, false) == result);

  /* Create locations to manipulate.  */
  ASSERT (mkdir (BASE "sub1", 0700) == 0);
  ASSERT (mkdir (BASE "sub2", 0700) == 0);
  ASSERT (close (creat (BASE "00", 0600)) == 0);
  cwd = xgetcwd ();

  dfd = open (BASE "sub1", O_RDONLY);
  ASSERT (0 <= dfd);
  ASSERT (chdir (BASE "sub2") == 0);

  /* There are 16 possible scenarios, based on whether an fd is
     AT_FDCWD or real, whether a file is absolute or relative, coupled
     with whether flag is set for 32 iterations.

     To ensure that we test all of the code paths (rather than
     triggering early normalization optimizations), we use a loop to
     repeatedly rename a file in the parent directory, use an fd open
     on subdirectory 1, all while executing in subdirectory 2; all
     relative names are thus given with a leading "../".  Finally, the
     last scenario (two relative paths given, neither one AT_FDCWD)
     has two paths, based on whether the two fds are equivalent, so we
     do the other variant after the loop.  */
  for (i = 0; i < 32; i++)
    {
      int flag = (i & 0x10 ? AT_SYMLINK_FOLLOW : 0);
      int fd1 = (i & 8) ? dfd : AT_FDCWD;
      char *file1 = file_name_concat ((i & 4) ? ".." : cwd, BASE "xx", NULL);
      int fd2 = (i & 2) ? dfd : AT_FDCWD;
      char *file2 = file_name_concat ((i & 1) ? ".." : cwd, BASE "xx", NULL);

      ASSERT (sprintf (strchr (file1, '\0') - 2, "%02d", i) == 2);
      ASSERT (sprintf (strchr (file2, '\0') - 2, "%02d", i + 1) == 2);
      ASSERT (linkat (fd1, file1, fd2, file2, flag) == 0);
      ASSERT (unlinkat (fd1, file1, 0) == 0);
      free (file1);
      free (file2);
    }
  dfd2 = open ("..", O_RDONLY);
  ASSERT (0 <= dfd2);
  ASSERT (linkat (dfd, "../" BASE "32", dfd2, BASE "33", 0) == 0);
  ASSERT (linkat (dfd, "../" BASE "33", dfd2, BASE "34",
                  AT_SYMLINK_FOLLOW) == 0);
  ASSERT (close (dfd2) == 0);

  /* Now we change back to the parent directory, and set dfd to ".",
     in order to test behavior on symlinks.  */
  ASSERT (chdir ("..") == 0);
  ASSERT (close (dfd) == 0);
  if (symlink (BASE "sub1", BASE "link1"))
    {
      ASSERT (unlink (BASE "32") == 0);
      ASSERT (unlink (BASE "33") == 0);
      ASSERT (unlink (BASE "34") == 0);
      ASSERT (rmdir (BASE "sub1") == 0);
      ASSERT (rmdir (BASE "sub2") == 0);
      free (cwd);
      fputs ("skipping test: symlinks not supported on this filesystem\n",
             stderr);
      return result;
    }
  dfd = open (".", O_RDONLY);
  ASSERT (0 <= dfd);
  ASSERT (symlink (BASE "34", BASE "link2") == 0);
  ASSERT (symlink (BASE "link3", BASE "link3") == 0);
  ASSERT (symlink (BASE "nowhere", BASE "link4") == 0);

  /* Link cannot overwrite existing files.  */
  errno = 0;
  ASSERT (linkat (dfd, BASE "link1", dfd, BASE "sub1", 0) == -1);
  ASSERT (errno == EEXIST);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link1/", dfd, BASE "sub1", 0) == -1);
  ASSERT (errno == EEXIST || errno == EPERM || errno == EACCES);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link1", dfd, BASE "sub1/", 0) == -1);
  ASSERT (errno == EEXIST);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link1", dfd, BASE "sub1",
                  AT_SYMLINK_FOLLOW) == -1);
  ASSERT (errno == EEXIST || errno == EPERM || errno == EACCES);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link1/", dfd, BASE "sub1",
                  AT_SYMLINK_FOLLOW) == -1);
  ASSERT (errno == EEXIST || errno == EPERM || errno == EACCES);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link1", dfd, BASE "sub1/",
                  AT_SYMLINK_FOLLOW) == -1);
  ASSERT (errno == EEXIST || errno == EPERM || errno == EACCES);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link1", dfd, BASE "link2", 0) == -1);
  ASSERT (errno == EEXIST);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link1", dfd, BASE "link2",
                  AT_SYMLINK_FOLLOW) == -1);
  ASSERT (errno == EEXIST || errno == EPERM || errno == EACCES);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link1", dfd, BASE "link3", 0) == -1);
  ASSERT (errno == EEXIST || errno == ELOOP);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link1", dfd, BASE "link3",
                  AT_SYMLINK_FOLLOW) == -1);
  ASSERT (errno == EEXIST || errno == EPERM || errno == EACCES
          || errno == ELOOP);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link2", dfd, BASE "link3", 0) == -1);
  ASSERT (errno == EEXIST || errno == ELOOP);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link2", dfd, BASE "link3",
                  AT_SYMLINK_FOLLOW) == -1);
  ASSERT (errno == EEXIST || errno == ELOOP);

  /* AT_SYMLINK_FOLLOW only follows first argument, not second.  */
  errno = 0;
  ASSERT (linkat (dfd, BASE "link1", dfd, BASE "link4", 0) == -1);
  ASSERT (errno == EEXIST);
  ASSERT (linkat (dfd, BASE "link1", dfd, BASE "link4",
                  AT_SYMLINK_FOLLOW) == -1);
  ASSERT (errno == EEXIST || errno == EPERM || errno == EACCES);
  errno = 0;
  ASSERT (linkat (dfd, BASE "34", dfd, BASE "link4", 0) == -1);
  ASSERT (errno == EEXIST);
  errno = 0;
  ASSERT (linkat (dfd, BASE "34", dfd, BASE "link4", AT_SYMLINK_FOLLOW) == -1);
  ASSERT (errno == EEXIST);

  /* Trailing slash handling.  */
  errno = 0;
  ASSERT (linkat (dfd, BASE "link2/", dfd, BASE "link5", 0) == -1);
  ASSERT (errno == ENOTDIR);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link2/", dfd, BASE "link5",
                  AT_SYMLINK_FOLLOW) == -1);
  ASSERT (errno == ENOTDIR);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link3/", dfd, BASE "link5", 0) == -1);
  ASSERT (errno == ELOOP);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link3/", dfd, BASE "link5",
                  AT_SYMLINK_FOLLOW) == -1);
  ASSERT (errno == ELOOP);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link4/", dfd, BASE "link5", 0) == -1);
  ASSERT (errno == ENOENT);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link4/", dfd, BASE "link5",
                  AT_SYMLINK_FOLLOW) == -1);
  ASSERT (errno == ENOENT);

  /* Check for hard links to symlinks.  */
  ASSERT (linkat (dfd, BASE "link1", dfd, BASE "link5", 0) == 0);
  check_same_link (BASE "link1", BASE "link5");
  ASSERT (unlink (BASE "link5") == 0);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link1", dfd, BASE "link5",
                  AT_SYMLINK_FOLLOW) == -1);
  ASSERT (errno == EPERM || errno == EACCES);
  ASSERT (linkat (dfd, BASE "link2", dfd, BASE "link5", 0) == 0);
  check_same_link (BASE "link2", BASE "link5");
  ASSERT (unlink (BASE "link5") == 0);
  ASSERT (linkat (dfd, BASE "link2", dfd, BASE "file", AT_SYMLINK_FOLLOW) == 0);
  errno = 0;
  ASSERT (areadlink (BASE "file") == NULL);
  ASSERT (errno == EINVAL);
  ASSERT (unlink (BASE "file") == 0);
  ASSERT (linkat (dfd, BASE "link3", dfd, BASE "link5", 0) == 0);
  check_same_link (BASE "link3", BASE "link5");
  ASSERT (unlink (BASE "link5") == 0);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link3", dfd, BASE "link5",
                  AT_SYMLINK_FOLLOW) == -1);
  ASSERT (errno == ELOOP);
  ASSERT (linkat (dfd, BASE "link4", dfd, BASE "link5", 0) == 0);
  check_same_link (BASE "link4", BASE "link5");
  ASSERT (unlink (BASE "link5") == 0);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link4", dfd, BASE "link5",
                  AT_SYMLINK_FOLLOW) == -1);
  ASSERT (errno == ENOENT);

  /* Check that symlink to symlink to file is followed all the way.  */
  ASSERT (symlink (BASE "link2", BASE "link5") == 0);
  ASSERT (linkat (dfd, BASE "link5", dfd, BASE "link6", 0) == 0);
  check_same_link (BASE "link5", BASE "link6");
  ASSERT (unlink (BASE "link6") == 0);
  ASSERT (linkat (dfd, BASE "link5", dfd, BASE "file", AT_SYMLINK_FOLLOW) == 0);
  errno = 0;
  ASSERT (areadlink (BASE "file") == NULL);
  ASSERT (errno == EINVAL);
  ASSERT (unlink (BASE "file") == 0);
  ASSERT (unlink (BASE "link5") == 0);
  ASSERT (symlink (BASE "link3", BASE "link5") == 0);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link5", dfd, BASE "file",
                  AT_SYMLINK_FOLLOW) == -1);
  ASSERT (errno == ELOOP);
  ASSERT (unlink (BASE "link5") == 0);
  ASSERT (symlink (BASE "link4", BASE "link5") == 0);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link5", dfd, BASE "file",
                  AT_SYMLINK_FOLLOW) == -1);
  ASSERT (errno == ENOENT);

  /* Now for some real fun with directory crossing.  */
  ASSERT (symlink (cwd, BASE "sub1/link") == 0);
  ASSERT (symlink (".././/" BASE "sub1/link/" BASE "link2",
                   BASE "sub2/link") == 0);
  ASSERT (close (dfd) == 0);
  dfd = open (BASE "sub1", O_RDONLY);
  ASSERT (0 <= dfd);
  dfd2 = open (BASE "sub2", O_RDONLY);
  ASSERT (0 < dfd2);
  ASSERT (linkat (dfd, "../" BASE "sub2/link", dfd2, "./..//" BASE "sub1/file",
              AT_SYMLINK_FOLLOW) == 0);
  errno = 0;
  ASSERT (areadlink (BASE "sub1/file") == NULL);
  ASSERT (errno == EINVAL);

  /* Cleanup.  */
  ASSERT (close (dfd) == 0);
  ASSERT (close (dfd2) == 0);
  ASSERT (unlink (BASE "sub1/file") == 0);
  ASSERT (unlink (BASE "sub1/link") == 0);
  ASSERT (unlink (BASE "sub2/link") == 0);
  ASSERT (unlink (BASE "32") == 0);
  ASSERT (unlink (BASE "33") == 0);
  ASSERT (unlink (BASE "34") == 0);
  ASSERT (rmdir (BASE "sub1") == 0);
  ASSERT (rmdir (BASE "sub2") == 0);
  ASSERT (unlink (BASE "link1") == 0);
  ASSERT (unlink (BASE "link2") == 0);
  ASSERT (unlink (BASE "link3") == 0);
  ASSERT (unlink (BASE "link4") == 0);
  ASSERT (unlink (BASE "link5") == 0);
  free (cwd);
  return result;
}
示例#28
0
static int test_if_untracked_cache_is_supported(void)
{
	struct stat st;
	struct stat_data base;
	int fd, ret = 0;
	char *cwd;

	strbuf_addstr(&mtime_dir, "mtime-test-XXXXXX");
	if (!mkdtemp(mtime_dir.buf))
		die_errno("Could not make temporary directory");

	cwd = xgetcwd();
	fprintf(stderr, _("Testing mtime in '%s' "), cwd);
	free(cwd);

	atexit(remove_test_directory);
	xstat_mtime_dir(&st);
	fill_stat_data(&base, &st);
	fputc('.', stderr);

	avoid_racy();
	fd = create_file("newfile");
	xstat_mtime_dir(&st);
	if (!match_stat_data(&base, &st)) {
		close(fd);
		fputc('\n', stderr);
		fprintf_ln(stderr,_("directory stat info does not "
				    "change after adding a new file"));
		goto done;
	}
	fill_stat_data(&base, &st);
	fputc('.', stderr);

	avoid_racy();
	xmkdir("new-dir");
	xstat_mtime_dir(&st);
	if (!match_stat_data(&base, &st)) {
		close(fd);
		fputc('\n', stderr);
		fprintf_ln(stderr, _("directory stat info does not change "
				     "after adding a new directory"));
		goto done;
	}
	fill_stat_data(&base, &st);
	fputc('.', stderr);

	avoid_racy();
	write_or_die(fd, "data", 4);
	close(fd);
	xstat_mtime_dir(&st);
	if (match_stat_data(&base, &st)) {
		fputc('\n', stderr);
		fprintf_ln(stderr, _("directory stat info changes "
				     "after updating a file"));
		goto done;
	}
	fputc('.', stderr);

	avoid_racy();
	close(create_file("new-dir/new"));
	xstat_mtime_dir(&st);
	if (match_stat_data(&base, &st)) {
		fputc('\n', stderr);
		fprintf_ln(stderr, _("directory stat info changes after "
				     "adding a file inside subdirectory"));
		goto done;
	}
	fputc('.', stderr);

	avoid_racy();
	xunlink("newfile");
	xstat_mtime_dir(&st);
	if (!match_stat_data(&base, &st)) {
		fputc('\n', stderr);
		fprintf_ln(stderr, _("directory stat info does not "
				     "change after deleting a file"));
		goto done;
	}
	fill_stat_data(&base, &st);
	fputc('.', stderr);

	avoid_racy();
	xunlink("new-dir/new");
	xrmdir("new-dir");
	xstat_mtime_dir(&st);
	if (!match_stat_data(&base, &st)) {
		fputc('\n', stderr);
		fprintf_ln(stderr, _("directory stat info does not "
				     "change after deleting a directory"));
		goto done;
	}

	if (rmdir(mtime_dir.buf))
		die_errno(_("failed to delete directory %s"), mtime_dir.buf);
	fprintf_ln(stderr, _(" OK"));
	ret = 1;

done:
	strbuf_release(&mtime_dir);
	return ret;
}
示例#29
0
/*
 * If you want to, you can share the DB area with any number of branches.
 * That has advantages: you can save space by sharing all the SHA1 objects.
 * On the other hand, it might just make lookup slower and messier. You
 * be the judge.  The default case is to have one DB per managed directory.
 */
int cmd_init_db(int argc, const char **argv, const char *prefix)
{
	const char *git_dir;
	const char *real_git_dir = NULL;
	const char *work_tree;
	const char *template_dir = NULL;
	unsigned int flags = 0;
	const struct option init_db_options[] = {
		OPT_STRING(0, "template", &template_dir, N_("template-directory"),
				N_("directory from which templates will be used")),
		OPT_SET_INT(0, "bare", &is_bare_repository_cfg,
				N_("create a bare repository"), 1),
		{ OPTION_CALLBACK, 0, "shared", &init_shared_repository,
			N_("permissions"),
			N_("specify that the git repository is to be shared amongst several users"),
			PARSE_OPT_OPTARG | PARSE_OPT_NONEG, shared_callback, 0},
		OPT_BIT('q', "quiet", &flags, N_("be quiet"), INIT_DB_QUIET),
		OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
			   N_("separate git dir from working tree")),
		OPT_END()
	};

	argc = parse_options(argc, argv, prefix, init_db_options, init_db_usage, 0);

	if (real_git_dir && !is_absolute_path(real_git_dir))
		real_git_dir = real_pathdup(real_git_dir, 1);

	if (argc == 1) {
		int mkdir_tried = 0;
	retry:
		if (chdir(argv[0]) < 0) {
			if (!mkdir_tried) {
				int saved;
				/*
				 * At this point we haven't read any configuration,
				 * and we know shared_repository should always be 0;
				 * but just in case we play safe.
				 */
				saved = get_shared_repository();
				set_shared_repository(0);
				switch (safe_create_leading_directories_const(argv[0])) {
				case SCLD_OK:
				case SCLD_PERMS:
					break;
				case SCLD_EXISTS:
					errno = EEXIST;
					/* fallthru */
				default:
					die_errno(_("cannot mkdir %s"), argv[0]);
					break;
				}
				set_shared_repository(saved);
				if (mkdir(argv[0], 0777) < 0)
					die_errno(_("cannot mkdir %s"), argv[0]);
				mkdir_tried = 1;
				goto retry;
			}
			die_errno(_("cannot chdir to %s"), argv[0]);
		}
	} else if (0 < argc) {
		usage(init_db_usage[0]);
	}
	if (is_bare_repository_cfg == 1) {
		char *cwd = xgetcwd();
		setenv(GIT_DIR_ENVIRONMENT, cwd, argc > 0);
		free(cwd);
	}

	if (init_shared_repository != -1)
		set_shared_repository(init_shared_repository);

	/*
	 * GIT_WORK_TREE makes sense only in conjunction with GIT_DIR
	 * without --bare.  Catch the error early.
	 */
	git_dir = xstrdup_or_null(getenv(GIT_DIR_ENVIRONMENT));
	work_tree = xstrdup_or_null(getenv(GIT_WORK_TREE_ENVIRONMENT));
	if ((!git_dir || is_bare_repository_cfg == 1) && work_tree)
		die(_("%s (or --work-tree=<directory>) not allowed without "
			  "specifying %s (or --git-dir=<directory>)"),
		    GIT_WORK_TREE_ENVIRONMENT,
		    GIT_DIR_ENVIRONMENT);

	/*
	 * Set up the default .git directory contents
	 */
	if (!git_dir)
		git_dir = DEFAULT_GIT_DIR_ENVIRONMENT;

	if (is_bare_repository_cfg < 0)
		is_bare_repository_cfg = guess_repository_type(git_dir);

	if (!is_bare_repository_cfg) {
		const char *git_dir_parent = strrchr(git_dir, '/');
		if (git_dir_parent) {
			char *rel = xstrndup(git_dir, git_dir_parent - git_dir);
			git_work_tree_cfg = real_pathdup(rel, 1);
			free(rel);
		}
		if (!git_work_tree_cfg)
			git_work_tree_cfg = xgetcwd();
		if (work_tree)
			set_git_work_tree(work_tree);
		else
			set_git_work_tree(git_work_tree_cfg);
		if (access(get_git_work_tree(), X_OK))
			die_errno (_("Cannot access work tree '%s'"),
				   get_git_work_tree());
	}
	else {
		if (work_tree)
			set_git_work_tree(work_tree);
	}

	UNLEAK(real_git_dir);
	UNLEAK(git_dir);
	UNLEAK(work_tree);

	flags |= INIT_DB_EXIST_OK;
	return init_db(git_dir, real_git_dir, template_dir, flags);
}
示例#30
0
	      ent->d_name[3] <= '9')
	    continue;
#endif

	  /* Found!  */
	  char *res;
	  char *cwd;
#if defined(__NetBSD__) || defined(__OpenBSD__)
	  /* Convert this block device to its character (raw) device.  */
	  const char *template = "%s/r%s";
#else
	  /* Keep the device name as it is.  */
	  const char *template = "%s/%s";
#endif

	  cwd = xgetcwd ();
	  res = xmalloc (strlen (cwd) + strlen (ent->d_name) + 3);
	  sprintf (res, template, cwd, ent->d_name);
	  strip_extra_slashes (res);
	  free (cwd);

	  /* /dev/root is not a real block device keep looking, takes care
	     of situation where root filesystem is on the same partition as
	     grub files */

	  if (strcmp(res, "/dev/root") == 0)
	    {
	      free (res);
	      continue;
	    }