Пример #1
0
int
dup_mmap(struct mm_struct *to, struct mm_struct *from) {
    assert(to != NULL && from != NULL);
    list_entry_t *list = &(from->mmap_list), *le = list;
    while ((le = list_prev(le)) != list) {
        struct vma_struct *vma, *nvma;
        vma = le2vma(le, list_link);
        nvma = vma_create(vma->vm_start, vma->vm_end, vma->vm_flags);
        if (nvma == NULL) {
            return -E_NO_MEM;
        }

        insert_vma_struct(to, nvma);

        bool share = 0;
        if (copy_range(to->pgdir, from->pgdir, vma->vm_start, vma->vm_end, share) != 0) {
            return -E_NO_MEM;
        }
    }
    return 0;
}
Пример #2
0
/*
 * Internal dhcptab record update routine, used to factor out the
 * common code between add_dt(), delete_dt(), and modify_dt().  If
 * `origp' is NULL, then act like add_dt(); if `newp' is NULL, then
 * act like delete_dt(); otherwise act like modify_dt().
 */
static int
update_dt(const dt_handle_t *dhp, const dt_rec_t *origp, dt_rec_t *newp)
{
	char		dtpath[MAXPATHLEN], newpath[MAXPATHLEN];
	int		retval = DSVC_SUCCESS;
	off_t		recoff, recnext;
	dt_rec_list_t	*reclist;
	FILE		*fp;
	int		newfd;
	uint_t		found;
	int		query;
	struct stat	st;

	if ((dhp->dh_oflags & DSVC_WRITE) == 0)
		return (DSVC_ACCESS);

	/*
	 * Open the container to update and a new container file which we
	 * will store the updated version of the container in.  When the
	 * update is done, rename the new file to be the real container.
	 */
	dt2path(dtpath, MAXPATHLEN, dhp->dh_location, "");
	fp = fopen(dtpath, "r");
	if (fp == NULL)
		return (syserr_to_dsvcerr(errno));

	dt2path(newpath, MAXPATHLEN, dhp->dh_location, ".new");
	(void) unlink(newpath);
	newfd = open(newpath, O_CREAT|O_EXCL|O_WRONLY, 0644);
	if (newfd == -1) {
		(void) fclose(fp);
		return (syserr_to_dsvcerr(errno));
	}

	DSVC_QINIT(query);
	DSVC_QEQ(query, DT_QKEY|DT_QTYPE);

	/*
	 * If we're adding a new record or changing a key for an existing
	 * record, bail if the record we want to add already exists.
	 */
	if (newp != NULL) {
		if (origp == NULL || origp->dt_type != newp->dt_type ||
		    strcmp(origp->dt_key, newp->dt_key) != 0) {
			retval = find_dt(fp, 0, query, 1, newp, NULL, &found);
			if (retval != DSVC_SUCCESS)
				goto out;
			if (found != 0) {
				retval = DSVC_EXISTS;
				goto out;
			}
		}
	}

	/*
	 * If we're deleting or modifying record, make sure the record
	 * still exists.  Note that we don't check signatures because this
	 * is a legacy format that has no signatures.
	 */
	if (origp != NULL) {
		retval = find_dt(fp, FIND_POSITION, query, 1, origp, &reclist,
		    &found);
		if (retval != DSVC_SUCCESS)
			goto out;
		if (found == 0) {
			retval = DSVC_NOENT;
			goto out;
		}

		/*
		 * Note the offset of the record we're modifying or deleting
		 * for use down below.
		 */
		recoff  = ((dt_recpos_t *)reclist->dtl_rec)->dtp_off;
		recnext = recoff + ((dt_recpos_t *)reclist->dtl_rec)->dtp_size;

		free_dtrec_list(reclist);
	} else {
		/*
		 * No record to modify or delete, so set `recoff' and
		 * `recnext' appropriately.
		 */
		recoff = 0;
		recnext = 0;
	}

	/*
	 * Make a new copy of the container.  If we're deleting or
	 * modifying a record, don't copy that record to the new container.
	 */
	if (fstat(fileno(fp), &st) == -1) {
		retval = DSVC_INTERNAL;
		goto out;
	}

	retval = copy_range(fileno(fp), 0, newfd, 0, recoff);
	if (retval != DSVC_SUCCESS)
		goto out;

	retval = copy_range(fileno(fp), recnext, newfd, recoff,
	    st.st_size - recnext);
	if (retval != DSVC_SUCCESS)
		goto out;

	/*
	 * If there's a new record, append it to the new container.
	 */
	if (newp != NULL) {
		retval = write_rec(newfd, newp, recoff + st.st_size - recnext);
		if (retval != DSVC_SUCCESS)
			goto out;
	}

	/*
	 * Note: we close these descriptors before the rename(2) (rather
	 * than just having the `out:' label clean them up) to save NFS
	 * some work (otherwise, NFS has to save `dtpath' to an alternate
	 * name since its vnode would still be active).
	 */
	(void) fclose(fp);
	(void) close(newfd);

	if (rename(newpath, dtpath) == -1)
		retval = syserr_to_dsvcerr(errno);

	return (retval);
out:
	(void) fclose(fp);
	(void) close(newfd);
	(void) unlink(newpath);
	return (retval);
}
Пример #3
0
/*
 * Internal dhcp_network record update routine, used to factor out the
 * common code between add_dn(), delete_dn(), and modify_dn().  If
 * `origp' is NULL, then act like add_dn(); if `newp' is NULL, then
 * act like delete_dn(); otherwise act like modify_dn().
 */
static int
update_dn(const dn_handle_t *dhp, const dn_rec_t *origp, dn_rec_t *newp)
{
	char		dnpath[MAXPATHLEN], newpath[MAXPATHLEN];
	int		retval = DSVC_SUCCESS;
	off_t		recoff, recnext;
	dn_rec_list_t	*reclist;
	int		fd, newfd;
	uint_t		found;
	int		query;
	struct stat	st;


	if ((dhp->dh_oflags & DSVC_WRITE) == 0)
		return (DSVC_ACCESS);

	/*
	 * Open the container to update and a new container file which we
	 * will store the updated version of the container in.  When the
	 * update is done, rename the new file to be the real container.
	 */
	net2path(dnpath, MAXPATHLEN, dhp->dh_location, dhp->dh_net, "");
	fd = open(dnpath, O_RDONLY);
	if (fd == -1)
		return (syserr_to_dsvcerr(errno));

	net2path(newpath, MAXPATHLEN, dhp->dh_location, dhp->dh_net, ".new");
	newfd = open(newpath, O_CREAT|O_TRUNC|O_WRONLY, 0644);
	if (newfd == -1) {
		(void) close(fd);
		return (syserr_to_dsvcerr(errno));
	}

	DSVC_QINIT(query);
	DSVC_QEQ(query, DN_QCIP);

	/*
	 * If we're changing the key for this record, make sure the key
	 * we're changing to doesn't already exist.
	 */
	if (origp != NULL && newp != NULL) {
		if (origp->dn_cip.s_addr != newp->dn_cip.s_addr) {
			retval = find_dn(fd, 0, query, 1, newp, NULL, &found);
			if (retval != DSVC_SUCCESS)
				goto out;
			if (found != 0) {
				retval = DSVC_EXISTS;
				goto out;
			}
		}
	}

	/*
	 * If we're adding a new record, make sure the record doesn't
	 * already exist.
	 */
	if (newp != NULL && origp == NULL) {
		retval = find_dn(fd, 0, query, 1, newp, NULL, &found);
		if (retval != DSVC_SUCCESS)
			goto out;
		if (found != 0) {
			retval = DSVC_EXISTS;
			goto out;
		}
	}

	/*
	 * If we're deleting or modifying record, make sure the record
	 * still exists and that our copy isn't stale.  Note that we don't
	 * check signatures if we're deleting the record and origp->dn_sig
	 * is zero, so that records that weren't looked up can be deleted.
	 */
	if (origp != NULL) {
		retval = find_dn(fd, FIND_POSITION, query, 1, origp, &reclist,
		    &found);
		if (retval != DSVC_SUCCESS)
			goto out;
		if (found == 0) {
			retval = DSVC_NOENT;
			goto out;
		}

		if (reclist->dnl_rec->dn_sig != origp->dn_sig) {
			if (newp != NULL || origp->dn_sig != 0) {
				free_dnrec_list(reclist);
				retval = DSVC_COLLISION;
				goto out;
			}
		}

		/*
		 * Note the offset of the record we're modifying or deleting
		 * for use down below.
		 */
		recoff  = ((dn_recpos_t *)reclist->dnl_rec)->dnp_off;
		recnext = recoff + ((dn_recpos_t *)reclist->dnl_rec)->dnp_size;

		free_dnrec_list(reclist);
	} else {
		/*
		 * No record to modify or delete, so set `recoff' and
		 * `recnext' appropriately.
		 */
		recoff = 0;
		recnext = 0;
	}

	/*
	 * Make a new copy of the container.  If we're deleting or
	 * modifying a record, don't copy that record to the new container.
	 */
	if (fstat(fd, &st) == -1) {
		retval = DSVC_INTERNAL;
		goto out;
	}

	retval = copy_range(fd, 0, newfd, 0, recoff);
	if (retval != DSVC_SUCCESS)
		goto out;

	retval = copy_range(fd, recnext, newfd, recoff, st.st_size - recnext);
	if (retval != DSVC_SUCCESS)
		goto out;

	/*
	 * If there's a new/modified record, append it to the new container.
	 */
	if (newp != NULL) {
		if (origp == NULL)
			newp->dn_sig = gensig();
		else
			newp->dn_sig = origp->dn_sig + 1;

		retval = write_rec(newfd, newp, recoff + st.st_size - recnext);
		if (retval != DSVC_SUCCESS)
			goto out;
	}

	/*
	 * Note: we close these descriptors before the rename(2) (rather
	 * than just having the `out:' label clean them up) to save NFS
	 * some work (otherwise, NFS has to save `dnpath' to an alternate
	 * name since its vnode would still be active).
	 */
	(void) close(fd);
	(void) close(newfd);

	if (rename(newpath, dnpath) == -1)
		retval = syserr_to_dsvcerr(errno);

	return (retval);
out:
	(void) close(fd);
	(void) close(newfd);
	(void) unlink(newpath);
	return (retval);
}