Ejemplo n.º 1
0
const char *
gnupg_bindir (void)
{
#if defined (HAVE_W32CE_SYSTEM)
  static char *name;

  if (!name)
    name = xstrconcat (w32_rootdir (), DIRSEP_S "bin", NULL);
  return name;
#elif defined(HAVE_W32_SYSTEM)
  const char *rdir;

  rdir = w32_rootdir ();
  if (w32_bin_is_bin)
    {
      static char *name;

      if (!name)
        name = xstrconcat (rdir, DIRSEP_S "bin", NULL);
      return name;
    }
  else
    return rdir;
#else /*!HAVE_W32_SYSTEM*/
  return GNUPG_BINDIR;
#endif /*!HAVE_W32_SYSTEM*/
}
Ejemplo n.º 2
0
/*! \brief Check if working with directory Check whether name is a directory. 
   \param[out] dst \param dir Parent directory name \param[in,out] name Child
   file/directory name \param stamp Time stamp applied to the parent directory 
   \param ornamelen Length of the child file/directory name without the
   version suffix \retval ZFS_OK Child is a directory; dst is filled in and
   name suffix is truncated \retval ENOENT Child in not a directory */
int32_t
version_is_directory(string * dst, char *dir, string * name, time_t stamp,
					 time_t * dirstamp, int orgnamelen)
{
	char *x;
	struct stat st;

	x = xstrconcat(dir, name->str, NULL);
	if (orgnamelen)
		x[strlen(dir) + orgnamelen] = '\0';

	if (!lstat(x, &st) && S_ISDIR(st.st_mode))
	{
		// it is a directory
		dst->str = x;
		dst->len = strlen(dst->str);
		free(dir);

		if (orgnamelen)
		{
			if (dirstamp)
				*dirstamp = stamp;
			name->str[orgnamelen] = '\0';
			name->len = orgnamelen;
		}

		RETURN_INT(ZFS_OK);
	}

	free(x);

	RETURN_INT(ENOENT);
}
Ejemplo n.º 3
0
/*! \brief Generate file version specifier Add a version suffix to the
   specified file path. Suffix is generated from the current time.  \param
   path Complete file path.  \param[out] verpath Complete file path including
   a version suffix. */
int32_t version_generate_filename(char *path, string * verpath)
{
	time_t t;
	char stamp[VERSION_MAX_SPECIFIER_LENGTH];	// even unsigned long long int 
												// 
	// will fit in here

	// get current time
	if (time(&t) == -1)
	{
		message(LOG_WARNING, FACILITY_VERSION,
				"version_generate_filename: time returned error=%d\n", errno);
		RETURN_INT(errno);
	}

	// convert to string
	sprintf(stamp, "%ld", t);

	verpath->str = xstrconcat(path, VERSION_NAME_SPECIFIER_S, stamp, NULL);
	verpath->len = strlen(verpath->str);

	message(LOG_DEBUG, FACILITY_VERSION,
			"version_generate_filename: path=%s, stamp=%s\n", path, stamp);

	RETURN_INT(ZFS_OK);
}
Ejemplo n.º 4
0
/* Return the default pinentry name.  If RESET is true the internal
   cache is first flushed.  */
static const char *
get_default_pinentry_name (int reset)
{
  static struct {
    const char *(*rfnc)(void);
    const char *name;
  } names[] = {
    /* The first entry is what we return in case we found no
       other pinentry.  */
    { gnupg_bindir, DIRSEP_S "pinentry" EXEEXT_S },
#ifdef HAVE_W32_SYSTEM
    /* Try Gpg4win directory (with bin and without.) */
    { w32_rootdir, "\\..\\Gpg4win\\bin\\pinentry.exe" },
    { w32_rootdir, "\\..\\Gpg4win\\pinentry.exe" },
    /* Try old Gpgwin directory.  */
    { w32_rootdir, "\\..\\GNU\\GnuPG\\pinentry.exe" },
    /* Try a Pinentry from the common GNU dir.  */
    { w32_rootdir, "\\..\\GNU\\bin\\pinentry.exe" },
#endif
    /* Last chance is a pinentry-basic (which comes with the
       GnuPG 2.1 Windows installer).  */
    { gnupg_bindir, DIRSEP_S "pinentry-basic" EXEEXT_S }
  };
  static char *name;

  if (reset)
    {
      xfree (name);
      name = NULL;
    }

  if (!name)
    {
      int i;

      for (i=0; i < DIM(names); i++)
        {
          char *name2;

          name2 = xstrconcat (names[i].rfnc (), names[i].name, NULL);
          if (!access (name2, F_OK))
            {
              /* Use that pinentry.  */
              xfree (name);
              name = name2;
              break;
            }
          if (!i) /* Store the first as fallback return.  */
            name = name2;
          else
            xfree (name2);
        }
    }

  return name;
}
Ejemplo n.º 5
0
/*! \brief Remove all version files from a directory Remove all version files 
   from specified directory. This function is called from rmdir operations to
   make sure all files are deleted even version files are not displayed. Works 
   correctly only if there are no other files but versions. \param path
   Complete path to the directory */
int32_t version_rmdir_versions(char *path)
{
	int32_t r;
	int working = 1;

	ZFS_DIR * dirp = zfs_opendir(path);
	if (dirp == NULL)
		RETURN_INT(errno);
	
	long dir_start_pos = zfs_telldir(dirp);

	while (working)
	{

		/* Always start from the beginning. We are modifying the contents of
		   the directory. And deleting files, so we will continue until there
		   are no (version) files. */
		zfs_seekdir(dirp, dir_start_pos);

		/* Comments to the work with getdents can be found in other functions. 
		 */

		zfs_dirent entry, *de;
		r = zfs_readdir_r(dirp, &entry, &de);
		if (r > 0)
		{
			zfs_closedir(dirp);
			RETURN_INT(r);
		}
		else if (r == 0 && de == NULL) // end of list
		{
			break;
		}

		/* If we delete at least one file, we should start over again.  */
		working = 0;

		/* Hide version files or convert their names or select them for
		   storage.  */
		if (strchr(de->d_name, VERSION_NAME_SPECIFIER_C))
		{
			char *f;
			f = xstrconcat(path, DIRECTORY_SEPARATOR, de->d_name, NULL);
			unlink(f);
			free(f);
			working = 1;
		}

	}

	zfs_closedir(dirp);

	RETURN_INT(ZFS_OK);
}
Ejemplo n.º 6
0
const char *
gnupg_datadir (void)
{
#ifdef HAVE_W32_SYSTEM
  static char *name;

  if (!name)
    name = xstrconcat (w32_rootdir (), DIRSEP_S "share" DIRSEP_S "gnupg", NULL);
  return name;
#else /*!HAVE_W32_SYSTEM*/
  return GNUPG_DATADIR;
#endif /*!HAVE_W32_SYSTEM*/
}
Ejemplo n.º 7
0
const char *
gnupg_localedir (void)
{
#ifdef HAVE_W32_SYSTEM
  static char *name;

  if (!name)
    name = xstrconcat (w32_rootdir (), DIRSEP_S "share" DIRSEP_S "locale",
                       NULL);
  return name;
#else /*!HAVE_W32_SYSTEM*/
  return LOCALEDIR;
#endif /*!HAVE_W32_SYSTEM*/
}
Ejemplo n.º 8
0
/*! \brief Delete version file Delete version file and its respective
   interval file.  \param path Complete path of the file */
int32_t version_unlink_version_file(char *path)
{
	int32_t r;
	char *x;

	// unlink both version file and interval file
	x = xstrconcat(path, VERSION_INTERVAL_FILE_ADD, NULL);
	unlink(x);
	free(x);

	r = unlink(path);

	RETURN_INT(r);
}
Ejemplo n.º 9
0
/* Get the standard home directory.  In general this function should
   not be used as it does not consider a registry value (under W32) or
   the GNUPGHOME environment variable.  It is better to use
   default_homedir(). */
const char *
standard_homedir (void)
{
#ifdef HAVE_W32_SYSTEM
  static const char *dir;

  if (!dir)
    {
      const char *rdir;

      rdir = w32_rootdir ();
      if (w32_portable_app)
        {
          dir = xstrconcat (rdir, DIRSEP_S "home", NULL);
        }
      else
        {
          char path[MAX_PATH];

          /* It might be better to use LOCAL_APPDATA because this is
             defined as "non roaming" and thus more likely to be kept
             locally.  For private keys this is desired.  However,
             given that many users copy private keys anyway forth and
             back, using a system roaming services might be better
             than to let them do it manually.  A security conscious
             user will anyway use the registry entry to have better
             control.  */
          if (w32_shgetfolderpath (NULL, CSIDL_APPDATA|CSIDL_FLAG_CREATE,
                                   NULL, 0, path) >= 0)
            {
              char *tmp = xmalloc (strlen (path) + 6 +1);
              strcpy (stpcpy (tmp, path), "\\gnupg");
              dir = tmp;

              /* Try to create the directory if it does not yet exists.  */
              if (access (dir, F_OK))
                w32_try_mkdir (dir);
            }
          else
            dir = GNUPG_DEFAULT_HOMEDIR;
        }
    }
  return dir;
#else/*!HAVE_W32_SYSTEM*/
  return GNUPG_DEFAULT_HOMEDIR;
#endif /*!HAVE_W32_SYSTEM*/
}
Ejemplo n.º 10
0
/* Check whether gpgconf is installed and if so read the gpgconf.ctl
   file. */
static void
check_portable_app (const char *dir)
{
  char *fname;

  fname = xstrconcat (dir, DIRSEP_S "gpgconf.exe", NULL);
  if (access (fname, F_OK))
    log_error ("required binary '%s' is not installed\n", fname);
  else
    {
      strcpy (fname + strlen (fname) - 3, "ctl");
      if (!access (fname, F_OK))
        {
          /* gpgconf.ctl file found.  Record this fact.  */
          w32_portable_app = 1;

          /* FIXME: We should read the file to detect special flags
             and print a warning if we don't understand them.  */
        }
    }
  xfree (fname);
}
Ejemplo n.º 11
0
/* Check whether gpgconf is installed and if so read the gpgconf.ctl
   file. */
static void
check_portable_app (const char *dir)
{
  char *fname;

  fname = xstrconcat (dir, DIRSEP_S "gpgconf.exe", NULL);
  if (!access (fname, F_OK))
    {
      strcpy (fname + strlen (fname) - 3, "ctl");
      if (!access (fname, F_OK))
        {
          /* gpgconf.ctl file found.  Record this fact.  */
          w32_portable_app = 1;
          {
            unsigned int flags;
            log_get_prefix (&flags);
            log_set_prefix (NULL, (flags | GPGRT_LOG_NO_REGISTRY));
          }
          /* FIXME: We should read the file to detect special flags
             and print a warning if we don't understand them  */
        }
    }
  xfree (fname);
}
Ejemplo n.º 12
0
/*! \brief Delete version file Delete version file and its respective
   interval file.  \param dir Dentry of the directory the file is in \param
   vol Volume the file is on \param name Name of the file */
bool version_retent_file(internal_dentry dir, volume vol, char *name)
{
	string path;
	char *dst;

	acquire_dentry(dir);
	zfsd_mutex_lock(&vol->mutex);
	zfsd_mutex_lock(&fh_mutex);

	build_local_path(&path, vol, dir);

	release_dentry(dir);
	zfsd_mutex_unlock(&vol->mutex);
	zfsd_mutex_unlock(&fh_mutex);

	dst = xstrconcat(path.str, DIRECTORY_SEPARATOR, name, NULL);

	version_unlink_version_file(dst);

	free(dst);

	// file is deleted immediately
	return true;
}
Ejemplo n.º 13
0
static void
test_xstrconcat (void)
{
  char *out;

  out = xstrconcat ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
                   "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
                   "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
                   "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
                   "1", "2", "3", "4", "5", "6", "7", NULL);
  if (!out)
    fail (0);

#if __GNUC__ < 4 /* gcc 4.0 has a sentinel attribute.  */
  out = xstrconcat (NULL);
  if (!out)
    fail (1);
#endif
  out = xstrconcat (NULL, NULL);
  if (!out)
    fail (1);
  out = xstrconcat ("", NULL);
  if (!out || *out)
    fail (1);
  xfree (out);

  out = xstrconcat ("", "", NULL);
  if (!out || *out)
    fail (2);
  xfree (out);

  out = xstrconcat ("a", "b", NULL);
  if (!out || strcmp (out, "ab"))
    fail (3);
  xfree (out);
  out = xstrconcat ("a", "b", "c", NULL);
  if (!out || strcmp (out, "abc"))
    fail (3);
  xfree (out);

  out = xstrconcat ("a", "b", "cc", NULL);
  if (!out || strcmp (out, "abcc"))
    fail (4);
  xfree (out);
  out = xstrconcat ("a1", "b1", "c1", NULL);
  if (!out || strcmp (out, "a1b1c1"))
    fail (4);
  xfree (out);

  out = xstrconcat ("", " long b ", "", "--even-longer--", NULL);
  if (!out || strcmp (out, " long b --even-longer--"))
    fail (5);
  xfree (out);

  out = xstrconcat ("", " long b ", "", "--even-longer--", NULL);
  if (!out || strcmp (out, " long b --even-longer--"))
    fail (5);
  xfree (out);
}
Ejemplo n.º 14
0
/*! \brief Create interval file name Create interval file name. \param[out]
   path Complete path of the interval file \param fh Internal file handle */
static void version_build_interval_path(string * path, internal_fh fh)
{
	path->str = xstrconcat(fh->version_path, VERSION_INTERVAL_FILE_ADD, NULL);
	path->len = strlen(path->str);
}
Ejemplo n.º 15
0
/*! \brief Find version files for specified time stamp. Find version files
   that contain data for the specified time stamp, i.e. all newer version
   files that combined together cover the whole file.  \param path Complete
   path of the directory \param name Name of the file \param stamp Time stamp
   of the moment in time \param[out] ino Inode of the first newer version file 
   \param[out] v varray filled with list of versions \see version_item_def */
static int32_t version_browse_dir(char *path, char *name, time_t * stamp,
								  uint32_t * ino, varray * v)
{
	int32_t r;
	unsigned int nl;
	time_t res = 0;
	long current_ino = 0;

	nl = strlen(name);

	ZFS_DIR * dirp = zfs_opendir(path);
	if (dirp == NULL)
		RETURN_INT(errno);

	while (1)
	{

		zfs_dirent entry, *de;
		r = zfs_readdir_r(dirp, &entry, &de);
		if (r > 0) // zfs_readdir_r has failed
		{
			zfs_closedir(dirp);
			RETURN_INT(r);
		}
		else if (r == 0 && de == NULL) // end of list
		{
			if (ino)
			{
				if (res)
					*stamp = res;
				else
				{
					// check modtime if version existed in that time
					struct stat st;
					char *x;
					time_t mtime = 0;

					x = xstrconcat(path, DIRECTORY_SEPARATOR, name, NULL);
					if (!stat(x, &st))
						mtime = st.st_mtime;
					free(x);

					if (mtime && (mtime <= *stamp))
						*ino = current_ino;
					else
						*ino = 0;

					*stamp = 0;
				}
			}
			zfs_closedir(dirp);
			RETURN_INT(ZFS_OK);
		}

		// check if we have our file
		if (!strncmp(de->d_name, name, nl))
		{
			// check if it is current file
			if (strlen(de->d_name) == nl)
			{
				current_ino = de->d_ino;
				if (v)
				{
					version_item item;
					item.stamp = INT32_MAX;
					item.name = xstrdup(de->d_name);
					item.intervals = NULL;
					item.path = NULL;
					VARRAY_PUSH(*v, item, version_item);
				}
				continue;
			}

			// get name stamp
			char *p, *q;
			time_t t;

			p = strchr(de->d_name, VERSION_NAME_SPECIFIER_C);
			if (!p)
				continue;
			*p = '\0';
			p++;

			q = strchr(p, '.');
			if (q)
			{
				*q = '\0';
				q++;
				// skip interval files
				if (*q == 'i')
					continue;
			}
			// get version file stamp
			t = atoi(p);

			// compare timestamps if we are looking for a file
			if (ino && (t >= *stamp) && (!res || (t < res)))
			{
				// check modtime if version existed in that time
				// in fact, this should be valid only for one file

				struct stat st;
				char *x;
				time_t mtime = 0;

				x = xstrconcat(path, DIRECTORY_SEPARATOR, de->d_name,
							   VERSION_NAME_SPECIFIER_S, p, NULL);
				if (!stat(x, &st))
					mtime = st.st_mtime;
				free(x);

				if (mtime && (mtime <= *stamp))
				{
					res = t;
					*ino = de->d_ino;
				}
			}

			// add into varray if we want list of version files
			if (v && (t > *stamp))
			{
				version_item item;
				*(--p) = VERSION_NAME_SPECIFIER_C;
				item.stamp = t;
				item.name = xstrdup(de->d_name);
				item.intervals = NULL;
				item.path = NULL;
				VARRAY_PUSH(*v, item, version_item);
			}
		}
	}
}
Ejemplo n.º 16
0
/****************
 * Copy the option file skeleton for NAME to the given directory.
 * Returns true if the new option file has any option.
 */
static int
copy_options_file (const char *destdir, const char *name)
{
  const char *datadir = gnupg_datadir ();
  char *fname;
  FILE *src, *dst;
  int linefeeds=0;
  int c;
  mode_t oldmask;
  int esc = 0;
  int any_option = 0;

  if (opt.dry_run)
    return 0;

  fname = xstrconcat (datadir, DIRSEP_S, name, "-conf", SKELEXT, NULL);
  src = fopen (fname, "r");
  if (src && is_secured_file (fileno (src)))
    {
      fclose (src);
      src = NULL;
      gpg_err_set_errno (EPERM);
    }
  if (!src)
    {
      log_info (_("can't open '%s': %s\n"), fname, strerror(errno));
      xfree(fname);
      return 0;
    }
  xfree (fname);
  fname = xstrconcat (destdir, DIRSEP_S, name, EXTSEP_S, "conf", NULL);

  oldmask = umask (077);
  if (is_secured_filename (fname))
    {
      dst = NULL;
      gpg_err_set_errno (EPERM);
    }
  else
    dst = fopen( fname, "w" );
  umask (oldmask);

  if (!dst)
    {
      log_info (_("can't create '%s': %s\n"), fname, strerror(errno) );
      fclose (src);
      xfree (fname);
      return 0;
    }

  while ((c = getc (src)) != EOF)
    {
      if (linefeeds < 3)
        {
          if (c == '\n')
            linefeeds++;
	}
      else
        {
          putc (c, dst);
          if (c== '\n')
            esc = 1;
          else if (esc == 1)
            {
              if (c == ' ' || c == '\t')
                ;
              else if (c == '#')
                esc = 2;
              else
                any_option = 1;
            }
        }
    }

  fclose (dst);
  fclose (src);

  log_info (_("new configuration file '%s' created\n"), fname);
  xfree (fname);
  return any_option;
}
Ejemplo n.º 17
0
/*
 * Make an output filename for the inputfile INAME.
 * Returns an IOBUF and an errorcode
 * Mode 0 = use ".gpg"
 *	1 = use ".asc"
 *	2 = use ".sig"
 *      3 = use ".rev"
 *
 * If INP_FD is not -1 the function simply creates an IOBUF for that
 * file descriptor and ignore INAME and MODE.  Note that INP_FD won't
 * be closed if the returned IOBUF is closed.  With RESTRICTEDPERM a
 * file will be created with mode 700 if possible.
 */
int
open_outfile (int inp_fd, const char *iname, int mode, int restrictedperm,
              iobuf_t *a)
{
  int rc = 0;

  *a = NULL;
  if (inp_fd != -1)
    {
      char xname[64];

      *a = iobuf_fdopen_nc (inp_fd, "wb");
      if (!*a)
        {
          rc = gpg_error_from_syserror ();
          snprintf (xname, sizeof xname, "[fd %d]", inp_fd);
          log_error (_("can't open '%s': %s\n"), xname, gpg_strerror (rc));
        }
      else if (opt.verbose)
        {
          snprintf (xname, sizeof xname, "[fd %d]", inp_fd);
          log_info (_("writing to '%s'\n"), xname);
        }
    }
  else if (iobuf_is_pipe_filename (iname) && !opt.outfile)
    {
      *a = iobuf_create (NULL, 0);
      if ( !*a )
        {
          rc = gpg_error_from_syserror ();
          log_error (_("can't open '%s': %s\n"), "[stdout]", strerror(errno) );
        }
      else if ( opt.verbose )
        log_info (_("writing to stdout\n"));
    }
  else
    {
      char *buf = NULL;
      const char *name;

      if (opt.dry_run)
        name = NAME_OF_DEV_NULL;
      else if (opt.outfile)
        name = opt.outfile;
      else
        {
#ifdef USE_ONLY_8DOT3
          if (opt.mangle_dos_filenames)
            {
              /* It is quite common for DOS systems to have only one
                 dot in a filename.  If we have something like this,
                 we simple replace the suffix except in cases where
                 the suffix is larger than 3 characters and not the
                 same as the new one.  We don't map the filenames to
                 8.3 because this is a duty of the file system.  */
              char *dot;
              const char *newsfx;

              newsfx = (mode==1 ? ".asc" :
                        mode==2 ? ".sig" :
                        mode==3 ? ".rev" : ".gpg");

              buf = xmalloc (strlen(iname)+4+1);
              strcpy (buf, iname);
              dot = strchr (buf, '.' );
              if ( dot && dot > buf && dot[1] && strlen(dot) <= 4
                   && CMP_FILENAME (newsfx, dot) )
                strcpy (dot, newsfx);
              else if (dot && !dot[1]) /* Do not duplicate a dot.  */
                strcpy (dot, newsfx+1);
              else
                strcat (buf, newsfx);
            }
          if (!buf)
#endif /* USE_ONLY_8DOT3 */
            {
              buf = xstrconcat (iname,
                                (mode==1 ? EXTSEP_S "asc" :
                                 mode==2 ? EXTSEP_S "sig" :
                                 mode==3 ? EXTSEP_S "rev" :
                                 /*     */ EXTSEP_S GPGEXT_GPG),
                                NULL);
            }
          name = buf;
        }

      rc = 0;
      while ( !overwrite_filep (name) )
        {
          char *tmp = ask_outfile_name (NULL, 0);
          if ( !tmp || !*tmp )
            {
              xfree (tmp);
              rc = gpg_error (GPG_ERR_EEXIST);
              break;
            }
          xfree (buf);
          name = buf = tmp;
        }

      if ( !rc )
        {
          if (is_secured_filename (name) )
            {
              *a = NULL;
              gpg_err_set_errno (EPERM);
            }
          else
            *a = iobuf_create (name, restrictedperm);
          if (!*a)
            {
              rc = gpg_error_from_syserror ();
              log_error(_("can't create '%s': %s\n"), name, strerror(errno) );
            }
          else if( opt.verbose )
            log_info (_("writing to '%s'\n"), name );
        }
      xfree(buf);
    }

  if (*a)
    iobuf_ioctl (*a, IOBUF_IOCTL_NO_CACHE, 1, NULL);

  return rc;
}
Ejemplo n.º 18
0
/*! \brief Find first newer version Find oldest version of the file that is
   newer than the specified time stamp.  \param dir Complete path of the
   directory \param[in,out] name File name; contains version suffix on return
   \param stamp Time stamp */
int32_t version_find_version(char *dir, string * name, time_t stamp)
{
	char *sname;
	char *p;
	uint32_t ino = 0;
	struct stat st;
	char *x;
	char ver[VERSION_MAX_SPECIFIER_LENGTH];

	sname = xstrdup(name->str);
	p = strchr(sname, VERSION_NAME_SPECIFIER_C);
	if (p)
		*p = '\0';

	// check for exact version file
	snprintf(ver, sizeof(ver), "%ld", stamp);
	x = xstrconcat(dir, DIRECTORY_SEPARATOR, sname,
				   VERSION_NAME_SPECIFIER_S, ver, NULL);
	if (!stat(x, &st))
	{
		free(x);
		// name is allocated in kernel call via FUSE
		// free (name->str);
		name->str = xstrconcat(sname, VERSION_NAME_SPECIFIER_S, ver, NULL);;
		name->len = strlen(name->str);
		free(sname);

		RETURN_INT(ZFS_OK);
	}
	free(x);

	// look for first newer
	version_browse_dir(dir, sname, &stamp, &ino, NULL);
	message(LOG_DEBUG, FACILITY_VERSION, "Using stamp=%d, sname=%s, ino=%u\n",
			stamp, sname, ino);

	if (stamp > 0)
	{
		// found version file
		free(name->str);
		snprintf(ver, sizeof(ver), "%ld", stamp);
		name->str = xstrconcat(sname, VERSION_NAME_SPECIFIER_S, ver, NULL);
		name->len = strlen(name->str);
	}
	else if (ino > 0)
	{
		// found current file
		p = strchr(name->str, VERSION_NAME_SPECIFIER_C);
		if (p)
			*p = '\0';
		name->len = strlen(name->str);
	}
	else
	{
		free(sname);
		RETURN_INT(ENOENT);
	}

	free(sname);

	RETURN_INT(ZFS_OK);
}
Ejemplo n.º 19
0
/* Return the name of the cache directory.  The name is allocated in a
   static area on the first use.  Windows only: If the directory does
   not exist it is created.  */
const char *
gnupg_cachedir (void)
{
#ifdef HAVE_W32_SYSTEM
  static const char *dir;

  if (!dir)
    {
      const char *rdir;

      rdir = w32_rootdir ();
      if (w32_portable_app)
        {
          dir = xstrconcat (rdir,
                            DIRSEP_S, "var",
                            DIRSEP_S, "cache",
                            DIRSEP_S, "gnupg", NULL);
        }
      else
        {
          char path[MAX_PATH];
          const char *s1[] = { "GNU", "cache", "gnupg", NULL };
          int s1_len;
          const char **comp;

          s1_len = 0;
          for (comp = s1; *comp; comp++)
            s1_len += 1 + strlen (*comp);

          if (w32_shgetfolderpath (NULL, CSIDL_LOCAL_APPDATA|CSIDL_FLAG_CREATE,
                                   NULL, 0, path) >= 0)
            {
              char *tmp = xmalloc (strlen (path) + s1_len + 1);
              char *p;

              p = stpcpy (tmp, path);
              for (comp = s1; *comp; comp++)
                {
                  p = stpcpy (p, "\\");
                  p = stpcpy (p, *comp);

                  if (access (tmp, F_OK))
                    w32_try_mkdir (tmp);
                }

              dir = tmp;
            }
          else
            {
              dir = "c:\\temp\\cache\\gnupg";
#ifdef HAVE_W32CE_SYSTEM
              dir += 2;
              w32_try_mkdir ("\\temp\\cache");
              w32_try_mkdir ("\\temp\\cache\\gnupg");
#endif
            }
        }
    }
  return dir;
#else /*!HAVE_W32_SYSTEM*/
  return GNUPG_LOCALSTATEDIR "/cache/" PACKAGE_NAME;
#endif /*!HAVE_W32_SYSTEM*/
}
Ejemplo n.º 20
0
/*! \brief Create list of intervals for a file version Create list of
   intervals together with version files these intervals are stored in that
   create the whole content of a file version. List is created from interval
   files during file open. Result is stored in the internal file handle.
   \param dentry Dentry of the file \param vol Volume the file in on */
int32_t version_build_intervals(internal_dentry dentry, volume vol)
{
	time_t stamp;
	varray v;
	char *sname;
	char *p;
	version_item *list;
	unsigned int n, m;
	unsigned int i, j;
	string dpath;
	bool r;

	r = version_load_interval_tree(dentry->fh);
	if (!r)
		RETURN_INT(ZFS_OK);

	// parse version file name
	sname = xstrdup(dentry->name.str);
	p = strchr(sname, VERSION_NAME_SPECIFIER_C);
	if (!p)
	{
		free(sname);
		RETURN_INT(ENOENT);
	}

	*p = '\0';
	stamp = atoi(p + 1);

	// get list of version files that newer than timestamp
	zfsd_mutex_lock(&dentry->parent->fh->mutex);
	build_local_path(&dpath, vol, dentry->parent);
	zfsd_mutex_unlock(&dentry->parent->fh->mutex);

	varray_create(&v, sizeof(version_item), 1);

	version_browse_dir(dpath.str, sname, &stamp, NULL, &v);

	free(sname);

	n = VARRAY_USED(v);
	list = (version_item *) xmalloc(n * sizeof(version_item));

	for (i = 0; i < n; i++)
	{
		list[i] = VARRAY_ACCESS(v, i, version_item);
		list[i].path =
			xstrconcat(dpath.str, DIRECTORY_SEPARATOR, list[i].name, NULL);
	}

	varray_destroy(&v);
	free(dpath.str);

	// sort the list
	qsort(list, n, sizeof(version_item), comp_version_items);

	// get intervals for version files in the list
	for (i = 0; i < n; i++)
	{
		// read
		int fd;
		char *ival;

		if (!list[i].path)
			continue;

		ival = xstrconcat(list[i].path, VERSION_INTERVAL_FILE_ADD, NULL);
		fd = open(ival, O_RDONLY);

		free(ival);

		if (fd > 0)
		{
			// read interval file
			struct stat st;

			list[i].intervals = interval_tree_create(1, NULL);

			if (fstat(fd, &st) < 0)
			{
				CLEAR_VERSION_ITEM(list[i]);
			}
			else if (!interval_tree_read
					 (list[i].intervals, fd, st.st_size / sizeof(interval)))
				CLEAR_VERSION_ITEM(list[i]);

			close(fd);
		}
		else if (errno == ENOENT)
		{
			// complete file
			i++;
			break;
		}
		// invalid version file
		else
			CLEAR_VERSION_ITEM(list[i]);
	}

	// delete all redundant intervals
	m = i;
	for (j = i + 1; j < n; j++)
		CLEAR_VERSION_ITEM(list[j]);

	dentry->fh->version_list = list;
	dentry->fh->version_list_length = m;

	RETURN_INT(ZFS_OK);
}