X-Git-Url: https://arthur.barton.de/gitweb/?a=blobdiff_plain;f=etc%2Fafpd%2Ffile.c;h=bc336a4e2b0cd721c678402ad83bd65b9dce2cd1;hb=ff117107526219d5ce89d5ff683eddd414e40293;hp=07813ef4ccb05f51c8cab5fb4e87958a25fdf1fc;hpb=6655a7d0a550224642fc0f83320565d6e1123273;p=netatalk.git diff --git a/etc/afpd/file.c b/etc/afpd/file.c index 07813ef4..bc336a4e 100644 --- a/etc/afpd/file.c +++ b/etc/afpd/file.c @@ -77,6 +77,7 @@ static int default_type(void *finder) /* FIXME path : unix or mac name ? (for now it's unix name ) */ void *get_finderinfo(const struct vol *vol, const char *upath, struct adouble *adp, void *data, int islink) { + struct extmap *em; void *ad_finder = NULL; int chk_ext = 0; @@ -85,6 +86,9 @@ void *get_finderinfo(const struct vol *vol, const char *upath, struct adouble *a if (ad_finder) { memcpy(data, ad_finder, ADEDLEN_FINDERI); + /* default type ? */ + if (default_type(ad_finder)) + chk_ext = 1; } else { memcpy(data, ufinderi, ADEDLEN_FINDERI); @@ -105,6 +109,12 @@ void *get_finderinfo(const struct vol *vol, const char *upath, struct adouble *a memcpy((char *)data + FINDERINFO_FRCREATOFF,"rhap",4); } + /** Only enter if no appledouble information and no finder information found. */ + if (chk_ext && (em = getextmap( upath ))) { + memcpy(data, em->em_type, sizeof( em->em_type )); + memcpy((char *)data + 4, em->em_creator, sizeof(em->em_creator)); + } + return data; } @@ -119,7 +129,7 @@ char *set_name(const struct vol *vol, char *data, cnid_t pid, char *name, cnid_t if (!utf8) { /* want mac name */ - if (utf8_encoding()) { + if (utf8_encoding(vol->v_obj)) { /* but name is an utf8 mac name */ char *u, *m; @@ -239,32 +249,29 @@ restart: vol->v_path); vol->v_cdb = cnid_open(vol->v_path, vol->v_umask, "tdb", flags, NULL, NULL); if (vol->v_cdb) { - /* set ro mode*/ - vol->v_flags |= AFPVOL_RO; -#ifdef SERVERTEXT - /* kill ourself with SIGUSR2 aka msg pending */ - setmessage("Something wrong with the volume's CNID DB, using temporary CNID DB instead." - "Check server messages for details. Switching to read-only mode."); - kill(getpid(), SIGUSR2); -#endif - goto restart; /* not try again with the temp CNID db */ + if (!(vol->v_flags & AFPVOL_TM)) { + vol->v_flags |= AFPVOL_RO; + setmessage("Something wrong with the volume's CNID DB, using temporary CNID DB instead." + "Check server messages for details. Switching to read-only mode."); + kill(getpid(), SIGUSR2); + } + goto restart; /* now try again with the temp CNID db */ } else { -#ifdef SERVERTEXT setmessage("Something wrong with the volume's CNID DB, using temporary CNID DB failed too!" "Check server messages for details, can't recover from this state!"); -#endif } } afp_errno = AFPERR_MISC; goto exit; } } - else if (adp && (adcnid != dbcnid)) { /* 4 */ + else if (adp && adcnid && (adcnid != dbcnid)) { /* 4 */ /* Update the ressource fork. For a folder adp is always null */ LOG(log_debug, logtype_afpd, "get_id(%s/%s): calling ad_setid(old: %u, new: %u)", getcwdpath(), upath, htonl(adcnid), htonl(dbcnid)); if (ad_setid(adp, st->st_dev, st->st_ino, dbcnid, did, vol->v_stamp)) { - ad_flush(adp); + if (ad_flush(adp) != 0) + LOG(log_error, logtype_afpd, "get_id(\"%s\"): can't flush", fullpathname(upath)); } } } @@ -299,7 +306,7 @@ int getmetadata(const AFPObj *obj, data = buf; if ( ((bitmap & ( (1 << FILPBIT_FINFO)|(1 << FILPBIT_LNAME)|(1 <m_name) - || (bitmap & ( (1 << FILPBIT_LNAME) ) && utf8_encoding()) /* FIXME should be m_name utf8 filename */ + || (bitmap & ( (1 << FILPBIT_LNAME) ) && utf8_encoding(obj)) /* FIXME should be m_name utf8 filename */ || (bitmap & (1 << FILPBIT_FNUM))) { if (!path->id) { bstring fullpath; @@ -316,7 +323,7 @@ int getmetadata(const AFPObj *obj, /* Get macname from unixname first */ if (path->m_name == NULL) { - if ((path->m_name = utompath(vol, upath, id, utf8_encoding())) == NULL) { + if ((path->m_name = utompath(vol, upath, id, utf8_encoding(obj))) == NULL) { LOG(log_error, logtype_afpd, "getmetadata: utompath error"); return AFPERR_MISC; } @@ -348,7 +355,7 @@ int getmetadata(const AFPObj *obj, return afp_errno; if (!path->m_name) { - path->m_name = utompath(vol, upath, id, utf8_encoding()); + path->m_name = utompath(vol, upath, id, utf8_encoding(vol->v_obj)); } } while ( bitmap != 0 ) { @@ -467,7 +474,7 @@ int getmetadata(const AFPObj *obj, to "pXYZ" when we created it. See IA, Ver 2. */ case FILPBIT_PDINFO : - if (afp_version >= 30) { /* UTF8 name */ + if (obj->afp_version >= 30) { /* UTF8 name */ utf8 = kTextEncodingUTF8; utf_nameoff = data; data += sizeof( uint16_t ); @@ -591,11 +598,8 @@ int getmetadata(const AFPObj *obj, } /* ----------------------- */ -int getfilparams(const AFPObj *obj, - struct vol *vol, - uint16_t bitmap, - struct path *path, struct dir *dir, - char *buf, size_t *buflen ) +int getfilparams(const AFPObj *obj, struct vol *vol, uint16_t bitmap, struct path *path, + struct dir *dir, char *buf, size_t *buflen, int in_enumerate) { struct adouble ad, *adp; int opened = 0; @@ -609,7 +613,12 @@ int getfilparams(const AFPObj *obj, if (opened) { char *upath; - flags = (bitmap & (1 << FILPBIT_ATTR)) ? ADFLAGS_CHECK_OF : 0; + /* + * Dont check for and resturn open fork attributes when enumerating + * This saves a lot of syscalls, the client will hopefully only use the result + * in FPGetFileParms where we return the correct value + */ + flags = (!in_enumerate &&(bitmap & (1 << FILPBIT_ATTR))) ? ADFLAGS_CHECK_OF : 0; adp = of_ad(vol, path, &ad); upath = path->u_name; @@ -702,6 +711,7 @@ int afp_createfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, return( AFPERR_ACCESS ); case EDQUOT: case ENOSPC : + LOG(log_info, logtype_afpd, "afp_createfile: DISK FULL"); return( AFPERR_DFULL ); default : return( AFPERR_PARAM ); @@ -727,11 +737,17 @@ int afp_createfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, return AFPERR_MISC; } - (void)get_id(vol, &ad, &st, dir->d_did, upath, strlen(upath)); + cnid_t id; + if ((id = get_id(vol, &ad, &st, dir->d_did, upath, strlen(upath))) == CNID_INVALID) { + LOG(log_error, logtype_afpd, "afp_createfile(\"%s\"): CNID error", upath); + goto createfile_iderr; + } + (void)ad_setid(&ad, st.st_dev, st.st_ino, id, dir->d_did, vol->v_stamp); +createfile_iderr: ad_flush(&ad); ad_close(&ad, ADFLAGS_DF|ADFLAGS_HF ); - fce_register_new_file(s_path); + fce_register(FCE_FILE_CREATE, fullpathname(upath), NULL, fce_file); createfile_done: curdir->d_offcnt++; @@ -822,7 +838,7 @@ int setfilparams(const AFPObj *obj, struct vol *vol, uint16_t bitmap = f_bitmap; uint32_t cdate,bdate; u_char finder_buf[32]; - int symlinked = 0; + int symlinked = S_ISLNK(path->st.st_mode); #ifdef DEBUG LOG(log_debug9, logtype_afpd, "begin setfilparams:"); @@ -919,7 +935,7 @@ int setfilparams(const AFPObj *obj, struct vol *vol, } break; case FILPBIT_PDINFO : - if (afp_version < 30) { /* else it's UTF8 name */ + if (obj->afp_version < 30) { /* else it's UTF8 name */ achar = *buf; buf += 2; /* Keep special case to support crlf translations */ @@ -996,6 +1012,17 @@ int setfilparams(const AFPObj *obj, struct vol *vol, ad_setdate(adp, AD_DATE_BACKUP, bdate); break; case FILPBIT_FINFO : + if (default_type( ad_entry( adp, ADEID_FINDERI )) + && ( + ((em = getextmap( path->m_name )) && + !memcmp(finder_buf, em->em_type, sizeof( em->em_type )) && + !memcmp(finder_buf + 4, em->em_creator,sizeof( em->em_creator))) + || ((em = getdefextmap()) && + !memcmp(finder_buf, em->em_type, sizeof( em->em_type )) && + !memcmp(finder_buf + 4, em->em_creator,sizeof( em->em_creator))) + )) { + memcpy(finder_buf, ufinderi, 8 ); + } memcpy(ad_entry( adp, ADEID_FINDERI ), finder_buf, 32 ); break; case FILPBIT_UNIXPR : @@ -1004,7 +1031,7 @@ int setfilparams(const AFPObj *obj, struct vol *vol, } break; case FILPBIT_PDINFO : - if (afp_version < 30) { /* else it's UTF8 name */ + if (obj->afp_version < 30) { /* else it's UTF8 name */ memcpy(ad_entry( adp, ADEID_FINDERI ), fdType, 4 ); memcpy(ad_entry( adp, ADEID_FINDERI ) + 4, "pdos", 4 ); break; @@ -1058,7 +1085,7 @@ setfilparam_done: * adp adouble struct of src file, if open, or & zeroed one * */ -int renamefile(const struct vol *vol, int sdir_fd, char *src, char *dst, char *newname, struct adouble *adp) +int renamefile(struct vol *vol, struct dir *ddir, int sdir_fd, char *src, char *dst, char *newname, struct adouble *adp) { int rc; @@ -1083,7 +1110,7 @@ int renamefile(const struct vol *vol, int sdir_fd, char *src, char *dst, char *n /* FIXME warning in syslog so admin'd know there's a conflict ?*/ return AFPERR_OLOCK; /* little lie */ } - if (AFP_OK != ( rc = copyfile(vol, vol, sdir_fd, src, dst, newname, NULL )) ) { + if (AFP_OK != ( rc = copyfile(vol, vol, ddir, sdir_fd, src, dst, newname, NULL )) ) { /* on error copyfile delete dest */ return( rc ); } @@ -1148,14 +1175,14 @@ size_t plen = 0; uint16_t len16; uint32_t hint; - if ( type != 2 && !(afp_version >= 30 && type == 3) ) { + if ( type != 2 && !(vol->v_obj->afp_version >= 30 && type == 3) ) { return -1; } ibuf++; switch (type) { case 2: if (( plen = (unsigned char)*ibuf++ ) != 0 ) { - if (afp_version >= 30) { + if (vol->v_obj->afp_version >= 30) { /* convert it to UTF8 */ if ((plen = mtoUTF8(vol, ibuf, plen, newname, AFPOBJ_TMPSIZ)) == (size_t)-1) @@ -1249,6 +1276,19 @@ int afp_copyfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, si if (ad_open(adp, s_path->u_name, ADFLAGS_DF | ADFLAGS_HF | ADFLAGS_NOHF | ADFLAGS_RDONLY | ADFLAGS_SETSHRMD) < 0) { return AFPERR_DENYCONF; } +#ifdef HAVE_FSHARE_T + fshare_t shmd; + shmd.f_access = F_RDACC; + shmd.f_deny = F_NODNY; + if (fcntl(ad_data_fileno(adp), F_SHARE, &shmd) != 0) { + retvalue = AFPERR_DENYCONF; + goto copy_exit; + } + if (AD_RSRC_OPEN(adp) && fcntl(ad_reso_fileno(adp), F_SHARE, &shmd) != 0) { + retvalue = AFPERR_DENYCONF; + goto copy_exit; + } +#endif denyreadset = (ad_testlock(adp, ADEID_DFORK, AD_FILELOCK_DENY_RD) != 0 || ad_testlock(adp, ADEID_RFORK, AD_FILELOCK_DENY_RD) != 0 ); @@ -1299,12 +1339,12 @@ int afp_copyfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, si /* newname is always only a filename so curdir *is* its * parent folder */ - if (NULL == (upath = mtoupath(d_vol, newname, curdir->d_did, utf8_encoding()))) { + if (NULL == (upath = mtoupath(d_vol, newname, curdir->d_did, utf8_encoding(d_vol->v_obj)))) { retvalue =AFPERR_PARAM; goto copy_exit; } - if ( (err = copyfile(s_vol, d_vol, -1, p, upath , newname, adp)) < 0 ) { + if ( (err = copyfile(s_vol, d_vol, curdir, -1, p, upath , newname, adp)) < 0 ) { retvalue = err; goto copy_exit; } @@ -1322,8 +1362,9 @@ copy_exit: * because we are doing it elsewhere. * currently if newname is NULL then adp is NULL. */ -int copyfile(const struct vol *s_vol, - const struct vol *d_vol, +int copyfile(struct vol *s_vol, + struct vol *d_vol, + struct dir *d_dir, int sfd, char *src, char *dst, @@ -1345,13 +1386,17 @@ int copyfile(const struct vol *s_vol, adp = &ads; } - adflags = ADFLAGS_DF | ADFLAGS_RF | ADFLAGS_NORF; + adflags = ADFLAGS_DF | ADFLAGS_HF | ADFLAGS_NOHF | ADFLAGS_RF | ADFLAGS_NORF; if (ad_openat(adp, sfd, src, adflags | ADFLAGS_RDONLY) < 0) { ret_err = errno; goto done; } + if (!AD_META_OPEN(adp)) + /* no resource fork, don't create one for dst file */ + adflags &= ~ADFLAGS_HF; + if (!AD_RSRC_OPEN(adp)) /* no resource fork, don't create one for dst file */ adflags &= ~ADFLAGS_RF; @@ -1384,12 +1429,25 @@ int copyfile(const struct vol *s_vol, if (err < 0) ret_err = errno; - if (!ret_err && newname && (adflags & ADFLAGS_HF)) { - /* set the new name in the resource fork */ - ad_copy_header(&add, adp); - ad_setname(&add, newname); - ad_flush( &add ); + if (AD_META_OPEN(&add)) { + if (AD_META_OPEN(adp)) + ad_copy_header(&add, adp); + ad_setname(&add, dst); + cnid_t id; + struct stat stdest; + if (fstat(ad_meta_fileno(&add), &stdest) != 0) { + ret_err = errno; + goto error; + } + if ((id = get_id(d_vol, &add, &stdest, d_dir->d_did, dst, strlen(dst))) == CNID_INVALID) { + ret_err = EINVAL; + goto error; + } + (void)ad_setid(&add, stdest.st_dev, stdest.st_ino, id, d_dir->d_did, d_vol->v_stamp); + ad_flush(&add); } + +error: ad_close( adp, adflags ); if (ad_close( &add, adflags ) <0) { @@ -1417,6 +1475,7 @@ done: case EDQUOT: case EFBIG: case ENOSPC: + LOG(log_info, logtype_afpd, "copyfile: DISK FULL"); return AFPERR_DFULL; case ENOENT: return AFPERR_NOOBJ; @@ -1676,7 +1735,7 @@ reenumerate_id(struct vol *vol, char *name, struct dir *dir) /* ------------------------------ resolve a file id */ -int afp_resolveid(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) +int afp_resolveid(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) { struct vol *vol; struct dir *dir; @@ -1762,17 +1821,17 @@ retry: /* directories are bad */ if (S_ISDIR(path.st.st_mode)) { /* OS9 and OSX don't return the same error code */ - return (afp_version >=30)?AFPERR_NOID:AFPERR_BADTYPE; + return (obj->afp_version >=30)?AFPERR_NOID:AFPERR_BADTYPE; } memcpy(&bitmap, ibuf, sizeof(bitmap)); bitmap = ntohs( bitmap ); - if (NULL == (path.m_name = utompath(vol, upath, cnid, utf8_encoding()))) { + if (NULL == (path.m_name = utompath(vol, upath, cnid, utf8_encoding(obj)))) { return AFPERR_NOID; } path.id = cnid; if (AFP_OK != (err = getfilparams(obj, vol, bitmap, &path , curdir, - rbuf + sizeof(bitmap), &buflen))) { + rbuf + sizeof(bitmap), &buflen, 0))) { return err; } *rbuflen = buflen + sizeof(bitmap); @@ -1934,9 +1993,6 @@ int afp_exchangefiles(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U uint32_t sid, did; uint16_t vid; - uid_t uid; - gid_t gid; - *rbuflen = 0; ibuf += 2; @@ -2052,17 +2108,17 @@ int afp_exchangefiles(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U } /* now, quickly rename the file. we error if we can't. */ - if ((err = renamefile(vol, -1, p, temp, temp, adsp)) != AFP_OK) + if ((err = renamefile(vol, curdir, -1, p, temp, temp, adsp)) != AFP_OK) goto err_exchangefile; of_rename(vol, s_of, sdir, spath, curdir, temp); /* rename destination to source */ - if ((err = renamefile(vol, -1, upath, p, spath, addp)) != AFP_OK) + if ((err = renamefile(vol, curdir, -1, upath, p, spath, addp)) != AFP_OK) goto err_src_to_tmp; of_rename(vol, d_of, curdir, path->m_name, sdir, spath); /* rename temp to destination */ - if ((err = renamefile(vol, -1, temp, upath, path->m_name, adsp)) != AFP_OK) + if ((err = renamefile(vol, curdir, -1, temp, upath, path->m_name, adsp)) != AFP_OK) goto err_dest_to_src; of_rename(vol, s_of, curdir, temp, curdir, path->m_name); @@ -2104,13 +2160,7 @@ int afp_exchangefiles(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U /* change perms, src gets dest perm and vice versa */ - uid = geteuid(); - gid = getegid(); - if (seteuid(0)) { - LOG(log_error, logtype_afpd, "seteuid failed %s", strerror(errno)); - err = AFP_OK; /* ignore error */ - goto err_temp_to_dest; - } + become_root(); /* * we need to exchange ACL entries as well @@ -2134,10 +2184,7 @@ int afp_exchangefiles(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U setfilunixmode(vol, path, srcst.st_mode); setfilowner(vol, srcst.st_uid, srcst.st_gid, path); - if ( setegid(gid) < 0 || seteuid(uid) < 0) { - LOG(log_error, logtype_afpd, "can't seteuid back %s", strerror(errno)); - exit(EXITERR_SYS); - } + unbecome_root(); err = AFP_OK; goto err_exchangefile; @@ -2146,17 +2193,17 @@ int afp_exchangefiles(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U * properly. */ err_temp_to_dest: /* rename dest to temp */ - renamefile(vol, -1, upath, temp, temp, adsp); + renamefile(vol, curdir, -1, upath, temp, temp, adsp); of_rename(vol, s_of, curdir, upath, curdir, temp); err_dest_to_src: /* rename source back to dest */ - renamefile(vol, -1, p, upath, path->m_name, addp); + renamefile(vol, curdir, -1, p, upath, path->m_name, addp); of_rename(vol, d_of, sdir, spath, curdir, path->m_name); err_src_to_tmp: /* rename temp back to source */ - renamefile(vol, -1, temp, p, spath, adsp); + renamefile(vol, curdir, -1, temp, p, spath, adsp); of_rename(vol, s_of, curdir, temp, sdir, spath); err_exchangefile: