Пример #1
0
int jjfs_release(const char *path, struct fuse_file_info *fi) {
  jjfs_cache_entry *file = jjfs_cache_lookup_path(path);
  int fd = fi->fh;
  jjfs_transfer *t;
  JJFS_GET_TRANS(t, fd);

  close(fd);

  DIR *d = opendir(jjfs_get_staging_dir());
  unlinkat(dirfd(d), file->file->name, 0);
  JJFS_FREE_TRANS(t);
  return 0;
}
Пример #2
0
int journal::init(int dfd)
{
#if !HAVE_FSTITCH
	if(fs_fd >= 0)
		return -EBUSY;
	fs_fd = openat(dfd, ".fsync_fs", O_RDWR | O_CREAT | O_TRUNC, 0600);
	if(fs_fd < 0)
		return fs_fd;
	unlinkat(dfd, ".fsync_fs", 0);
	memset(fd_tv, 0, sizeof(fd_tv));
#endif
	return 0;
}
Пример #3
0
static int fd_copy_regular(int df, const char *from, const struct stat *st, int dt, const char *to) {
        _cleanup_close_ int fdf = -1, fdt = -1;
        int r, q;

        assert(from);
        assert(st);
        assert(to);

        fdf = openat(df, from, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
        if (fdf < 0)
                return -errno;

        fdt = openat(dt, to, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, st->st_mode & 07777);
        if (fdt < 0)
                return -errno;

        r = copy_bytes(fdf, fdt, (off_t) -1, true);
        if (r < 0) {
                unlinkat(dt, to, 0);
                return r;
        }

        if (fchown(fdt, st->st_uid, st->st_gid) < 0)
                r = -errno;

        if (fchmod(fdt, st->st_mode & 07777) < 0)
                r = -errno;

        q = close(fdt);
        fdt = -1;

        if (q < 0) {
                r = -errno;
                unlinkat(dt, to, 0);
        }

        return r;
}
Пример #4
0
int btree_dtable::create(int dfd, const char * file, const params & config, dtable::iter * source, const ktable * shadow)
{
	int bt_dfd, r;
	params base_config;
	dtable * base_dtable;
	const dtable_factory * base = dtable_factory::lookup(config, "base");
	if(!base)
		return -ENOENT;
	if(!config.get("base_config", &base_config, params()))
		return -EINVAL;
	if(!base->indexed_access(base_config))
		return -ENOSYS;
	
	if(!source_shadow_ok(source, shadow))
		return -EINVAL;
	
	r = mkdirat(dfd, file, 0755);
	if(r < 0)
		return r;
	bt_dfd = openat(dfd, file, O_RDONLY);
	if(bt_dfd < 0)
		goto fail_open;
	
	r = base->create(bt_dfd, "base", base_config, source, shadow);
	if(r < 0)
		goto fail_create;
	
	base_dtable = base->open(bt_dfd, "base", base_config, NULL);
	if(!base_dtable)
		goto fail_reopen;
	
	r = write_btree(bt_dfd, "btree", base_dtable);
	if(r < 0)
		goto fail_write;
	
	base_dtable->destroy();
	
	close(bt_dfd);
	return 0;
	
fail_write:
	base_dtable->destroy();
fail_reopen:
	util::rm_r(bt_dfd, "base");
fail_create:
	close(bt_dfd);
fail_open:
	unlinkat(dfd, file, AT_REMOVEDIR);
	return (r < 0) ? r : -1;
}
Пример #5
0
/**
 * Remove the tmp file if any kind of critical error came up
 */
void MigrateFile::removeTmpOnErr(void)
{
   int unlinkRes = unlinkat(this->dirFD, this->tmpName.c_str(), 0);
   if (unlinkRes)
   {
      if (errno != ENOENT)
      {
         std::string tmpPath = this->dirPath + "/" + this->tmpName;
         std::cerr << "Unlinking of the tmp file (" << tmpPath << ") failed. Aborting. " <<
            "(" << System::getErrString() << ")" << std::endl;
         throw ModeMigrateException("Unexpected migration errror!");
      }
   }
}
Пример #6
0
int sys_lremovexattr(const char *path, const char *name)
{
	int attrdirfd;
	int ret;

	if ((attrdirfd = attropen(path, ".", O_RDONLY)) < 0)
		return -1;

	ret = unlinkat(attrdirfd, name, 0);

	close(attrdirfd);

	return ret;
}
Пример #7
0
void
pkg_delete_dir(struct pkg *pkg, struct pkg_dir *dir)
{
	const char *path;
	pkg_open_root_fd(pkg);

	path = pkg_dir_path(dir);
	/* remove the first / */
	path++;

	if (unlinkat(pkg->rootfd, path, AT_REMOVEDIR) == -1 &&
	    errno != ENOTEMPTY && errno != EBUSY)
		pkg_emit_errno("rmdir", pkg_dir_path(dir));
}
Пример #8
0
/**
 * -delete action.
 */
bool eval_delete(const struct expr *expr, struct eval_state *state) {
	struct BFTW *ftwbuf = state->ftwbuf;

	int flag = 0;
	if (ftwbuf->typeflag == BFTW_DIR) {
		flag |= AT_REMOVEDIR;
	}

	if (unlinkat(ftwbuf->at_fd, ftwbuf->at_path, flag) != 0) {
		eval_error(state);
		return false;
	}

	return true;
}
Пример #9
0
static gboolean
prune_commitpartial_file (OstreeRepo    *repo,
                          const char    *checksum,
                          GCancellable  *cancellable,
                          GError       **error)
{
  g_autofree char *path = _ostree_get_commitpartial_path (checksum);
  if (unlinkat (repo->repo_dir_fd, path, 0) != 0)
    {
      if (errno != ENOENT)
        return glnx_throw_errno_prefix (error, "unlinkat");
    }

  return TRUE;
}
Пример #10
0
gboolean
ot_ensure_unlinked_at (int dfd,
                       const char *path,
                       GError **error)
{
  if (unlinkat (dfd, path, 0) != 0)
    {
      if (G_UNLIKELY (errno != ENOENT))
        {
          glnx_set_error_from_errno (error);
          return FALSE;
        }
    }
  return TRUE;
}
Пример #11
0
void close_image(struct cr_img *img)
{
	if (lazy_image(img)) {
		/*
		 * Remove the image file if it's there so that
		 * subsequent restore doesn't read wrong or fake
		 * data from it.
		 */
		unlinkat(get_service_fd(IMG_FD_OFF), img->path, 0);
		xfree(img->path);
	} else if (!empty_image(img))
		bclose(&img->_x);

	xfree(img);
}
Пример #12
0
static gboolean
_ostree_repo_prune_tmp (OstreeRepo *self,
                        GCancellable *cancellable,
                        GError **error)
{
  if (self->cache_dir_fd == -1)
    return TRUE;

  g_auto(GLnxDirFdIterator) dfd_iter = { 0, };
  gboolean exists;
  if (!ot_dfd_iter_init_allow_noent (self->cache_dir_fd, _OSTREE_SUMMARY_CACHE_DIR,
                                     &dfd_iter, &exists, error))
    return FALSE;
  /* Note early return */
  if (!exists)
    return TRUE;

  while (TRUE)
    {
      size_t len;
      gboolean has_sig_suffix = FALSE;
      struct dirent *dent;

      if (!glnx_dirfd_iterator_next_dent (&dfd_iter, &dent, cancellable, error))
        return FALSE;
      if (dent == NULL)
        break;

      len = strlen (dent->d_name);
      if (len > 4 && g_strcmp0 (dent->d_name + len - 4, ".sig") == 0)
        {
          has_sig_suffix = TRUE;
          dent->d_name[len - 4] = '\0';
        }

      if (!g_hash_table_contains (self->remotes, dent->d_name))
        {
          /* Restore the previous value to get the file name.  */
          if (has_sig_suffix)
            dent->d_name[len - 4] = '.';

          if (unlinkat (dfd_iter.fd, dent->d_name, 0) < 0)
            return glnx_throw_errno_prefix (error, "unlinkat");
        }
    }

  return TRUE;
}
Пример #13
0
static int remove_boot_efi(const char *esp_path) {
        char *p;
        _cleanup_closedir_ DIR *d = NULL;
        struct dirent *de;
        int r, c = 0;

        p = strjoina(esp_path, "/EFI/Boot");
        d = opendir(p);
        if (!d) {
                if (errno == ENOENT)
                        return 0;

                return log_error_errno(errno, "Failed to open directory \"%s\": %m", p);
        }

        while ((de = readdir(d))) {
                _cleanup_close_ int fd = -1;
                _cleanup_free_ char *v = NULL;

                if (de->d_name[0] == '.')
                        continue;

                if (!endswith_no_case(de->d_name, ".efi"))
                        continue;

                if (!startswith_no_case(de->d_name, "Boot"))
                        continue;

                fd = openat(dirfd(d), de->d_name, O_RDONLY|O_CLOEXEC);
                if (fd < 0)
                        return log_error_errno(errno, "Failed to open \"%s/%s\" for reading: %m", p, de->d_name);

                r = get_file_version(fd, &v);
                if (r < 0)
                        return r;
                if (r > 0 && startswith(v, "systemd-boot ")) {
                        r = unlinkat(dirfd(d), de->d_name, 0);
                        if (r < 0)
                                return log_error_errno(errno, "Failed to remove \"%s/%s\": %m", p, de->d_name);

                        log_info("Removed \"%s/%s\".", p, de->d_name);
                }

                c++;
        }

        return c;
}
Пример #14
0
CAMLprim value caml_extunix_unlinkat(value v_dirfd, value v_name, value v_flags)
{
  CAMLparam3(v_dirfd, v_name, v_flags);
  char* p = caml_stat_alloc(caml_string_length(v_name) + 1);
  int ret = 0;
  int flags = caml_convert_flag_list(v_flags, at_flags_table);
  flags &= AT_REMOVEDIR;  /* only allowed flag here */

  strcpy(p, String_val(v_name));
  caml_enter_blocking_section();
  ret = unlinkat(Int_val(v_dirfd), p, flags);
  caml_leave_blocking_section();
  caml_stat_free(p);
  if (ret != 0) uerror("unlinkat", v_name);
  CAMLreturn(Val_unit);
}
Пример #15
0
static int
callback_unlink (const char *path)
{
  struct stat stbuf;
  path = ENSURE_RELPATH (path);

  if (fstatat (basefd, path, &stbuf, AT_SYMLINK_NOFOLLOW) == 0)
    {
      if (!S_ISDIR (stbuf.st_mode))
	devino_set_remove (stbuf.st_dev, stbuf.st_ino);
    }

  if (unlinkat (basefd, path, 0) == -1)
    return -errno;
  return 0;
}
Пример #16
0
int
solaris_removexattr(const char *path,
                    const char* key)
{
    int ret = -1;
    int attrfd = attropen (path, ".", O_RDONLY, 0);
    if (attrfd >= 0) {
        ret = unlinkat (attrfd, key, 0);
        close (attrfd);
    } else {
        if (errno == ENOENT)
            errno = ENODATA;
        return -1;
    }

    return ret;
}
Пример #17
0
int open_image_at(int dfd, int type, unsigned long flags, ...)
{
	char path[PATH_MAX];
	va_list args;
	int ret;

	va_start(args, flags);
	vsnprintf(path, PATH_MAX, fdset_template[type].fmt, args);
	va_end(args);

	if (flags & O_EXCL) {
		ret = unlinkat(dfd, path, 0);
		if (ret && errno != ENOENT) {
			pr_perror("Unable to unlink %s", path);
			goto err;
		}
	}

	ret = openat(dfd, path, flags, CR_FD_PERM);
	if (ret < 0) {
		pr_perror("Unable to open %s", path);
		goto err;
	}

	if (fdset_template[type].magic == RAW_IMAGE_MAGIC)
		goto skip_magic;

	if (flags == O_RDONLY) {
		u32 magic;

		if (read_img(ret, &magic) < 0)
			goto err;
		if (magic != fdset_template[type].magic) {
			pr_err("Magic doesn't match for %s\n", path);
			goto err;
		}
	} else {
		if (write_img(ret, &fdset_template[type].magic))
			goto err;
	}

skip_magic:
	return ret;
err:
	return -1;
}
Пример #18
0
/* move any old watches directory out of the way, and then restore
 * the watches
 */
void udev_watch_restore(struct udev *udev)
{
        if (inotify_fd < 0)
                return;

        if (rename("/run/udev/watch", "/run/udev/watch.old") == 0) {
                DIR *dir;
                struct dirent *ent;

                dir = opendir("/run/udev/watch.old");
                if (dir == NULL) {
                        log_error("unable to open old watches dir /run/udev/watch.old; old watches will not be restored: %m");
                        return;
                }

                for (ent = readdir(dir); ent != NULL; ent = readdir(dir)) {
                        char device[UTIL_PATH_SIZE];
                        ssize_t len;
                        struct udev_device *dev;

                        if (ent->d_name[0] == '.')
                                continue;

                        len = readlinkat(dirfd(dir), ent->d_name, device, sizeof(device));
                        if (len <= 0 || len == (ssize_t)sizeof(device))
                                goto unlink;
                        device[len] = '\0';

                        dev = udev_device_new_from_device_id(udev, device);
                        if (dev == NULL)
                                goto unlink;

                        log_debug("restoring old watch on '%s'", udev_device_get_devnode(dev));
                        udev_watch_begin(udev, dev);
                        udev_device_unref(dev);
unlink:
                        unlinkat(dirfd(dir), ent->d_name, 0);
                }

                closedir(dir);
                rmdir("/run/udev/watch.old");

        } else if (errno != ENOENT) {
                log_error("unable to move watches dir /run/udev/watch; old watches will not be restored: %m");
        }
}
Пример #19
0
int
destroy_todo(char *n, day_t day, tm_t *date)
{
	int dfd;
	if (date) {
		dfd = opendate(date);
	} else {
		dfd = openday(day);
	}
	int tdfd = opentodos(dfd);
	int uaret = unlinkat(tdfd, n, 0);
	if (uaret == -1) {
		return (DESTROY_TD_EEXIST);
	}
	close(dfd);
	close(tdfd);
	return (0);
}
Пример #20
0
static ssize_t xattr_fremovexattr(int fd, const char *name, int options)
{
  int xfd, status;
    /* XXX should check that name does not have / characters in it */
    if (!(options == 0 || options == XATTR_XATTR_NOFOLLOW)) {
        return -1;
    }
    if (options & XATTR_XATTR_NOFOLLOW) {
        return -1;
    }
    xfd = openat(fd, ".", O_XATTR, 0644);
    if (xfd == -1) {
    return -1;
    }
    status = unlinkat(xfd, name, 0);
    close(xfd);
    return status;
}
Пример #21
0
/* Remove the file system object specified by ENT.  IS_DIR specifies
   whether it is expected to be a directory or non-directory.
   Return RM_OK upon success, else RM_ERROR.  */
static enum RM_status
excise (FTS *fts, FTSENT *ent, struct rm_options const *x, bool is_dir)
{
  int flag = is_dir ? AT_REMOVEDIR : 0;
  if (unlinkat (fts->fts_cwd_fd, ent->fts_accpath, flag) == 0)
    {
      if (x->verbose)
        {
          printf ((is_dir
                   ? _("removed directory: %s\n")
                   : _("removed %s\n")), quote (ent->fts_path));
        }
      return RM_OK;
    }

  /* The unlinkat from kernels like linux-2.6.32 reports EROFS even for
     nonexistent files.  When the file is indeed missing, map that to ENOENT,
     so that rm -f ignores it, as required.  Even without -f, this is useful
     because it makes rm print the more precise diagnostic.  */
  if (errno == EROFS)
    {
      struct stat st;
      if ( ! (lstatat (fts->fts_cwd_fd, ent->fts_accpath, &st)
                       && errno == ENOENT))
        errno = EROFS;
    }

  if (ignorable_missing (x, errno))
    return RM_OK;

  /* When failing to rmdir an unreadable directory, we see errno values
     like EISDIR or ENOTDIR (or, on Solaris 10, EEXIST), but they would be
     meaningless in a diagnostic.  When that happens and the errno value
     from the failed open is EPERM or EACCES, use the earlier, more
     descriptive errno value.  */
  if (ent->fts_info == FTS_DNR
      && (errno == ENOTEMPTY || errno == EISDIR || errno == ENOTDIR
          || errno == EEXIST)
      && (ent->fts_errno == EPERM || ent->fts_errno == EACCES))
    errno = ent->fts_errno;
  error (0, errno, _("cannot remove %s"), quote (ent->fts_path));
  mark_ancestor_dirs (ent);
  return RM_ERROR;
}
Пример #22
0
void test_create_symlink_at()
{
  char *symlink_filename = alloc_filename("symlink");
  int dir_fd = get_dir_fd(".");
  const char *dest_path = "dest_path";
  t_check_zero(symlinkat(dest_path, dir_fd, symlink_filename));

  char buf[100];
  int got;
  got = readlinkat(dir_fd, symlink_filename, buf, sizeof(buf));
  t_check(got >= 0);
  assert(got == strlen(dest_path));
  buf[got] = 0;
  assert(strcmp(buf, dest_path) == 0);

  t_check_zero(unlinkat(dir_fd, symlink_filename, 0));
  close(dir_fd);
  free(symlink_filename);
}
Пример #23
0
Файл: clean.c Проект: grembo/pkg
static int
delete_dellist(int fd, const char *cachedir,  dl_list *dl, int total)
{
	struct stat st;
	int retcode = EX_OK;
	int flag = 0;
	unsigned int count = 0, processed = 0;
	char *file, *relpath;

	count = kv_size(*dl);
	progressbar_start("Deleting files");
	for (int i = 0; i < kv_size(*dl); i++) {
		flag = 0;
		relpath = file = kv_A(*dl, i);
		relpath += strlen(cachedir) + 1;
		if (fstatat(fd, relpath, &st, AT_SYMLINK_NOFOLLOW) == -1) {
			++processed;
			progressbar_tick(processed, total);
			warn("can't stat %s", file);
			continue;
		}
		if (S_ISDIR(st.st_mode))
			flag = AT_REMOVEDIR;
		if (unlinkat(fd, relpath, flag) == -1) {
			warn("unlink(%s)", file);
			retcode = EX_SOFTWARE;
		}
		free(file);
		kv_A(*dl, i) = NULL;
		++processed;
		progressbar_tick(processed, total);
	}
	progressbar_tick(processed, total);

	if (!quiet) {
		if (retcode == EX_OK)
			printf("All done\n");
		else
			printf("%d package%s could not be deleted\n",
			      count, count > 1 ? "s" : "");
	}
	return (retcode);
}
Пример #24
0
void
rpmostree_bwrap_unref (RpmOstreeBwrap *bwrap)
{
  bwrap->refcount--;
  if (bwrap->refcount > 0)
    return;

  if (bwrap->rofiles_mnt)
    {
      g_autoptr(GError) tmp_error = NULL;
      const char *fusermount_argv[] = { "fusermount", "-u", bwrap->rofiles_mnt, NULL};
      int estatus;

      if (!g_spawn_sync (NULL, (char**)fusermount_argv, NULL, G_SPAWN_SEARCH_PATH,
                         NULL, NULL, NULL, NULL, &estatus, &tmp_error))
        {
          g_prefix_error (&tmp_error, "Executing fusermount: ");
          goto out;
        }
      if (!g_spawn_check_exit_status (estatus, &tmp_error))
        {
          g_prefix_error (&tmp_error, "Executing fusermount: ");
          goto out;
        }

      (void) unlinkat (AT_FDCWD, bwrap->rofiles_mnt, AT_REMOVEDIR);
    out:
      /* We don't want a failure to unmount to be fatal, so all we do here
       * is log.  Though in practice what we *really* want is for the
       * fusermount to be in the bwrap namespace, and hence tied by the
       * kernel to the lifecycle of the container.  This would require
       * special casing for somehow doing FUSE mounts in bwrap.  Which
       * would be hard because NO_NEW_PRIVS turns off the setuid bits for
       * fuse.
       */
      if (tmp_error)
        sd_journal_print (LOG_WARNING, "%s", tmp_error->message);
    }

  g_ptr_array_unref (bwrap->argv);
  g_free (bwrap->rofiles_mnt);
  g_free (bwrap);
}
Пример #25
0
void
pkg_delete_file(struct pkg *pkg, struct pkg_file *file, unsigned force)
{
	const char *sum = pkg_file_cksum(file);
	const char *path;
	struct stat st;
	char sha256[SHA256_DIGEST_LENGTH * 2 + 1];

	pkg_open_root_fd(pkg);

	path = pkg_file_path(file);
	path++;

	/* Regular files and links */
	/* check sha256 */
	if (!force && sum[0] != '\0') {
		if (fstatat(pkg->rootfd, path, &st, AT_SYMLINK_NOFOLLOW) == -1) {
			pkg_emit_error("cannot stat %s: %s", path, strerror(errno));
			return;
		}
		if (S_ISLNK(st.st_mode)) {
			if (pkg_symlink_cksumat(pkg->rootfd, path, NULL,
			    sha256) != EPKG_OK)
				return;
		}
		else {
			if (sha256_fileat(pkg->rootfd, path, sha256) != EPKG_OK)
				return;
		}
		if (strcmp(sha256, sum)) {
			pkg_emit_error("%s fails original SHA256 "
				"checksum, not removing", path);
			return;
		}
	}

	if (unlinkat(pkg->rootfd, path, 0) == -1) {
		if (force < 2)
			pkg_emit_errno("unlinkat", path);
		return;
	}
}
/*
 * Like symlinkat() but overwrites (atomically) an existing
 * symlink.
 */
static gboolean
symlink_at_replace (const char    *oldpath,
                    int            parent_dfd,
                    const char    *newpath,
                    GCancellable  *cancellable,
                    GError       **error)
{
  gboolean ret = FALSE;
  int res;
  /* Possibly in the future generate a temporary random name here,
   * would need to move "generate a temporary name" code into
   * libglnx or glib?
   */
  const char *temppath = glnx_strjoina (newpath, ".tmp");

  /* Clean up any stale temporary links */ 
  (void) unlinkat (parent_dfd, temppath, 0);

  /* Create the temp link */ 
  do
    res = symlinkat (oldpath, parent_dfd, temppath);
  while (G_UNLIKELY (res == -1 && errno == EINTR));
  if (res == -1)
    {
      glnx_set_error_from_errno (error);
      goto out;
    }

  /* Rename it into place */ 
  do
    res = renameat (parent_dfd, temppath, parent_dfd, newpath);
  while (G_UNLIKELY (res == -1 && errno == EINTR));
  if (res == -1)
    {
      glnx_set_error_from_errno (error);
      goto out;
    }

  ret = TRUE;
 out:
  return ret;
}
Пример #27
0
int simple_stable::create(int dfd, const char * name, const params & config, dtype::ctype key_type)
{
	int md_dfd, r;
	params meta_config, data_config;
	const dtable_factory * meta = dtable_factory::lookup(config, "meta");
	const ctable_factory * data = ctable_factory::lookup(config, "data");
	if(!meta || !data)
		return -ENOENT;
	if(!config.get("meta_config", &meta_config, params()))
		return -EINVAL;
	if(!config.get("data_config", &data_config, params()))
		return -EINVAL;
	r = mkdirat(dfd, name, 0755);
	if(r < 0)
		return r;
	md_dfd = openat(dfd, name, O_RDONLY);
	if(md_dfd < 0)
	{
		r = md_dfd;
		goto fail_open;
	}
	
	/* the metadata is keyed by named properties (strings) */
	r = meta->create(md_dfd, "st_meta", meta_config, dtype::STRING);
	if(r < 0)
		goto fail_meta;
	r = data->create(md_dfd, "st_data", data_config, key_type);
	if(r < 0)
		goto fail_data;
	
	close(md_dfd);
	return 0;
	
fail_data:
	util::rm_r(md_dfd, "st_meta");
fail_meta:
	close(md_dfd);
fail_open:
	unlinkat(dfd, name, AT_REMOVEDIR);
	return r;
}
Пример #28
0
int rmFullDir(const char *name) {
  struct dirent *cur;
  int fd;
  DIR *dir;

  dir = opendir(name);
  if (dir == NULL) return -1;

  fd = open(name, O_RDONLY);
  if (fd == -1) return -1;

  while ((cur = readdir(dir)) != NULL) {
    if (cur->d_type == DT_REG) {
      if (unlinkat(fd,cur->d_name,0) == -1) return -1;
    }
  }

  close(fd);
  closedir(dir);
  return rmdir(name);
}
Пример #29
0
/* Remove the file system object specified by ENT.  IS_DIR specifies
   whether it is expected to be a directory or non-directory.
   Return RM_OK upon success, else RM_ERROR.  */
static enum RM_status
excise (FTS *fts, FTSENT *ent, struct rm_options const *x, bool is_dir)
{
  int flag = is_dir ? AT_REMOVEDIR : 0;
  if (unlinkat (fts->fts_cwd_fd, ent->fts_accpath, flag) == 0)
    {
      if (x->verbose)
        {
          printf ((is_dir
                   ? _("removed directory: %s\n")
                   : _("removed %s\n")), quote (ent->fts_path));
        }
      return RM_OK;
    }

  /* The unlinkat from kernels like linux-2.6.32 reports EROFS even for
     nonexistent files.  When the file is indeed missing, map that to ENOENT,
     so that rm -f ignores it, as required.  Even without -f, this is useful
     because it makes rm print the more precise diagnostic.  */
  if (errno == EROFS)
    {
      struct stat st;
      if ( ! (lstatat (fts->fts_cwd_fd, ent->fts_accpath, &st)
                       && errno == ENOENT))
        errno = EROFS;
    }

  if (ignorable_missing (x, errno))
    return RM_OK;

  /* When failing to rmdir an unreadable directory, the typical
     errno value is EISDIR, but that is not as useful to the user
     as the errno value from the failed open (probably EPERM).
     Use the earlier, more descriptive errno value.  */
  if (ent->fts_info == FTS_DNR)
    errno = ent->fts_errno;
  error (0, errno, _("cannot remove %s"), quote (ent->fts_path));
  mark_ancestor_dirs (ent);
  return RM_ERROR;
}
Пример #30
0
static int hash_dir(const char *dirname)
{
	struct dirent *de;
	struct stat st;
	int dirfd;
	DIR *d;

	fprintf(stdout, "Doing %s\n", dirname);
	dirfd = open(dirname, O_RDONLY | O_DIRECTORY);
	if (dirfd < 0) {
		perror(dirname);
		return -1;
	}
	d = opendir(dirname);
	if (!d) {
		close(dirfd);
		return -1;
	}
	while ((de = readdir(d)) != NULL) {
		if (fstatat(dirfd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
			continue;
		if (!S_ISLNK(st.st_mode))
			continue;
		if (!is_hash_filename(de->d_name))
			continue;

		if (unlinkat(dirfd, de->d_name, 0) < 0)
			perror(de->d_name);
	}

	rewinddir(d);
	while ((de = readdir(d)) != NULL) {
		if (fnmatch("*.pem", de->d_name, FNM_NOESCAPE) == 0)
			hash_file(dirfd, de->d_name);
	}
	closedir(d);

	return 0;
}