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; }
/* * 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); }
/* * 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); }