From: Frank Lahm Date: Tue, 21 Feb 2012 14:15:44 +0000 (+0100) Subject: Add conversion option to dbd X-Git-Url: https://arthur.barton.de/gitweb/?p=netatalk.git;a=commitdiff_plain;h=1f1bf1d7dd7f47bac89da0e25fcb6064ac842fe9 Add conversion option to dbd --- diff --git a/etc/cnid_dbd/cmd_dbd.c b/etc/cnid_dbd/cmd_dbd.c index 8eb9c576..d197efd5 100644 --- a/etc/cnid_dbd/cmd_dbd.c +++ b/etc/cnid_dbd/cmd_dbd.c @@ -129,48 +129,29 @@ static void set_signal(void) static void usage (void) { printf("dbd (Netatalk %s)\n" - "Usage: dbd [-etvxF] -d [-i] | -s [-c|-n]| -r [-c|-f] | -u \n" + "Usage: dbd [-CeFtvx] -d [-i] | -s [-c|-n]| -r [-c|-f] | -u \n" "dbd can dump, scan, reindex and rebuild Netatalk dbd CNID databases.\n" "dbd must be run with appropiate permissions i.e. as root.\n\n" "Main commands are:\n" " -d Dump CNID database\n" " Option: -i dump indexes too\n\n" " -s Scan volume:\n" - " 1. Compare CNIDs in database with volume\n" - " 2. Check if .AppleDouble dirs exist\n" - " 3. Check if AppleDouble file exist\n" - " 4. Report orphaned AppleDouble files\n" - " 5. Check for directories inside AppleDouble directories\n" - " 6. Check name encoding by roundtripping, log on error\n" - " 7. Check for orphaned CNIDs in database (requires -e)\n" - " 8. Open and close adouble files\n" " Options: -c Don't check .AppleDouble stuff, only ckeck orphaned.\n" " -n Don't open CNID database, skip CNID checks.\n\n" " -r Rebuild volume:\n" - " 1. Sync CNIDSs in database with volume\n" - " 2. Make sure .AppleDouble dir exist, create if missing\n" - " 3. Make sure AppleDouble file exists, create if missing\n" - " 4. Delete orphaned AppleDouble files\n" - " 5. Check for directories inside AppleDouble directories\n" - " 6. Check name encoding by roundtripping, log on error\n" - " 7. Check for orphaned CNIDs in database (requires -e)\n" - " 8. Open and close adouble files\n" " Options: -c Don't create .AppleDouble stuff, only cleanup orphaned.\n" " -f wipe database and rebuild from IDs stored in AppleDouble\n" - " files, only available for volumes without 'nocnidcache'\n" - " option. Implies -e.\n\n" + " metadata file or EA. Implies -e.\n\n" " -u Upgrade:\n" " Opens the database which triggers any necessary upgrades,\n" " then closes and exits.\n\n" "General options:\n" + " -C convert from adouble:v2 to adouble:ea (use with -r)\n" " -F location of the afp.conf config file\n" " -e only work on inactive volumes and lock them (exclusive)\n" " -x rebuild indexes (just for completeness, mostly useless!)\n" " -t show statistics while running\n" " -v verbose\n\n" - "WARNING:\n" - "For -r -f restore of the CNID database from the adouble files,\n" - "the CNID must of course be synched to them files first with a plain -r rebuild!\n" , VERSION ); } @@ -192,11 +173,14 @@ int main(int argc, char **argv) /* Inhereting perms in ad_mkdir etc requires this */ ad_setfuid(0); - while ((c = getopt(argc, argv, ":cdefFinrstuvx")) != -1) { + while ((c = getopt(argc, argv, ":cCdefFinrstuvx")) != -1) { switch(c) { case 'c': flags |= DBD_FLAGS_CLEANUP; break; + case 'C': + flags |= DBD_FLAGS_V2TOEA; + break; case 'd': dump = 1; break; @@ -288,6 +272,12 @@ int main(int argc, char **argv) dbd_log( LOGSTD, "Couldn't find volume for '%s'", volpath); exit(EXIT_FAILURE); } + + if (load_charset(vol) != 0) { + dbd_log( LOGSTD, "Couldn't load charsets for '%s'", volpath); + exit(EXIT_FAILURE); + } + pack_setvol(vol); if (vol->v_adouble == AD_VERSION_EA) @@ -299,6 +289,12 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); } + /* -C v2 to ea conversion only on adouble:ea volumes */ + if ((flags & DBD_FLAGS_V2TOEA) && (vol->v_adouble!= AD_VERSION_EA)) { + dbd_log( LOGSTD, "Can't run adouble:v2 to adouble:ea conversion because not an adouble:ea volume"); + exit(EXIT_FAILURE); + } + /* Sanity checks to ensure we can touch this volume */ if (vol->v_vfs_ea != AFPVOL_EA_AD && vol->v_vfs_ea != AFPVOL_EA_SYS) { dbd_log( LOGSTD, "Unknown Extended Attributes option: %u", vol->v_vfs_ea); diff --git a/etc/cnid_dbd/cmd_dbd.h b/etc/cnid_dbd/cmd_dbd.h index e94c8618..efec636b 100644 --- a/etc/cnid_dbd/cmd_dbd.h +++ b/etc/cnid_dbd/cmd_dbd.h @@ -15,6 +15,7 @@ typedef unsigned int dbd_flags_t; #define DBD_FLAGS_EXCL (1 << 2) #define DBD_FLAGS_CLEANUP (1 << 3) /* Dont create AD stuff, but cleanup orphaned */ #define DBD_FLAGS_STATS (1 << 4) +#define DBD_FLAGS_V2TOEA (1 << 5) /* Convert adouble:v2 to adouble:ea */ #define ADv2_DIRNAME ".AppleDouble" diff --git a/etc/cnid_dbd/cmd_dbd_scanvol.c b/etc/cnid_dbd/cmd_dbd_scanvol.c index 90421a93..9685c3d2 100644 --- a/etc/cnid_dbd/cmd_dbd_scanvol.c +++ b/etc/cnid_dbd/cmd_dbd_scanvol.c @@ -218,13 +218,25 @@ static int check_adfile(const char *fname, const struct stat *st) struct adouble ad; const char *adname; - if (myvol->v_adouble == AD_VERSION_EA) + if (myvol->v_adouble == AD_VERSION_EA) { + if (!(dbd_flags & DBD_FLAGS_V2TOEA)) + return 0; + if (ad_convert(fname, st, myvol) != 0) { + switch (errno) { + case ENOENT: + break; + default: + dbd_log(LOGSTD, "Conversion error for \"%s/%s\": %s", cwdbuf, fname, strerror(errno)); + break; + } + } return 0; - + } + if (dbd_flags & DBD_FLAGS_CLEANUP) return 0; - if (S_ISREG(st->st_mode)) + if (S_ISDIR(st->st_mode)) adflags |= ADFLAGS_DIR; adname = myvol->ad_path(fname, adflags); @@ -521,10 +533,10 @@ static int read_addir(void) struct dirent *ep; struct stat st; - if (myvol->v_adouble == AD_VERSION_EA) - return 0; - if ((chdir(ADv2_DIRNAME)) != 0) { + if (myvol->v_adouble == AD_VERSION_EA) { + return 0; + } dbd_log(LOGSTD, "Couldn't chdir to '%s/%s': %s", cwdbuf, ADv2_DIRNAME, strerror(errno)); return -1; @@ -803,7 +815,7 @@ static int dbd_readdir(int volroot, cnid_t did) return -1; /* Check AppleDouble files in AppleDouble folder, but only if it exists or could be created */ - if (myvol->v_adouble == AD_VERSION2 && ADDIR_OK) + if (ADDIR_OK) if ((read_addir()) != 0) if ( ! (dbd_flags & DBD_FLAGS_SCAN)) /* Fatal on rebuild run, continue if only scanning ! */ @@ -958,13 +970,25 @@ static int dbd_readdir(int volroot, cnid_t did) /* Use results of previous checks */ - + if ((myvol->v_adouble == AD_VERSION_EA) && (dbd_flags & DBD_FLAGS_V2TOEA)) { + if (rmdir(ADv2_DIRNAME) != 0) { + switch (errno) { + case ENOENT: + break; + default: + dbd_log(LOGSTD, "Error removing adouble dir \"%s/%s\": %s", cwdbuf, ADv2_DIRNAME, strerror(errno)); + break; + } + } + } closedir(dp); return ret; } static int scanvol(struct vol *vol, dbd_flags_t flags) { + struct stat st; + /* Make this stuff accessible from all funcs easily */ myvol = vol; dbd_flags = flags; @@ -975,6 +999,20 @@ static int scanvol(struct vol *vol, dbd_flags_t flags) strcpy(cwdbuf, myvol->v_path); chdir(myvol->v_path); + if ((myvol->v_adouble == AD_VERSION_EA) && (dbd_flags & DBD_FLAGS_V2TOEA)) { + if (lstat(".", &st) != 0) + return -1; + if (ad_convert(".", &st, vol) != 0) { + switch (errno) { + case ENOENT: + break; + default: + dbd_log(LOGSTD, "Conversion error for \"%s\": %s", myvol->v_path, strerror(errno)); + break; + } + } + } + /* Start recursion */ if (dbd_readdir(1, htonl(2)) < 0) /* 2 = volumeroot CNID */ return -1; diff --git a/etc/cnid_dbd/main.c b/etc/cnid_dbd/main.c index 9b5fd785..fea36b81 100644 --- a/etc/cnid_dbd/main.c +++ b/etc/cnid_dbd/main.c @@ -319,7 +319,7 @@ int main(int argc, char *argv[]) EC_ZERO( load_volumes(&obj, NULL) ); EC_NULL( vol = getvolbypath(volpath) ); - + EC_ZERO( load_charset(vol) ); pack_setvol(vol); EC_NULL( dbpath = bfromcstr(vol->v_dbpath) ); diff --git a/include/atalk/netatalk_conf.h b/include/atalk/netatalk_conf.h index a8d525f5..9c189e63 100644 --- a/include/atalk/netatalk_conf.h +++ b/include/atalk/netatalk_conf.h @@ -22,6 +22,7 @@ extern int afp_config_parse(AFPObj *obj); +extern int load_charset(struct vol *vol); extern int load_volumes(AFPObj *obj, void (*delvol_fn)(struct vol *)); extern void unload_volumes(AFPObj *obj); extern struct vol *getvolumes(void); diff --git a/libatalk/adouble/ad_open.c b/libatalk/adouble/ad_open.c index 8d0e6f4b..c6aa776d 100644 --- a/libatalk/adouble/ad_open.c +++ b/libatalk/adouble/ad_open.c @@ -806,6 +806,7 @@ static int ad_conv_v22ea_hf(const char *path, const struct stat *sp, const struc EC_CLEANUP: EC_ZERO_LOG( ad_close(&adv2, ADFLAGS_HF | ADFLAGS_SETSHRMD) ); EC_ZERO_LOG( ad_close(&adea, ADFLAGS_HF | ADFLAGS_SETSHRMD) ); + LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): END: %d", fullpathname(path), ret); EC_EXIT; } @@ -839,6 +840,7 @@ static int ad_conv_v22ea_rf(const char *path, const struct stat *sp, const struc EC_CLEANUP: EC_ZERO_LOG( ad_close(&adv2, ADFLAGS_HF | ADFLAGS_RF) ); EC_ZERO_LOG( ad_close(&adea, ADFLAGS_HF | ADFLAGS_RF) ); + LOG(log_debug, logtype_default,"ad_conv_v22ea_rf(\"%s\"): END: %d", fullpathname(path), ret); EC_EXIT; } @@ -1862,6 +1864,8 @@ int ad_convert(const char *path, const struct stat *sp, const struct vol *vol) const char *adpath; int adflags = S_ISDIR(sp->st_mode) ? ADFLAGS_DIR : 0; + LOG(log_debug, logtype_default,"ad_convert(\"%s\"): BEGIN", fullpathname(path)); + if (!(vol->v_adouble == AD_VERSION_EA) || (vol->v_flags & AFPVOL_NOV2TOEACONV)) goto EC_CLEANUP; @@ -1877,6 +1881,7 @@ int ad_convert(const char *path, const struct stat *sp, const struct vol *vol) unbecome_root(); EC_CLEANUP: + LOG(log_debug, logtype_default,"ad_convert(\"%s\"): END: %d", fullpathname(path), ret); EC_EXIT; } diff --git a/libatalk/util/netatalk_conf.c b/libatalk/util/netatalk_conf.c index ab5e8787..38ba6643 100644 --- a/libatalk/util/netatalk_conf.c +++ b/libatalk/util/netatalk_conf.c @@ -606,9 +606,13 @@ static int creatvol(AFPObj *obj, if (val = getoption(obj->iniconfig, name, "volcharset", preset)) EC_NULL( volume->v_volcodepage = strdup(val) ); + else + EC_NULL( volume->v_volcodepage = strdup("UTF8") ); if (val = getoption(obj->iniconfig, name, "maccharset", preset)) EC_NULL( volume->v_maccodepage = strdup(val) ); + else + EC_NULL( volume->v_maccodepage = strdup(obj->options.maccodepage) ); if (val = getoption(obj->iniconfig, name, "dbpath", preset)) EC_NULL( volume->v_dbpath = volxlate(obj, NULL, MAXPATHLEN, val, pwd, path, name) ); @@ -1035,6 +1039,24 @@ void volume_free(struct vol *vol) LOG(log_debug, logtype_afpd, "volume_free: END"); } +/*! + * Load charsets for a volume + */ +int load_charset(struct vol *vol) +{ + if ((vol->v_maccharset = add_charset(vol->v_maccodepage)) == (charset_t)-1) { + LOG(log_error, logtype_default, "Setting Mac codepage '%s' failed", vol->v_maccodepage); + return -1; + } + + if ((vol->v_volcharset = add_charset(vol->v_volcodepage)) == (charset_t)-1) { + LOG(log_error, logtype_default, "Setting volume codepage '%s' failed", vol->v_volcodepage); + return -1; + } + + return 0; +} + /*! * Initialize volumes and load ini configfile *