head	1.1;
access;
symbols
	experimental-1:1.1.0.4
	autoconf:1.1.0.2;
locks; strict;
comment	@ * @;


1.1
date	99.02.25.02.13.07;	author brianp;	state Exp;
branches;
next	;


desc
@@


1.1
log
@initial check-in
@
text
@
/* Copyright (c) Mark J. Kilgard, 1994. */

/*
 * (c) Copyright 1993, Silicon Graphics, Inc.
 * ALL RIGHTS RESERVED 
 * Permission to use, copy, modify, and distribute this software for 
 * any purpose and without fee is hereby granted, provided that the above
 * copyright notice appear in all copies and that both the copyright notice
 * and this permission notice appear in supporting documentation, and that 
 * the name of Silicon Graphics, Inc. not be used in advertising
 * or publicity pertaining to distribution of the software without specific,
 * written prior permission. 
 *
 * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
 * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
 * FITNESS Fdir,old_name,old_len,1,0,0,&sinfo);
	PRINTK(("vfat_rename 2\n"));
	if (res < 0) goto rename_done;

	old_slots = sinfo.total_slots;
	old_longname_offset = sinfo.longname_offset;
	old_offset = sinfo.shortname_offset;
	old_ino = sinfo.ino;
	res = fat_get_entry(old_dir, &old_offset, &old_bh, &old_de);
	PRINTK(("vfat_rename 3\n"));
	if (res < 0) goto rename_done;

	res = -ENOENT;
	if (!(old_inode = iget(old_dir->i_sb,old_ino)))
		goto rename_done;
	is_dir = S_ISDIR(old_inode->i_mode);
	if (must_be_dir && !is_dir)
		goto rename_done;
	if (is_dir) {
		if ((old_dir->i_dev != new_dir->i_dev) ||
		    (old_ino == new_dir->i_ino)) {
			res = -EINVAL;
			goto rename_done;
		}
		if (!(walk = iget(new_dir->i_sb,new_dir->i_ino))) return -EIO;
		/* prevent moving directory below itself */
		while (walk->i_ino != MSDOS_ROOT_INO) {
			ino = fat_parent_ino(walk,1);
			iput(walk);
			if (ino < 0) {
				res = ino;
				goto rename_done;
			}
			if (ino == old_ino) {
				res = -EINVAL;
				goto rename_done;
			}
			if (!(walk = iget(new_dir->i_sb,ino))) {
				res = -EIO;
				goto rename_done;
			}
		}
		iput(walk);
	}

	res = vfat_find(new_dir,new_name,new_len,1,0,is_dir,&sinfo);

	PRINTK(("vfat_rename 4\n"));
	if (res > -1) {
		int new_is_dir;

		PRINTK(("vfat_rename 5\n"));
		/* Filename currently exists.  Need to delete it */
		new_offset = sinfo.shortname_offset;
		res = fat_get_entry(new_dir, &new_offset, &new_bh, &new_de);
		PRINTK(("vfat_rename 6\n"));
		if (res < 0) goto rename_done;

		if (!(new_inode = iget(new_dir->i_sb,res)))
			goto rename_done;
		new_is_dir = S_ISDIR(new_inode->i_mode);
		iput(new_inode);
		if (new_is_dir) {
			PRINTK(("vfat_rename 7\n"));
			res = vfat_rmdirx(new_dir,new_name,new_len);
			PRINTK(("vfat_rename 8\n"));
			if (res < 0) goto rename_done;
		} else {
			/* Is this the same file, different case? */
			if (new_inode != old_inode) {
				PRINTK(("vfat_rename 9\n"));
				res = vfat_unlinkx(new_dir,new_name,new_len,1);
				PRINTK(("vfat_rename 10\n"));
				if (res < 0) goto rename_done;
			}
		}
	}

	PRINTK(("vfat_rename 11\n"));
	fat_lock_creation(); locked = 1;
	res = vfat_find(new_dir,new_name,new_len,1,1,is_dir,&sinfo);

	PRINTK(("vfat_rename 12\n"));
	if (res < 0) goto rename_done;

	new_offset = sinfo.shortname_offset;
	new_ino = sinfo.ino;
	res = fat_get_entry(new_dir, &new_offset, &new_bh, &new_de);
	PRINTK(("vfat_rename 13\n"));
	if (res < 0) goto rename_done;

	new_de->attr = old_de->attr;
	new_de->time = old_de->time;
	new_de->date = old_de->date;
	new_de->ctime_ms = old_de->ctime_ms;
	new_de->cdate = old_de->cdate;
	new_de->adate = old_de->adate;
	new_de->start = old_de->start;
	new_de->starthi = old_de->starthi;
	new_de->size = old_de->size;

	if (!(new_inode = iget(new_dir->i_sb,new_ino))) goto rename_done;
	PRINTK(("vfat_rename 14\n"));

	/* At this point, we have the inodes of the old file and the
	 * new file.  We need to transfer all information from the old
	 * inode to the new inode and then delete the slots of the old
	 * entry
	 */

	vfat_read_inode(new_inode);
	MSDOS_I(old_inode)->i_busy = 1;
	MSDOS_I(old_inode)->i_linked = new_inode;
	MSDOS_I(new_inode)->i_oldlink = old_inode;
	fat_cache_inval_inode(old_inode);
	PRINTK(("vfat_rename 15: old_slots=%d\n",old_slots));
	old_inode->i_dirt = 1;
	old_dir->i_version = ++event;

	/* remove the old entry */
	for (i = old_slots; i > 0; --i) {
		res = fat_get_entry(old_dir, &old_longname_offset, &old_