vol->v_path);
vol->v_cdb = cnid_open(vol->v_path, vol->v_umask, "tdb", flags, NULL, NULL);
if (vol->v_cdb) {
- /* deactivate cnid caching/storing in AppleDouble files and set ro mode*/
- vol->v_flags &= ~AFPVOL_CACHE;
+ /* set ro mode*/
vol->v_flags |= AFPVOL_RO;
#ifdef SERVERTEXT
/* kill ourself with SIGUSR2 aka msg pending */
options[VOLOPT_FLAGS].i_value |= AFPVOL_CASEINSEN;
else if (strcasecmp(p, "illegalseq") == 0)
options[VOLOPT_FLAGS].i_value |= AFPVOL_EILSEQ;
- else if (strcasecmp(p, "nocnidcache") == 0)
- options[VOLOPT_FLAGS].i_value &= ~AFPVOL_CACHE;
else if (strcasecmp(p, "tm") == 0)
options[VOLOPT_FLAGS].i_value |= AFPVOL_TM;
else if (strcasecmp(p, "searchdb") == 0)
volume->v_ad_options = 0;
if ((volume->v_flags & AFPVOL_NODEV))
volume->v_ad_options |= ADVOL_NODEV;
- if ((volume->v_flags & AFPVOL_CACHE))
- volume->v_ad_options |= ADVOL_CACHE;
if ((volume->v_flags & AFPVOL_UNIX_PRIV))
volume->v_ad_options |= ADVOL_UNIXPRIV;
if ((volume->v_flags & AFPVOL_INV_DOTS))
memset(default_options, 0, sizeof(default_options));
/* Enable some default options for all volumes */
- default_options[VOLOPT_FLAGS].i_value |= AFPVOL_CACHE;
#ifdef HAVE_ACLS
default_options[VOLOPT_FLAGS].i_value |= AFPVOL_ACLS;
#endif
"Check server messages for details!");
kill(getpid(), SIGUSR2);
/* deactivate cnid caching/storing in AppleDouble files */
- volume->v_flags &= ~AFPVOL_CACHE;
}
#endif
}
GNU General Public License for more details.
*/
-/*
- dbd specs and implementation progress
- =====================================
-
- St := Status
-
- Force option
- ------------
-
- St Spec
- -- ----
- OK If -f is requested, ensure -e is too.
- Check if volumes is using AFPVOL_CACHE, then wipe db from disk. Rebuild from ad-files.
-
- 1st pass: Scan volume
- --------------------
-
- St Type Check
- -- ---- -----
- OK F/D Make sure ad file exists
- OK D Make sure .AppleDouble dir exist, create if missing. Error creating
- it is fatal as that shouldn't happen as root.
- OK F/D Delete orphaned ad-files, log dirs in ad-dir
- OK F/D Check name encoding by roundtripping, log on error
- OK F/D try: read CNID from ad file (if cnid caching is on)
- try: fetch CNID from database
- -> on mismatch: use CNID from file, update database (deleting both found CNIDs first)
- -> if no CNID in ad file: write CNID from database to ad file
- -> if no CNID in database: add CNID from ad file to database
- -> on no CNID at all: create one and store in both places
- OK F/D Add found CNID, DID, filename, dev/inode, stamp to rebuild database
- OK F/D Check/update stamp (implicitly done while checking CNIDs)
-
-
- 2nd pass: Delete unused CNIDs
- -----------------------------
-
- St Spec
- -- ----
- OK Step through dbd (the one on disk) and rebuild-db from pass 1 and delete any CNID from
- dbd not in rebuild db. This in only done in exclusive mode.
-*/
-
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
}
/* Check if -f is requested and wipe db if yes */
- if ((flags & DBD_FLAGS_FORCE) && rebuild && (volinfo.v_flags & AFPVOL_CACHE)) {
+ if ((flags & DBD_FLAGS_FORCE) && rebuild) {
char cmd[8 + MAXPATHLEN];
if ((db_locked = get_lock(LOCK_FREE, NULL)) != 0)
goto exit_noenv;
return( upath );
}
-#if 0
-/*
- Check if "name" is pointing to
- a) an object inside the current volume (return 0)
- b) an object outside the current volume (return 1)
- Then stats the pointed to object and if it is a dir ors ADFLAGS_DIR to *adflags
- Return -1 on any serious error.
- */
-static int check_symlink(const char *name, int *adflags)
-{
- int cwd;
- ssize_t len;
- char pathbuf[MAXPATHLEN + 1];
- char *sep;
- struct stat st;
-
- if ((len = readlink(name, pathbuf, MAXPATHLEN)) == -1) {
- dbd_log(LOGSTD, "Error reading link info for '%s/%s': %s",
- cwdbuf, name, strerror(errno));
- return -1;
- }
- pathbuf[len] = 0;
-
- if ((stat(pathbuf, &st)) != 0) {
- dbd_log(LOGSTD, "stat error '%s': %s", pathbuf, strerror(errno));
- }
-
- /* Remember cwd */
- if ((cwd = open(".", O_RDONLY)) < 0) {
- dbd_log(LOGSTD, "error opening cwd '%s': %s", cwdbuf, strerror(errno));
- return -1;
- }
-
- if (S_ISDIR(st.st_mode)) {
- *adflags |= ADFLAGS_DIR;
- } else { /* file */
- /* get basename from path */
- if ((sep = strrchr(pathbuf, '/')) == NULL)
- /* just a file at the same level */
- return 0;
- sep = 0; /* pathbuf now contains the directory*/
- }
-
- /* fchdir() to pathbuf so we can easily get its path with getcwd() */
- if ((chdir(pathbuf)) != 0) {
- dbd_log(LOGSTD, "Cant chdir to '%s': %s", pathbuf, strerror(errno));
- return -1;
- }
-
- if ((getcwd(pathbuf, MAXPATHLEN)) == NULL) {
- dbd_log(LOGSTD, "Cant get symlink'ed dir '%s/%s': %s", cwdbuf, pathbuf, strerror(errno));
- if ((fchdir(cwd)) != 0)
- /* We're foobared */
- longjmp(jmp, 1); /* this jumps back to cmd_dbd_scanvol() */
- return -1;
- }
-
- if ((fchdir(cwd)) != 0)
- /* We're foobared */
- longjmp(jmp, 1); /* this jumps back to cmd_dbd_scanvol() */
-
- /*
- We now have the symlink target dir as absoulte path in pathbuf
- and can compare it with the currents volume path
- */
- int i = 0;
- while (myvolinfo->v_path[i]) {
- if ((pathbuf[i] == 0) || (myvolinfo->v_path[i] != pathbuf[i])) {
- dbd_log( LOGDEBUG, "extra-share symlink '%s/%s', following", cwdbuf, name);
- return 1;
- }
- i++;
- }
-
- dbd_log( LOGDEBUG, "intra-share symlink '%s/%s', not following", cwdbuf, name);
- return 0;
-}
-#endif
-
/*
Check for wrong encoding e.g. "." at the beginning is not CAP encoded (:2e) although volume is default !AFPVOL_USEDOTS.
We do it by roundtripiping from volcharset to UTF8-MAC and back and then compare the result.
struct adouble ad;
const char *adname;
+ if (volume.v_adouble == AD_VERSION_EA)
+ return 0;
+
if (dbd_flags & DBD_FLAGS_CLEANUP)
return 0;
if (dbd_flags & DBD_FLAGS_CLEANUP)
return 0;
+ if (volume.v_adouble == AD_VERSION_EA)
+ return 0;
+
/* Check for ad-dir */
if ( (addir_ok = access(ADv2_DIRNAME, F_OK)) != 0) {
if (errno != ENOENT) {
dbd_log(LOGSTD, "Missing %s for '%s'", ADv2_DIRNAME, cwdbuf);
}
+ if (volume.v_adouble == AD_VERSION_EA)
+ return 0;
+
/* Check for ".Parent" */
if ( (adpar_ok = access(myvolinfo->ad_path(".", ADFLAGS_DIR), F_OK)) != 0) {
if (errno != ENOENT) {
struct dirent *ep;
struct stat st;
+ if (volume.v_adouble == AD_VERSION_EA)
+ return 0;
+
if ((chdir(ADv2_DIRNAME)) != 0) {
dbd_log(LOGSTD, "Couldn't chdir to '%s/%s': %s",
cwdbuf, ADv2_DIRNAME, strerror(errno));
/* Check if its "." or ".." */
if (DIR_DOT_OR_DOTDOT(ep->d_name))
continue;
+
/* Skip ".Parent" */
if (STRCMP(ep->d_name, ==, ".Parent"))
continue;
}
}
- /* Get CNID from ad-file if volume is using AFPVOL_CACHE */
+ /* Get CNID from ad-file */
ad_cnid = 0;
- if ( (myvolinfo->v_flags & AFPVOL_CACHE) && ADFILE_OK) {
+ if (ADFILE_OK) {
ad_init_old(&ad, myvolinfo->v_adouble, myvolinfo->v_ad_options);
if (ad_open(&ad, name, adflags | ADFLAGS_RDWR) != 0) {
db_cnid = rply.cnid;
dbd_log(LOGSTD, "New CNID for '%s/%s': %u", cwdbuf, name, ntohl(db_cnid));
- if ((myvolinfo->v_flags & AFPVOL_CACHE)
- && ADFILE_OK
- && ( ! (dbd_flags & DBD_FLAGS_SCAN))) {
+ if (ADFILE_OK && ( ! (dbd_flags & DBD_FLAGS_SCAN))) {
dbd_log(LOGSTD, "Writing CNID data for '%s/%s' to AppleDouble file",
cwdbuf, name, ntohl(db_cnid));
ad_init_old(&ad, myvolinfo->v_adouble, myvolinfo->v_ad_options);
}
if ((ad_cnid == 0) && db_cnid) {
- /* in db but zeroID in ad-file, write it to ad-file if AFPVOL_CACHE */
- if ((myvolinfo->v_flags & AFPVOL_CACHE) && ADFILE_OK) {
+ /* in db but zeroID in ad-file, write it to ad-file */
+ if (ADFILE_OK) {
if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
dbd_log(LOGSTD, "Writing CNID data for '%s/%s' to AppleDouble file",
cwdbuf, name, ntohl(db_cnid));
return -1;
/* Check AppleDouble files in AppleDouble folder, but only if it exists or could be created */
- if (ADDIR_OK)
+ if (volume.v_adouble == AD_VERSION2 && ADDIR_OK)
if ((read_addir()) != 0)
if ( ! (dbd_flags & DBD_FLAGS_SCAN))
/* Fatal on rebuild run, continue if only scanning ! */
break;
case S_IFLNK:
dbd_log(LOGDEBUG, "Ignoring symlink %s/%s", cwdbuf, ep->d_name);
-#if 0
- ret = check_symlink(ep->d_name, &adflags);
- if (ret == 1)
- break;
- if (ret == -1)
- dbd_log(LOGSTD, "Error checking symlink %s/%s", cwdbuf, ep->d_name);
-#endif
continue;
default:
dbd_log(LOGSTD, "Bad filetype: %s/%s", cwdbuf, ep->d_name);
dbd_flags = flags;
/* Init a fake struct vol with just enough so we can call ea_open and friends */
- volume.v_adouble = AD_VERSION2;
+ volume.v_adouble = vi->v_adouble;
volume.v_vfs_ea = myvolinfo->v_vfs_ea;
initvol_vfs(&volume);
CNID salvation spec:
general rule: better safe then sorry, so we always delete CNIDs and assign
new ones in case of a lookup mismatch. afpd also sends us the CNID found
-in the adouble file (for AFPVOL_CACHE volumes). In certain cases we can
-use this hint to determince the right CNID.
+in the adouble file. In certain cases we can use this hint to determince
+the right CNID.
The lines...
#define ADEDLEN_PRIVID 4
#define ADEID_NUM_V2 13
-#define ADEID_NUM_EA 5
+#define ADEID_NUM_EA 8
#define ADEID_NUM_OSX 2
#define AD_DATASZ2 (AD_HEADER_LEN + ADEDLEN_NAME + ADEDLEN_COMMENT + ADEDLEN_FILEI + \
#error bad size for AD_DATASZ2
#endif
-#define AD_DATASZ_EA (AD_HEADER_LEN + (ADEID_NUM_EA * AD_ENTRY_LEN) + ADEDLEN_FINDERI + \
- ADEDLEN_COMMENT + ADEDLEN_FILEDATESI + ADEDLEN_AFPFILEI + ADEDLEN_PRIVID)
+#define AD_DATASZ_EA (AD_HEADER_LEN + (ADEID_NUM_EA * AD_ENTRY_LEN) + \
+ ADEDLEN_FINDERI + ADEDLEN_COMMENT + ADEDLEN_FILEDATESI + ADEDLEN_AFPFILEI + \
+ ADEDLEN_PRIVDEV + ADEDLEN_PRIVINO + ADEDLEN_PRIVSYN + ADEDLEN_PRIVID)
-#if AD_DATASZ_EA != 342
+#if AD_DATASZ_EA != 402
#error bad size for AD_DATASZ_EA
#endif
#define ADFLAGS_TRUNC (1<<12) /* truncate, open called with O_TRUNC */
#define ADVOL_NODEV (1 << 0)
-#define ADVOL_CACHE (1 << 1)
#define ADVOL_UNIXPRIV (1 << 2) /* adouble unix priv */
#define ADVOL_INVDOTS (1 << 3) /* dot files (.DS_Store) are invisible) */
#define AFPVOL_CASEINSEN (1 << 19) /* volume is case insensitive */
#define AFPVOL_EILSEQ (1 << 20) /* encode illegal sequence 'asis' UCS2, ex "\217-", which is not
a valid SHIFT-JIS char, is encoded as U\217 -*/
-
-#define AFPVOL_CACHE (1 << 21) /* Use adouble v2 CNID caching. Default: yes */
#define AFPVOL_INV_DOTS (1 << 22) /* dots files are invisible */
#define AFPVOL_TM (1 << 23) /* Supports TimeMachine */
#define AFPVOL_ACLS (1 << 24) /* Volume supports ACLS */
tmp = htonl(tmp);
memcpy(ad_entry( adp, ADEID_PRIVID ), &tmp, sizeof(tmp));
- if (adp->ad_vers == AD_VERSION2) {
- ad_setentrylen( adp, ADEID_PRIVDEV, sizeof(dev_t));
- if ((adp->ad_options & ADVOL_NODEV)) {
- memset(ad_entry( adp, ADEID_PRIVDEV ), 0, sizeof(dev_t));
- } else {
- memcpy(ad_entry( adp, ADEID_PRIVDEV ), &dev, sizeof(dev_t));
- }
+ ad_setentrylen( adp, ADEID_PRIVDEV, sizeof(dev_t));
+ if ((adp->ad_options & ADVOL_NODEV)) {
+ memset(ad_entry( adp, ADEID_PRIVDEV ), 0, sizeof(dev_t));
+ } else {
+ memcpy(ad_entry( adp, ADEID_PRIVDEV ), &dev, sizeof(dev_t));
+ }
- ad_setentrylen( adp, ADEID_PRIVINO, sizeof(ino_t));
- memcpy(ad_entry( adp, ADEID_PRIVINO ), &ino, sizeof(ino_t));
+ ad_setentrylen( adp, ADEID_PRIVINO, sizeof(ino_t));
+ memcpy(ad_entry( adp, ADEID_PRIVINO ), &ino, sizeof(ino_t));
- ad_setentrylen( adp, ADEID_DID, sizeof(did));
- memcpy(ad_entry( adp, ADEID_DID ), &did, sizeof(did));
+ ad_setentrylen( adp, ADEID_DID, sizeof(did));
+ memcpy(ad_entry( adp, ADEID_DID ), &did, sizeof(did));
+
+ ad_setentrylen( adp, ADEID_PRIVSYN, ADEDLEN_PRIVSYN);
+ memcpy(ad_entry( adp, ADEID_PRIVSYN ), stamp, ADEDLEN_PRIVSYN);
- ad_setentrylen( adp, ADEID_PRIVSYN, ADEDLEN_PRIVSYN);
- memcpy(ad_entry( adp, ADEID_PRIVSYN ), stamp, ADEDLEN_PRIVSYN);
- }
return 1;
}
char temp[ADEDLEN_PRIVSYN];
if (adp) {
- if ((adp->ad_vers == AD_VERSION2)
- && (sizeof(dev_t) == ad_getentrylen(adp, ADEID_PRIVDEV))) {
+ if (sizeof(dev_t) == ad_getentrylen(adp, ADEID_PRIVDEV)) {
memcpy(&dev, ad_entry(adp, ADEID_PRIVDEV), sizeof(dev_t));
memcpy(&ino, ad_entry(adp, ADEID_PRIVINO), sizeof(ino_t));
memcpy(temp, ad_entry(adp, ADEID_PRIVSYN), sizeof(temp));
memcpy(&a_did, ad_entry(adp, ADEID_DID), sizeof(cnid_t));
- if ( ((adp->ad_options & ADVOL_NODEV) || dev == st_dev)
- && ino == st_ino
- && (!did || a_did == did)
- && (memcmp(stamp, temp, sizeof(temp)) == 0) ) {
+ if (((adp->ad_options & ADVOL_NODEV) || (dev == st_dev))
+ && ino == st_ino
+ && (!did || a_did == did)
+ && (memcmp(stamp, temp, sizeof(temp)) == 0) ) {
memcpy(&aint, ad_entry(adp, ADEID_PRIVID), sizeof(aint));
- return aint;
+ if (adp->ad_vers == AD_VERSION2)
+ return aint;
+ else
+ return ntohl(aint);
}
- } else {
- memcpy(&aint, ad_entry(adp, ADEID_PRIVID), sizeof(aint));
- LOG(log_maxdebug, logtype_afpd, "ad_getid(\"%s\"): CNID: %" PRIu32 "", adp->ad_m_name, ntohl(aint));
- return ntohl(aint);
}
}
return 0;
{
uint32_t aint = 0;
- if (adp && (adp->ad_options & ADVOL_CACHE)) {
+ if (adp) {
memcpy(&aint, ad_entry(adp, ADEID_PRIVID), sizeof(aint));
- return aint;
+ if (adp->ad_vers == AD_VERSION2)
+ return aint;
+ else
+ return ntohl(aint);
}
return 0;
}
/* ad:ea */
#define ADEDOFF_FINDERI_EA (AD_HEADER_LEN + ADEID_NUM_EA * AD_ENTRY_LEN)
-#define ADEDOFF_COMMENT_EA (ADEDOFF_FINDERI_EA + ADEDLEN_FINDERI)
-#define ADEDOFF_FILEDATESI_EA (ADEDOFF_COMMENT_EA + ADEDLEN_COMMENT)
+#define ADEDOFF_COMMENT_EA (ADEDOFF_FINDERI_EA + ADEDLEN_FINDERI)
+#define ADEDOFF_FILEDATESI_EA (ADEDOFF_COMMENT_EA + ADEDLEN_COMMENT)
#define ADEDOFF_AFPFILEI_EA (ADEDOFF_FILEDATESI_EA + ADEDLEN_FILEDATESI)
-#define ADEDOFF_PRIVID_EA (ADEDOFF_AFPFILEI_EA + ADEDLEN_AFPFILEI)
+#define ADEDOFF_PRIVDEV_EA (ADEDOFF_AFPFILEI_EA + ADEDLEN_AFPFILEI)
+#define ADEDOFF_PRIVINO_EA (ADEDOFF_PRIVDEV_EA + ADEDLEN_PRIVDEV)
+#define ADEDOFF_PRIVSYN_EA (ADEDOFF_PRIVINO_EA + ADEDLEN_PRIVINO)
+#define ADEDOFF_PRIVID_EA (ADEDOFF_PRIVSYN_EA + ADEDLEN_PRIVSYN)
/* this is to prevent changing timezones from causing problems with
localtime volumes. the screw-up is 30 years. we use a delta of 5 years */
{ADEID_COMMENT, ADEDOFF_COMMENT_EA, ADEDLEN_INIT},
{ADEID_FILEDATESI, ADEDOFF_FILEDATESI_EA, ADEDLEN_FILEDATESI},
{ADEID_AFPFILEI, ADEDOFF_AFPFILEI_EA, ADEDLEN_AFPFILEI},
+ {ADEID_PRIVDEV, ADEDOFF_PRIVDEV_EA, ADEDLEN_INIT},
+ {ADEID_PRIVINO, ADEDOFF_PRIVINO_EA, ADEDLEN_INIT},
+ {ADEID_PRIVSYN, ADEDOFF_PRIVSYN_EA, ADEDLEN_INIT},
{ADEID_PRIVID, ADEDOFF_PRIVID_EA, ADEDLEN_INIT},
{0, 0, 0}
};
{AFPVOL_NODEV, "NODEV"}, /* always use 0 for device number in cnid calls */
{AFPVOL_CASEINSEN, "CASEINSENSITIVE"}, /* volume is case insensitive */
{AFPVOL_EILSEQ, "ILLEGALSEQ"}, /* encode illegal sequence */
- {AFPVOL_CACHE, "CACHEID"}, /* Use adouble v2 CNID caching, default don't use it */
{AFPVOL_INV_DOTS, "INVISIBLEDOTS"},
{AFPVOL_ACLS, "ACLS"}, /* Vol supports ACLs */
{AFPVOL_TM, "TM"}, /* Set "kSupportsTMLockSteal" is volume attributes */
vol->v_ad_options = 0;
if ((vol->v_flags & AFPVOL_NODEV))
vol->v_ad_options |= ADVOL_NODEV;
- if ((vol->v_flags & AFPVOL_CACHE))
- vol->v_ad_options |= ADVOL_CACHE;
if ((vol->v_flags & AFPVOL_UNIX_PRIV))
vol->v_ad_options |= ADVOL_UNIXPRIV;
if ((vol->v_flags & AFPVOL_INV_DOTS))