Esempio n. 1
0
inline int xp_id_compare(struct xp_daemon_id *id1, struct xp_daemon_id *id2, int check_related)
{
	if (id1 == NULL || id2 == NULL)
		return DAZUKO_DIFFERENT;

	/* if file's are available and they match,
	 * then we say that the id's match
	 * ("file" is only used to unregister daemons and
	 * here we allow other processes to do this)
	 * Note: this is a Linux-only "hack" */
	if (id1->file != NULL && id1->file == id2->file)
		return DAZUKO_SAME;

	if (id1->pid == id2->pid && id1->current_p == id2->current_p && id1->files == id2->files)
		return DAZUKO_SAME;

	if (check_related)
	{
		if (check_parent(id1->current_p, id2->current_p) == 0)
		{
			return DAZUKO_CHILD;
		}
		else if (id1->pid == id2->pid || id1->current_p == id2->current_p || id1->files == id2->files)
		{
			return DAZUKO_SUSPICIOUS;
		}
	}

	return DAZUKO_DIFFERENT;
}
Esempio n. 2
0
static struct ib_umem_odp *odp_lookup(struct ib_ucontext *ctx,
				      u64 start, u64 length,
				      struct mlx5_ib_mr *parent)
{
	struct ib_umem_odp *odp;
	struct rb_node *rb;

	down_read(&ctx->umem_rwsem);
	odp = rbt_ib_umem_lookup(&ctx->umem_tree, start, length);
	if (!odp)
		goto end;

	while (1) {
		if (check_parent(odp, parent))
			goto end;
		rb = rb_next(&odp->interval_tree.rb);
		if (!rb)
			goto not_found;
		odp = rb_entry(rb, struct ib_umem_odp, interval_tree.rb);
		if (ib_umem_start(odp->umem) > start + length)
			goto not_found;
	}
not_found:
	odp = NULL;
end:
	up_read(&ctx->umem_rwsem);
	return odp;
}
Esempio n. 3
0
static int
pre_ss(PRE_ARGS)
{

	if (MDOC_BLOCK != n->type)
		return(1);
	return(check_parent(mdoc, n, MDOC_Sh, MDOC_BODY));
}
Esempio n. 4
0
static int
pre_sh(PRE_ARGS)
{

	if (MDOC_BLOCK != n->type)
		return(1);

	mdoc->regs->regs[(int)REG_nS].set = 0;
	return(check_parent(mdoc, n, MDOC_MAX, MDOC_ROOT));
}
Esempio n. 5
0
static struct ib_umem_odp *odp_next(struct ib_umem_odp *odp)
{
	struct mlx5_ib_mr *mr = odp->private, *parent = mr->parent;
	struct ib_ucontext *ctx = odp->umem->context;
	struct rb_node *rb;

	down_read(&ctx->umem_rwsem);
	while (1) {
		rb = rb_next(&odp->interval_tree.rb);
		if (!rb)
			goto not_found;
		odp = rb_entry(rb, struct ib_umem_odp, interval_tree.rb);
		if (check_parent(odp, parent))
			goto end;
	}
not_found:
	odp = NULL;
end:
	up_read(&ctx->umem_rwsem);
	return odp;
}
static void
views_parser_start_element (GMarkupParseContext  *context,
                            const gchar          *element_name,
                            const gchar         **attribute_names,
                            const gchar         **attribute_values,
                            gpointer              user_data,
                            GError              **error)
{
  ViewsParserData *parser_data = user_data;
  GtkWidget *item;

  g_assert (context != NULL);
  g_assert (element_name != NULL);
  g_assert (parser_data != NULL);

  if (g_strcmp0 (element_name, "views") == 0)
    {
    }
  else if (g_strcmp0 (element_name, "view") == 0)
    {
      const gchar *name = NULL;

      if (!check_parent (context, "views", error))
        return;

      if (!g_markup_collect_attributes (element_name, attribute_names, attribute_values, error,
                                        G_MARKUP_COLLECT_STRING, "name", &name,
                                        G_MARKUP_COLLECT_INVALID))
        return;

      item = g_object_new (GB_TYPE_SHORTCUTS_VIEW,
                           "view-name", name,
                           "visible", TRUE,
                           NULL);

      g_queue_push_head (parser_data->stack, g_object_ref_sink (item));
    }
  else if (g_strcmp0 (element_name, "page") == 0)
    {
      if (!check_parent (context, "view", error))
        return;

      item = g_object_new (GB_TYPE_SHORTCUTS_PAGE,
                           "visible", TRUE,
                           NULL);
      g_queue_push_head (parser_data->stack, g_object_ref_sink (item));
    }
  else if (g_strcmp0 (element_name, "column") == 0)
    {
      GtkSizeGroup *size_group;

      if (!check_parent (context, "page", error))
        return;

      size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
      g_queue_push_head (parser_data->column_image_size_groups, size_group);

      size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
      g_queue_push_head (parser_data->column_desc_size_groups, size_group);

      item = g_object_new (GB_TYPE_SHORTCUTS_COLUMN,
                           "visible", TRUE,
                           NULL);
      g_queue_push_head (parser_data->stack, g_object_ref_sink (item));
    }
  else if (g_strcmp0 (element_name, "group") == 0)
    {
      if (!check_parent (context, "column", error))
        return;

      item = g_object_new (GB_TYPE_SHORTCUTS_GROUP,
                           "visible", TRUE,
                           NULL);
      g_queue_push_head (parser_data->stack, g_object_ref_sink (item));
    }
  else if (g_strcmp0 (element_name, "shortcut") == 0)
    {
      GtkSizeGroup *accel_size_group;
      GtkSizeGroup *desc_size_group;

      if (!check_parent (context, "group", error))
        return;

      accel_size_group = g_queue_peek_head (parser_data->column_image_size_groups);
      desc_size_group = g_queue_peek_head (parser_data->column_desc_size_groups);

      parser_data->search_item = g_object_new (GB_TYPE_SHORTCUTS_SHORTCUT,
                                               "visible", TRUE,
                                               NULL);

      item = g_object_new (GB_TYPE_SHORTCUTS_SHORTCUT,
                           "accelerator-size-group", accel_size_group,
                           "title-size-group", desc_size_group,
                           "visible", TRUE,
                           NULL);
      g_queue_push_head (parser_data->stack, g_object_ref_sink (item));
    }
  else if (g_strcmp0 (element_name, "gesture") == 0)
    {
      GtkSizeGroup *accel_size_group;
      GtkSizeGroup *desc_size_group;

      if (!check_parent (context, "group", error))
        return;

      accel_size_group = g_queue_peek_head (parser_data->column_image_size_groups);
      desc_size_group = g_queue_peek_head (parser_data->column_desc_size_groups);

      parser_data->search_item = g_object_new (GB_TYPE_SHORTCUTS_GESTURE,
                                               "visible", TRUE,
                                               NULL);

      item = g_object_new (GB_TYPE_SHORTCUTS_GESTURE,
                           "desc-size-group", desc_size_group,
                           "icon-size-group", accel_size_group,
                           "visible", TRUE,
                           NULL);
      g_queue_push_head (parser_data->stack, g_object_ref_sink (item));
    }
  else if (g_strcmp0 (element_name, "property") == 0)
    {
      const gchar *name = NULL;
      const gchar *translatable = NULL;

      item = g_queue_peek_head (parser_data->stack);

      if (item == NULL)
        {
          g_set_error (error,
                       GTK_BUILDER_ERROR,
                       GTK_BUILDER_ERROR_INVALID_TAG,
                       "Property called without a parent object");
          return;
        }

      if (!g_markup_collect_attributes (element_name, attribute_names, attribute_values, error,
                                        G_MARKUP_COLLECT_STRING, "name", &name,
                                        G_MARKUP_COLLECT_OPTIONAL | G_MARKUP_COLLECT_STRING, "translatable", &translatable,
                                        G_MARKUP_COLLECT_INVALID))
        return;

      g_free (parser_data->property_name);
      parser_data->property_name = g_strdup (name);
      parser_data->translatable = (g_strcmp0 (translatable, "yes") == 0);
    }
  else
    {
      const GSList *stack;
      const gchar *parent_name;
      const gchar *our_name;
      gint line;
      gint col;

      stack = g_markup_parse_context_get_element_stack (context);
      our_name = stack->data;
      parent_name = stack->next ? stack->next->data : "";

      g_markup_parse_context_get_position (context, &line, &col);
      g_set_error (error,
                   GTK_BUILDER_ERROR,
                   GTK_BUILDER_ERROR_INVALID_TAG,
                   "%d:%d: Unknown element <%s> found in <%s>.",
                   line, col, our_name, parent_name);
    }
}
Esempio n. 7
0
/*
 * Rename a file.
 *
 * Locking:
 *    Locks sfs_renamelock.
 *    Calls check_parent, which locks various directories one at a
 *       time.
 *    Locks the target vnodes and their parents in a complex fashion
 *       (described in detail below) which is carefully arranged so
 *       it won't deadlock with rmdir. Or at least I hope so.
 *    Then unlocks everything.
 *
 *    The rationale for all this is complex. See the comments below.
 *
 * Requires up to 7 buffers.
 */
static
int
sfs_rename(struct vnode *absdir1, const char *name1,
	   struct vnode *absdir2, const char *name2)
{
	struct sfs_fs *sfs = absdir1->vn_fs->fs_data;
	struct sfs_vnode *dir1 = absdir1->vn_data;
	struct sfs_vnode *dir2 = absdir2->vn_data;
	struct sfs_vnode *obj1=NULL, *obj2=NULL;
	struct sfs_dinode *dir1_inodeptr, *dir2_inodeptr;
	struct sfs_dinode *obj1_inodeptr, *obj2_inodeptr;
	int slot1=-1, slot2=-1;
	int result, result2;
	struct sfs_direntry sd;
	int found_dir1;

	/* make gcc happy */
	obj2_inodeptr = NULL;

	/* The VFS layer is supposed to enforce this */
	KASSERT(absdir1->vn_fs == absdir2->vn_fs);

	if (!strcmp(name1, ".") || !strcmp(name2, ".") ||
	    !strcmp(name1, "..") || !strcmp(name2, "..")) {
		return EINVAL;
	}

	if (strlen(name2)+1 > sizeof(sd.sfd_name)) {
		return ENAMETOOLONG;
	}

	/*
	 * We only allow one rename to occur at a time. This appears
	 * to be necessary to preserve the consistency of the
	 * filesystem: once you do the parent check (that n1 is not an
	 * ancestor of d2/n2) nothing may be allowed to happen that
	 * might invalidate that result until all of the
	 * rearrangements are complete. If other renames are allowed
	 * to proceed, we'd need to lock every descendent of n1 to
	 * make sure that some ancestor of d2/n2 doesn't get inserted
	 * at some point deep down. This is impractical, so we use one
	 * global lock.
	 *
	 * To prevent certain deadlocks while locking the vnodes we
	 * need, the rename lock goes outside all the vnode locks.
	 */

	reserve_buffers(SFS_BLOCKSIZE);

	lock_acquire(sfs->sfs_renamelock);

	/*
	 * Get the objects we're moving.
	 *
	 * Lock each directory temporarily. We'll check again later to
	 * make sure they haven't disappeared and to find slots.
	 */
	lock_acquire(dir1->sv_lock);
	result = sfs_lookonce(dir1, name1, &obj1, NULL);
	lock_release(dir1->sv_lock);

	if (result) {
		goto out0;
	}

	lock_acquire(dir2->sv_lock);
	result = sfs_lookonce(dir2, name2, &obj2, NULL);
	lock_release(dir2->sv_lock);

	if (result && result != ENOENT) {
		goto out0;
	}

	if (result==ENOENT) {
		/*
		 * sfs_lookonce returns a null vnode with ENOENT in
		 * order to make our life easier.
		 */
		KASSERT(obj2==NULL);
	}

	/*
	 * Prohibit the case where obj1 is a directory and it's a direct
	 * ancestor in the tree of dir2 (or is the same as dir2). If
	 * that were to be permitted, it'd create a detached chunk of
	 * the directory tree, and we don't like that.
	 *
	 * If we see dir1 while checking up the tree, found_dir1 is
	 * set to true. We use this info to choose the correct ordering
	 * for locking dir1 and dir2.
	 *
	 * To prevent deadlocks, the parent check must be done without
	 * holding locks on any other directories.
	 */
	result = check_parent(dir1, obj1, dir2, &found_dir1);
	if (result) {
		goto out0;
	}

	/*
	 * Now check for cases where some of the four vnodes we have
	 * are the same.
	 *
	 * These cases are, in the order they are handled below:
	 *
	 *    dir1 == obj1		Already checked.
	 *    dir2 == obj2		Already checked.
	 *    dir2 == obj1		Already checked.
	 *    dir1 == obj2		Checked below.
	 *    dir1 == dir2		Legal.
	 *    obj1 == obj2		Legal, special handling.
	 */

	/*
	 * A directory should have no entries for itself other than '.'.
	 * Thus, since we explicitly reject '.' above, the names
	 * within the directories should not refer to the directories
	 * themselves.
	 */
	KASSERT(dir1 != obj1);
	KASSERT(dir2 != obj2);

	/*
	 * The parent check should have caught this case.
	 */
	KASSERT(dir2 != obj1);

	/*
	 * Check for dir1 == obj2.
	 *
	 * This is not necessarily wrong if obj1 is the last entry in
	 * dir1 (this is essentially "mv ./foo/bar ./foo") but our
	 * implementation doesn't tolerate it. Because we need to
	 * unlink g2 before linking g1 in the new place, it will
	 * always fail complaining that g2 (sv1) isn't empty. We could
	 * just charge ahead and let this happen, but we'll get into
	 * trouble with our locks if we do, so detect this as a
	 * special case and return ENOTEMPTY.
	 */

	if (obj2==dir1) {
		result = ENOTEMPTY;
		goto out0;
	}


	/*
	 * Now we can begin acquiring locks for real.
	 *
	 * If we saw dir1 while doing the parent check, it means
	 * dir1 is higher in the tree than dir2. Thus, we should
	 * lock dir1 before dir2.
	 *
	 * If on the other hand we didn't see dir1, either dir2 is
	 * higher in the tree than dir1, in which case we should lock
	 * dir2 first, or dir1 and dir2 are on disjoint branches of
	 * the tree, in which case (because there's a single rename
	 * lock for the whole fs) it doesn't matter what order we lock
	 * in.
	 *
	 * If we lock dir1 first, we don't need to lock obj1 before
	 * dir2, since (due to the parent check) obj1 cannot be an
	 * ancestor of dir2.
	 *
	 * However, if we lock dir2 first, obj2 must be locked before
	 * dir1, in case obj2 is an ancestor of dir1. (In this case we
	 * will find that obj2 is not empty and cannot be removed, but
	 * we must lock it before we can check that.)
	 *
	 * Thus we lock in this order:
	 *
	 * dir1   (if found_dir1)
	 * dir2
	 * obj2   (if non-NULL)
	 * dir1   (if !found_dir1)
	 * obj1
	 *
	 * Also, look out for the case where both dirs are the same.
	 * (If this is true, found_dir1 will be set.)
	 */

	if (dir1==dir2) {
		/* This locks "both" dirs */
		lock_acquire(dir1->sv_lock);
		KASSERT(found_dir1);
	}
	else {
		if (found_dir1) {
			lock_acquire(dir1->sv_lock);
		}
		lock_acquire(dir2->sv_lock);
	}

	/*
	 * Now lock obj2.
	 *
	 * Note that we must redo the lookup and get a new obj2, as it
	 * may have changed under us. Since we hold the rename lock
	 * for the whole fs, the fs structure cannot have changed, so
	 * we don't need to redo the parent check or any of the checks
	 * for vnode aliasing with dir1 or dir2 above. Note however
	 * that obj1 and obj2 may now be the same even if they weren't
	 * before.
	 */
	KASSERT(lock_do_i_hold(dir2->sv_lock));
	if (obj2) {
		VOP_DECREF(&obj2->sv_absvn);
		obj2 = NULL;
	}
	result = sfs_lookonce(dir2, name2, &obj2, &slot2);
	if (result==0) {
		KASSERT(obj2 != NULL);
		lock_acquire(obj2->sv_lock);
		result = sfs_dinode_load(obj2);
		if (result) {
			/* ENOENT would confuse us below; but it can't be */
			KASSERT(result != ENOENT);
			lock_release(obj2->sv_lock);
			VOP_DECREF(&obj2->sv_absvn);
			/* continue to check below */
		}
		else {
			obj2_inodeptr = sfs_dinode_map(obj2);
		}
	}
	else if (result==ENOENT) {
		/*
		 * sfs_lookonce returns a null vnode and an empty slot
		 * with ENOENT in order to make our life easier.
		 */
		KASSERT(obj2==NULL);
		KASSERT(slot2>=0);
	}

	if (!found_dir1) {
		lock_acquire(dir1->sv_lock);
	}

	/* Postpone this check to simplify the error cleanup. */
	if (result != 0 && result != ENOENT) {
		goto out1;
	}

	/*
	 * Now reload obj1.
	 */
	KASSERT(lock_do_i_hold(dir1->sv_lock));
	VOP_DECREF(&obj1->sv_absvn);
	obj1 = NULL;
	result = sfs_lookonce(dir1, name1, &obj1, &slot1);
	if (result) {
		goto out1;
	}
	/*
	 * POSIX mandates that if obj1==obj2, we succeed and nothing
	 * happens.  This is somewhat stupid if obj1==obj2 and dir1 != dir2,
	 * but we'll go with POSIX anyway.
	 */
	if (obj1==obj2) {
		result = 0;
		VOP_DECREF(&obj1->sv_absvn);
		obj1 = NULL;
		goto out1;
	}
	lock_acquire(obj1->sv_lock);
	result = sfs_dinode_load(obj1);
	if (result) {
		lock_release(obj1->sv_lock);
		VOP_DECREF(&obj1->sv_absvn);
		obj1 = NULL;
		goto out1;
	}
	obj1_inodeptr = sfs_dinode_map(obj1);

	result = sfs_dinode_load(dir2);
	if (result) {
		goto out2;
	}
	dir2_inodeptr = sfs_dinode_map(dir2);

	result = sfs_dinode_load(dir1);
	if (result) {
		goto out3;
	}
	dir1_inodeptr = sfs_dinode_map(dir1);

	/*
	 * One final piece of paranoia: make sure dir2 hasn't been rmdir'd.
	 * (If dir1 was, the obj1 lookup above would have failed.)
	 */
	if (dir2_inodeptr->sfi_linkcount==0) {
		result = ENOENT;
		goto out4;
	}

	/*
	 * Now we have all the locks we need and we can proceed with
	 * the operation.
	 */

	/* At this point we should have valid slots in both dirs. */
	KASSERT(slot1>=0);
	KASSERT(slot2>=0);

	if (obj2 != NULL) {
		/*
		 * Target already exists.
		 * Must be the same type (file or directory) as the source,
		 * and if a directory, must be empty. Then unlink it.
		 */

		if (obj1_inodeptr->sfi_type == SFS_TYPE_DIR) {
			if (obj2_inodeptr->sfi_type != SFS_TYPE_DIR) {
				result = ENOTDIR;
				goto out4;
			}
			result = sfs_dir_checkempty(obj2);
			if (result) {
				goto out4;
			}

			/* Remove the name */
			result = sfs_dir_unlink(dir2, slot2);
			if (result) {
				goto out4;
			}

			/* Dispose of the directory */
			KASSERT(dir2_inodeptr->sfi_linkcount > 1);
			KASSERT(obj2_inodeptr->sfi_linkcount == 2);
			dir2_inodeptr->sfi_linkcount--;
			obj2_inodeptr->sfi_linkcount -= 2;
			sfs_dinode_mark_dirty(dir2);
			sfs_dinode_mark_dirty(obj2);

			/* ignore errors on this */
			sfs_itrunc(obj2, 0);
		}
		else {
			KASSERT(obj1->sv_type == SFS_TYPE_FILE);
			if (obj2->sv_type != SFS_TYPE_FILE) {
				result = EISDIR;
				goto out4;
			}

			/* Remove the name */
			result = sfs_dir_unlink(dir2, slot2);
			if (result) {
				goto out4;
			}

			/* Dispose of the file */
			KASSERT(obj2_inodeptr->sfi_linkcount > 0);
			obj2_inodeptr->sfi_linkcount--;
			sfs_dinode_mark_dirty(obj2);
		}

		sfs_dinode_unload(obj2);

		lock_release(obj2->sv_lock);
		VOP_DECREF(&obj2->sv_absvn);
		obj2 = NULL;
	}

	/*
	 * At this point the target should be nonexistent and we have
	 * a slot in the target directory we can use. Create a link
	 * there. Do it by hand instead of using sfs_dir_link to avoid
	 * duplication of effort.
	 */
	KASSERT(obj2==NULL);

	bzero(&sd, sizeof(sd));
	sd.sfd_ino = obj1->sv_ino;
	strcpy(sd.sfd_name, name2);
	result = sfs_writedir(dir2, slot2, &sd);
	if (result) {
		goto out4;
	}

	obj1_inodeptr->sfi_linkcount++;
	sfs_dinode_mark_dirty(obj1);

	if (obj1->sv_type == SFS_TYPE_DIR && dir1 != dir2) {
		/* Directory: reparent it */
		result = sfs_readdir(obj1, DOTDOTSLOT, &sd);
		if (result) {
			goto recover1;
		}
		if (strcmp(sd.sfd_name, "..")) {
			panic("sfs: %s: rename: moving dir: .. is not "
			      "in slot %d\n", sfs->sfs_sb.sb_volname,
			      DOTDOTSLOT);
		}
		if (sd.sfd_ino != dir1->sv_ino) {
			panic("sfs: %s: rename: moving dir: .. is i%u "
			      "and not i%u\n", sfs->sfs_sb.sb_volname,
			      sd.sfd_ino, dir1->sv_ino);
		}
		sd.sfd_ino = dir2->sv_ino;
		result = sfs_writedir(obj1, DOTDOTSLOT, &sd);
		if (result) {
			goto recover1;
		}
		dir1_inodeptr->sfi_linkcount--;
		sfs_dinode_mark_dirty(dir1);
		dir2_inodeptr->sfi_linkcount++;
		sfs_dinode_mark_dirty(dir2);
	}

	result = sfs_dir_unlink(dir1, slot1);
	if (result) {
		goto recover2;
	}
	obj1_inodeptr->sfi_linkcount--;
	sfs_dinode_mark_dirty(obj1);

	KASSERT(result==0);

	if (0) {
		/* Only reached on error */
    recover2:
		if (obj1->sv_type == SFS_TYPE_DIR) {
			sd.sfd_ino = dir1->sv_ino;
			result2 = sfs_writedir(obj1, DOTDOTSLOT, &sd);
			if (result2) {
				recovermsg(sfs->sfs_sb.sb_volname,
					   result, result2);
			}
			dir1_inodeptr->sfi_linkcount++;
			sfs_dinode_mark_dirty(dir1);
			dir2_inodeptr->sfi_linkcount--;
			sfs_dinode_mark_dirty(dir2);
		}
    recover1:
		result2 = sfs_dir_unlink(dir2, slot2);
		if (result2) {
			recovermsg(sfs->sfs_sb.sb_volname,
				   result, result2);
		}
		obj1_inodeptr->sfi_linkcount--;
		sfs_dinode_mark_dirty(obj1);
	}

 out4:
 	sfs_dinode_unload(dir1);
 out3:
 	sfs_dinode_unload(dir2);
 out2:
 	sfs_dinode_unload(obj1);
	lock_release(obj1->sv_lock);
 out1:
	if (obj2) {
		sfs_dinode_unload(obj2);
		lock_release(obj2->sv_lock);
	}
	lock_release(dir1->sv_lock);
	if (dir1 != dir2) {
		lock_release(dir2->sv_lock);
	}
 out0:
	if (obj2 != NULL) {
		VOP_DECREF(&obj2->sv_absvn);
	}
	if (obj1 != NULL) {
		VOP_DECREF(&obj1->sv_absvn);
	}

	unreserve_buffers(SFS_BLOCKSIZE);

	lock_release(sfs->sfs_renamelock);

	return result;
}
Esempio n. 8
0
static void sendcmd(const char *cmd, const char *arg1, const char *arg2)
{
	int	i, pipefd, ret;
	char	buf[SMALLBUF], enc[SMALLBUF];

	/* insanity */
	if (!arg1)
		return;

	/* build the request */
	snprintf(buf, sizeof(buf), "%s \"%s\"",
		cmd, pconf_encode(arg1, enc, sizeof(enc)));

	if (arg2)
		snprintfcat(buf, sizeof(buf), " \"%s\"",
			pconf_encode(arg2, enc, sizeof(enc)));

	snprintf(enc, sizeof(enc), "%s\n", buf);

	/* see if the parent needs to be started (and maybe start it) */

	for (i = 0; i < MAX_TRIES; i++) {

		pipefd = check_parent(cmd, arg2);

		if (pipefd == PARENT_STARTED) {

			/* loop back and try to connect now */
			usleep(250000);
			continue;
		}

		/* special case for CANCEL when no parent is running */
		if (pipefd == PARENT_UNNECESSARY)
			return;

		/* we're connected now */

		ret = write(pipefd, enc, strlen(enc));

		/* if we can't send the whole thing, loop back and try again */
		if ((ret < 1) || (ret != (int) strlen(enc))) {
			upslogx(LOG_ERR, "write failed, trying again");
			close(pipefd);
			continue;
		}

		/* ugh - probably should use select here... */
		setup_sigalrm();

		alarm(2);
		ret = read(pipefd, buf, sizeof(buf));
		alarm(0);

		signal(SIGALRM, SIG_IGN);

		close(pipefd);

		/* same idea: no OK = go try it all again */
		if (ret < 2) {
			upslogx(LOG_ERR, "read confirmation failed, trying again");
			continue;
		}

		if (!strncmp(buf, "OK", 2))
			return;		/* success */

		upslogx(LOG_ERR, "read confirmation got [%s]", buf);

		/* try again ... */
	}

	fatalx(EXIT_FAILURE, "Unable to connect to daemon and unable to start daemon");
}
Esempio n. 9
0
/*
 * Unlink a file or directory
 * N.B. After this call fhp needs an fh_put
 */
int
nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
				char *fname, int flen)
{
	struct dentry	*dentry, *rdentry;
	struct inode	*dirp;
	int		err;

	/* N.B. We shouldn't need this test ... handled by dentry layer */
	err = nfserr_acces;
	if (!flen || isdotent(fname, flen))
		goto out;
	err = fh_verify(rqstp, fhp, S_IFDIR, MAY_REMOVE);
	if (err)
		goto out;

	dentry = fhp->fh_dentry;
	dirp = dentry->d_inode;

	rdentry = lookup_dentry(fname, dget(dentry), 0);
	err = PTR_ERR(rdentry);
	if (IS_ERR(rdentry))
		goto out_nfserr;

	if (!rdentry->d_inode) {
		dput(rdentry);
		err = nfserr_noent;
		goto out;
	}

	if (type != S_IFDIR) {
		/* It's UNLINK */
		err = fh_lock_parent(fhp, rdentry);
		if (err)
			goto out;

		err = vfs_unlink(dirp, rdentry);

		DQUOT_DROP(dirp);
		fh_unlock(fhp);

		dput(rdentry);

	} else {
		/* It's RMDIR */
		/* See comments in fs/namei.c:do_rmdir */
		rdentry->d_count++;
		nfsd_double_down(&dirp->i_sem, &rdentry->d_inode->i_sem);
		if (!fhp->fh_pre_mtime)
			fhp->fh_pre_mtime = dirp->i_mtime;
		fhp->fh_locked = 1;

		err = -ENOENT;
		if (check_parent(dirp, rdentry))
			err = vfs_rmdir(dirp, rdentry);

		rdentry->d_count--;
		DQUOT_DROP(dirp);
		if (!fhp->fh_post_version)
			fhp->fh_post_version = dirp->i_version;
		fhp->fh_locked = 0;
		nfsd_double_up(&dirp->i_sem, &rdentry->d_inode->i_sem);

		dput(rdentry);
	}

	if (err)
		goto out_nfserr;
	if (EX_ISSYNC(fhp->fh_export))
		write_inode_now(dirp);
out:
	return err;

out_nfserr:
	err = nfserrno(-err);
	goto out;
}
Esempio n. 10
0
/*
 * Rename a file
 * N.B. After this call _both_ ffhp and tfhp need an fh_put
 */
int
nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
			    struct svc_fh *tfhp, char *tname, int tlen)
{
	struct dentry	*fdentry, *tdentry, *odentry, *ndentry;
	struct inode	*fdir, *tdir;
	int		err;

	err = fh_verify(rqstp, ffhp, S_IFDIR, MAY_REMOVE);
	if (err)
		goto out;
	err = fh_verify(rqstp, tfhp, S_IFDIR, MAY_CREATE);
	if (err)
		goto out;

	fdentry = ffhp->fh_dentry;
	fdir = fdentry->d_inode;

	tdentry = tfhp->fh_dentry;
	tdir = tdentry->d_inode;

	/* N.B. We shouldn't need this ... dentry layer handles it */
	err = nfserr_perm;
	if (!flen || (fname[0] == '.' && 
	    (flen == 1 || (flen == 2 && fname[1] == '.'))) ||
	    !tlen || (tname[0] == '.' && 
	    (tlen == 1 || (tlen == 2 && tname[1] == '.'))))
		goto out;

	odentry = lookup_dentry(fname, dget(fdentry), 0);
	err = PTR_ERR(odentry);
	if (IS_ERR(odentry))
		goto out_nfserr;

	err = -ENOENT;
	if (!odentry->d_inode)
		goto out_dput_old;

	ndentry = lookup_dentry(tname, dget(tdentry), 0);
	err = PTR_ERR(ndentry);
	if (IS_ERR(ndentry))
		goto out_dput_old;

	/*
	 * Lock the parent directories.
	 */
	nfsd_double_down(&tdir->i_sem, &fdir->i_sem);
	err = -ENOENT;
	/* GAM3 check for parent changes after locking. */
	if (check_parent(fdir, odentry) &&
	    check_parent(tdir, ndentry)) {

		err = vfs_rename(fdir, odentry, tdir, ndentry);
		if (!err && EX_ISSYNC(tfhp->fh_export)) {
			write_inode_now(fdir);
			write_inode_now(tdir);
		}
	} else
		dprintk("nfsd: Caught race in nfsd_rename");
	DQUOT_DROP(fdir);
	DQUOT_DROP(tdir);

	nfsd_double_up(&tdir->i_sem, &fdir->i_sem);
	dput(ndentry);

out_dput_old:
	dput(odentry);
	if (err)
		goto out_nfserr;
out:
	return err;

out_nfserr:
	err = nfserrno(-err);
	goto out;
}
Esempio n. 11
0
int main(int argc, char *argv[])
{
    const char	*prog = xbasename(argv[0]);
    int	i, cmd = 0, checking_flag = 0;

    printf("Network UPS Tools %s %s\n", prog, UPS_VERSION);

    /* if no configuration file is specified on the command line, use default */
    configfile = xmalloc(SMALLBUF);
    snprintf(configfile, SMALLBUF, "%s/upsmon.conf", confpath());
    configfile = xrealloc(configfile, strlen(configfile) + 1);

    run_as_user = xstrdup(RUN_AS_USER);

    while ((i = getopt(argc, argv, "+Dhic:f:pu:VK46")) != -1) {
        switch (i) {
        case 'c':
            if (!strncmp(optarg, "fsd", strlen(optarg)))
                cmd = SIGCMD_FSD;
            if (!strncmp(optarg, "stop", strlen(optarg)))
                cmd = SIGCMD_STOP;
            if (!strncmp(optarg, "reload", strlen(optarg)))
                cmd = SIGCMD_RELOAD;

            /* bad command name given */
            if (cmd == 0)
                help(argv[0]);
            break;
        case 'D':
            nut_debug_level++;
            break;
        case 'f':
            free(configfile);
            configfile = xstrdup(optarg);
            break;
        case 'h':
            help(argv[0]);
            break;
        case 'K':
            checking_flag = 1;
            break;
        case 'p':
            use_pipe = 0;
            break;
        case 'u':
            free(run_as_user);
            run_as_user = xstrdup(optarg);
            break;
        case 'V':
            /* just show the banner */
            exit(EXIT_SUCCESS);
        case '4':
            opt_af = AF_INET;
            break;
        case '6':
            opt_af = AF_INET6;
            break;
        default:
            help(argv[0]);
            break;
        }
    }

    if (cmd) {
        sendsignal(prog, cmd);
        exit(EXIT_SUCCESS);
    }

    /* otherwise, we are being asked to start.
     * so check if a previous instance is running by sending signal '0'
     * (Ie 'kill <pid> 0') */
    if (sendsignal(prog, 0) == 0) {
        printf("Fatal error: A previous upsmon instance is already running!\n");
        printf("Either stop the previous instance first, or use the 'reload' command.\n");
        exit(EXIT_FAILURE);
    }

    argc -= optind;
    argv += optind;

    open_syslog(prog);

    loadconfig();

    if (checking_flag)
        exit(check_pdflag());

    if (shutdowncmd == NULL)
        printf("Warning: no shutdown command defined!\n");

    /* we may need to get rid of a flag from a previous shutdown */
    if (powerdownflag != NULL)
        clear_pdflag();
    /* FIXME (else): POWERDOWNFLAG is not defined!!
     * => fallback to a default value */

    if (totalpv < minsupplies) {
        printf("\nFatal error: insufficient power configured!\n\n");

        printf("Sum of power values........: %d\n", totalpv);
        printf("Minimum value (MINSUPPLIES): %d\n", minsupplies);

        printf("\nEdit your upsmon.conf and change the values.\n");
        exit(EXIT_FAILURE);
    }

    if (nut_debug_level < 1) {
        background();
    } else {
        upsdebugx(1, "debug level is '%d'", nut_debug_level);
    }

    /* only do the pipe stuff if the user hasn't disabled it */
    if (use_pipe) {
        struct passwd	*new_uid = get_user_pwent(run_as_user);

        /* === root parent and unprivileged child split here === */
        start_pipe();

        /* write the pid file now, as we will soon lose root */
        writepid(prog);

        become_user(new_uid);
    } else {
        upslogx(LOG_INFO, "Warning: running as one big root process by request (upsmon -p)");

        writepid(prog);
    }

    /* prep our signal handlers */
    setup_signals();

    /* reopen the log for the child process */
    closelog();
    open_syslog(prog);

    while (exit_flag == 0) {
        utype_t	*ups;

        /* check flags from signal handlers */
        if (userfsd)
            forceshutdown();

        if (reload_flag)
            reload_conf();

        for (ups = firstups; ups != NULL; ups = ups->next)
            pollups(ups);

        recalc();

        /* make sure the parent hasn't died */
        if (use_pipe)
            check_parent();

        /* reap children that have exited */
        waitpid(-1, NULL, WNOHANG);

        sleep(sleepval);
    }

    upslogx(LOG_INFO, "Signal %d: exiting", exit_flag);
    upsmon_cleanup();

    exit(EXIT_SUCCESS);
}