Home | History | Annotate | Download | only in syscall
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License, Version 1.0 only
      6  * (the "License").  You may not use this file except in compliance
      7  * with the License.
      8  *
      9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10  * or http://www.opensolaris.org/os/licensing.
     11  * See the License for the specific language governing permissions
     12  * and limitations under the License.
     13  *
     14  * When distributing Covered Code, include this CDDL HEADER in each
     15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16  * If applicable, add the following below this CDDL HEADER, with the
     17  * fields enclosed by brackets "[]" replaced with your own identifying
     18  * information: Portions Copyright [yyyy] [name of copyright owner]
     19  *
     20  * CDDL HEADER END
     21  */
     22 /*
     23  * Copyright 2001 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
     28 /*	  All Rights Reserved  	*/
     29 
     30 /*
     31  * Portions of this source code were derived from Berkeley 4.3 BSD
     32  * under license from the Regents of the University of California.
     33  */
     34 
     35 #pragma ident	"@(#)rename.c	1.5	05/06/08 SMI"
     36 
     37 #include <sys/param.h>
     38 #include <sys/isa_defs.h>
     39 #include <sys/types.h>
     40 #include <sys/sysmacros.h>
     41 #include <sys/systm.h>
     42 #include <sys/errno.h>
     43 #include <sys/vnode.h>
     44 #include <sys/uio.h>
     45 #include <sys/debug.h>
     46 #include <sys/file.h>
     47 #include <sys/fcntl.h>
     48 
     49 /*
     50  * Rename or move an existing file.
     51  */
     52 int
     53 rename(char *from, char *to)
     54 {
     55 	int	error;
     56 
     57 	if (error = vn_rename(from, to, UIO_USERSPACE))
     58 		return (set_errno(error));
     59 	return (0);
     60 }
     61 
     62 /*
     63  * Rename a file relative to a given directory
     64  */
     65 int
     66 renameat(int fromfd, char *old, int tofd, char *new)
     67 {
     68 	file_t *fromfp;
     69 	file_t *tofp;
     70 	vnode_t	*fromvp, *tovp;
     71 	int error;
     72 	proc_t *p = curproc;
     73 	char oldstart, newstart;
     74 
     75 	tovp = fromvp = NULL;
     76 
     77 	if ((fromfd == AT_FDCWD && old == NULL) ||
     78 	    (tofd == AT_FDCWD && new == NULL))
     79 		return (set_errno(EFAULT));
     80 
     81 	if (fromfd == AT_FDCWD || tofd == AT_FDCWD) {
     82 		mutex_enter(&p->p_lock);
     83 		if (fromfd == AT_FDCWD) {
     84 			fromvp = PTOU(p)->u_cdir;
     85 			VN_HOLD(fromvp);
     86 		}
     87 		if (tofd == AT_FDCWD) {
     88 			tovp = PTOU(p)->u_cdir;
     89 			VN_HOLD(tovp);
     90 		}
     91 		mutex_exit(&p->p_lock);
     92 	}
     93 
     94 	if (copyin(old, &oldstart, sizeof (char)))
     95 		return (set_errno(EFAULT));
     96 
     97 	if (copyin(new, &newstart, sizeof (char)))
     98 		return (set_errno(EFAULT));
     99 
    100 	if (fromvp == NULL) {
    101 		if (oldstart != '/') {
    102 			if ((fromfp = getf(fromfd)) == NULL) {
    103 				if (tovp != NULL)
    104 					VN_RELE(tovp);
    105 				return (set_errno(EBADF));
    106 			}
    107 			fromvp = fromfp->f_vnode;
    108 			VN_HOLD(fromvp);
    109 			releasef(fromfd);
    110 		} else {
    111 			fromvp = NULL;
    112 		}
    113 	}
    114 
    115 	if (tovp == NULL) {
    116 		if (newstart != '/') {
    117 			if ((tofp = getf(tofd)) == NULL) {
    118 				if (fromvp != NULL)
    119 					VN_RELE(fromvp);
    120 				return (set_errno(EBADF));
    121 			}
    122 			tovp = tofp->f_vnode;
    123 			VN_HOLD(tovp);
    124 			releasef(tofd);
    125 		} else {
    126 			tovp = NULL;
    127 		}
    128 	}
    129 
    130 	error = vn_renameat(fromvp, old, tovp, new, UIO_USERSPACE);
    131 
    132 	if (fromvp != NULL)
    133 		VN_RELE(fromvp);
    134 	if (tovp != NULL)
    135 		VN_RELE(tovp);
    136 	if (error != 0)
    137 		return (set_errno(error));
    138 	return (error);
    139 }
    140