+ struct adouble *adp;
+ struct ofork *opened = NULL;
+ struct path path;
+ cnid_t id;
+
+ ad_init(&ad, vol->v_adouble, vol->v_ad_options);
+ adp = &ad;
+ adflags = 0;
+
+ if (!isdir) {
+ p = mtoupath(vol, oldname, sdir->d_did, utf8_encoding());
+ if (!p) {
+ return AFPERR_PARAM; /* can't convert */
+ }
+ id = cnid_get(vol->v_cdb, sdir->d_did, p, strlen(p));
+ p = ctoupath( vol, sdir, oldname );
+ if (!p) {
+ return AFPERR_PARAM; /* pathname too long */
+ }
+ path.st_valid = 0;
+ path.u_name = p;
+ if ((opened = of_findname(&path))) {
+ /* reuse struct adouble so it won't break locks */
+ adp = opened->of_ad;
+ }
+ }
+ else {
+ id = sdir->d_did; /* we already have the CNID */
+ p = ctoupath( vol, sdir->d_parent, oldname );
+ if (!p) {
+ return AFPERR_PARAM;
+ }
+ adflags = ADFLAGS_DIR;
+ }
+ /*
+ * p now points to the full pathname of the source fs object.
+ *
+ * we are in the dest folder so we need to use p for ad_open
+ */
+
+ if (!ad_metadata(p, adflags, adp)) {
+ u_int16_t bshort;
+
+ ad_getattr(adp, &bshort);
+ ad_close_metadata( adp);
+ if ((bshort & htons(ATTRBIT_NORENAME)))
+ return(AFPERR_OLOCK);
+ }
+
+ if (NULL == (upath = mtoupath(vol, newname, curdir->d_did, utf8_encoding()))){
+ return AFPERR_PARAM;
+ }
+ path.u_name = upath;
+ st = &path.st;
+ if (0 != (rc = check_name(vol, upath))) {
+ return rc;
+ }
+
+ /* source == destination. we just silently accept this. */
+ if ((!isdir && curdir == sdir) || (isdir && curdir == sdir->d_parent)) {
+ if (strcmp(oldname, newname) == 0)
+ return AFP_OK;
+
+ if (stat(upath, st) == 0 || caseenumerate(vol, &path, curdir) == 0) {
+ if (!stat(p, &nst) && !(nst.st_dev == st->st_dev && nst.st_ino == st->st_ino) ) {
+ /* not the same file */
+ return AFPERR_EXIST;
+ }
+ errno = 0;
+ }
+ } else if (stat(upath, st ) == 0 || caseenumerate(vol, &path, curdir) == 0)
+ return AFPERR_EXIST;
+
+ if ( !isdir ) {
+ path.st_valid = 1;
+ path.st_errno = errno;
+ if (of_findname(&path)) {
+ rc = AFPERR_EXIST; /* was AFPERR_BUSY; */
+ } else {
+ rc = renamefile(vol, p, upath, newname, adp );
+ if (rc == AFP_OK)
+ of_rename(vol, opened, sdir, oldname, curdir, newname);
+ }
+ } else {
+ rc = renamedir(vol, p, upath, sdir, curdir, newname);
+ }
+ if ( rc == AFP_OK && id ) {
+ /* renaming may have moved the file/dir across a filesystem */
+ if (stat(upath, st) < 0)
+ return AFPERR_MISC;
+
+ /* fix up the catalog entry */
+ cnid_update(vol->v_cdb, id, st, curdir->d_did, upath, strlen(upath));
+ }