// File: /workspace/github_c_makefile_star2_O2/gadget114514[P]fatfs-example/fatfs/source/ff.c
// Function: f_rename
FRESULT f_rename (
	const TCHAR* path_old,	/* Pointer to the object name to be renamed */
	const TCHAR* path_new	/* Pointer to the new name */
)
{
	FRESULT res;
	DIR djo, djn;
	FATFS *fs;
	BYTE buf[FF_FS_EXFAT ? SZDIRE * 2 : SZDIRE], *dir;
	DWORD dw;
	DEF_NAMBUF


	get_ldnumber(&path_new);						/* Snip the drive number of new name off */
	res = find_volume(&path_old, &fs, FA_WRITE);	/* Get logical drive of the old object */
	if (res == FR_OK) {
		djo.obj.fs = fs;
		INIT_NAMBUF(fs);
		res = follow_path(&djo, path_old);		/* Check old object */
		if (res == FR_OK && (djo.fn[NSFLAG] & (NS_DOT | NS_NONAME))) res = FR_INVALID_NAME;	/* Check validity of name */
#if FF_FS_LOCK != 0
		if (res == FR_OK) {
			res = chk_lock(&djo, 2);
		}
#endif
		if (res == FR_OK) {						/* Object to be renamed is found */
#if FF_FS_EXFAT
			if (fs->fs_type == FS_EXFAT) {	/* At exFAT volume */
				BYTE nf, nn;
				WORD nh;

				mem_cpy(buf, fs->dirbuf, SZDIRE * 2);	/* Save 85+C0 entry of old object */
				mem_cpy(&djn, &djo, sizeof djo);
				res = follow_path(&djn, path_new);		/* Make sure if new object name is not in use */
				if (res == FR_OK) {						/* Is new name already in use by any other object? */
					res = (djn.obj.sclust == djo.obj.sclust && djn.dptr == djo.dptr) ? FR_NO_FILE : FR_EXIST;
				}
				if (res == FR_NO_FILE) { 				/* It is a valid path and no name collision */
					res = dir_register(&djn);			/* Register the new entry */
					if (res == FR_OK) {
						nf = fs->dirbuf[XDIR_NumSec]; nn = fs->dirbuf[XDIR_NumName];
						nh = ld_word(fs->dirbuf + XDIR_NameHash);
						mem_cpy(fs->dirbuf, buf, SZDIRE * 2);	/* Restore 85+C0 entry */
						fs->dirbuf[XDIR_NumSec] = nf; fs->dirbuf[XDIR_NumName] = nn;
						st_word(fs->dirbuf + XDIR_NameHash, nh);
						if (!(fs->dirbuf[XDIR_Attr] & AM_DIR)) fs->dirbuf[XDIR_Attr] |= AM_ARC;	/* Set archive attribute if it is a file */
/* Start of critical section where an interruption can cause a cross-link */
						res = store_xdir(&djn);
					}
				}
			} else
#endif
			{	/* At FAT/FAT32 volume */
				mem_cpy(buf, djo.dir, SZDIRE);			/* Save directory entry of the object */
				mem_cpy(&djn, &djo, sizeof (DIR));		/* Duplicate the directory object */
				res = follow_path(&djn, path_new);		/* Make sure if new object name is not in use */
				if (res == FR_OK) {						/* Is new name already in use by any other object? */
					res = (djn.obj.sclust == djo.obj.sclust && djn.dptr == djo.dptr) ? FR_NO_FILE : FR_EXIST;
				}
				if (res == FR_NO_FILE) { 				/* It is a valid path and no name collision */
					res = dir_register(&djn);			/* Register the new entry */
					if (res == FR_OK) {
						dir = djn.dir;					/* Copy directory entry of the object except name */
						mem_cpy(dir + 13, buf + 13, SZDIRE - 13);
						dir[DIR_Attr] = buf[DIR_Attr];
						if (!(dir[DIR_Attr] & AM_DIR)) dir[DIR_Attr] |= AM_ARC;	/* Set archive attribute if it is a file */
						fs->wflag = 1;
						if ((dir[DIR_Attr] & AM_DIR) && djo.obj.sclust != djn.obj.sclust) {	/* Update .. entry in the sub-directory if needed */
							dw = clst2sect(fs, ld_clust(fs, dir));
							if (dw == 0) {
								res = FR_INT_ERR;
							} else {
/* Start of critical section where an interruption can cause a cross-link */
								res = move_window(fs, dw);
								dir = fs->win + SZDIRE * 1;	/* Ptr to .. entry */
								if (res == FR_OK && dir[1] == '.') {
									st_clust(fs, dir, djn.obj.sclust);
									fs->wflag = 1;
								}
							}
						}
					}
				}
			}
			if (res == FR_OK) {
				res = dir_remove(&djo);		/* Remove old entry */
				if (res == FR_OK) {
					res = sync_fs(fs);
				}
			}
/* End of the critical section */
		}
		FREE_NAMBUF();
	}

	LEAVE_FF(fs, res);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0xe0, %rsp
leaq -0x38(%rbp), %rbx
movq %rdi, (%rbx)
leaq -0x30(%rbp), %rdi
movq %rsi, (%rdi)
callq 0x143f
leaq -0x28(%rbp), %rsi
pushq $0x2
popq %r14
movq %rbx, %rdi
movl %r14d, %edx
callq 0x1480
testl %eax, %eax
jne 0x37c9
movq -0x28(%rbp), %rbx
leaq -0xd8(%rbp), %r15
movq %rbx, (%r15)
movq -0x38(%rbp), %rsi
movq %r15, %rdi
callq 0x1a6d
movl %eax, %ecx
xorl %edx, %edx
testb $-0x60, 0x4b(%r15)
sete %sil
pushq $0x6
popq %rax
cmovel %edx, %eax
testl %ecx, %ecx
sete %dl
cmovnel %ecx, %eax
andb %sil, %dl
cmpb $0x1, %dl
jne 0x37c9
movq 0x38(%r15), %rsi
leaq -0x100(%rbp), %rdi
pushq $0x20
popq %rdx
callq 0x22ea
leaq -0x88(%rbp), %r12
pushq $0x50
popq %rdx
movq %r12, %rdi
movq %r15, %rsi
callq 0x22ea
movq -0x30(%rbp), %rsi
movq %r12, %rdi
callq 0x1a6d
cmpl $0x4, %eax
je 0x3761
testl %eax, %eax
jne 0x37c9
movq -0x78(%rbp), %rcx
pushq $0x8
popq %rax
cmpq -0xc8(%rbp), %rcx
jne 0x37c9
movq -0xb8(%rbp), %rcx
cmpq %rcx, -0x68(%rbp)
jne 0x37c9
leaq -0x88(%rbp), %rdi
callq 0x1d24
testl %eax, %eax
jne 0x37c9
movq -0x50(%rbp), %r12
leaq 0xd(%r12), %rdi
leaq -0xf3(%rbp), %r15
pushq $0x13
popq %rdx
movq %r15, %rsi
callq 0x22ea
movb -0x2(%r15), %al
movl %eax, %ecx
notb %cl
addb %cl, %cl
andb $0x20, %cl
orb %al, %cl
movb %cl, 0xb(%r12)
movb $0x1, 0x3(%rbx)
testb $0x10, 0xb(%r12)
je 0x37b9
movq -0x78(%rbp), %r15
cmpq %r15, -0xc8(%rbp)
jne 0x37f0
leaq -0xd8(%rbp), %rdi
callq 0x3366
testl %eax, %eax
je 0x37d9
addq $0xe0, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
movq %rbx, %rdi
addq $0xe0, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmp 0x281f
movzwl 0x1a(%r12), %esi
cmpb $0x3, (%rbx)
jne 0x3807
movzwl 0x14(%r12), %eax
shll $0x10, %eax
orq %rax, %rsi
movq %rbx, %rdi
callq 0x201a
movq %rax, %rsi
movl %r14d, %eax
testq %rsi, %rsi
je 0x37c9
movq %rbx, %rdi
callq 0x1e87
testl %eax, %eax
jne 0x37c9
cmpb $0x2e, 0x79(%rbx)
jne 0x37b9
leaq 0x78(%rbx), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x1dc1
movb $0x1, 0x3(%rbx)
jmp 0x37b9