* FIX: dbd: remove orphaned ._ AppleDouble files. Bug #549.
* NEW: afpd: Automatic conversion of ._ AppleDouble files
created by OS X. Bug #550.
+* FIX: afpd: Fix a crash in of_closefork(). Bug #551.
+* FIX: dbd: Don't print message "Ignoring ._file" for every ._ file.
+ Bug #552.
Changes in 3.1.0
================
setuplog("default:note", "/dev/tty");
- if (load_volumes(&obj) != 0)
+ if (load_volumes(&obj, lv_none) != 0)
return 1;
if (STRCMP(argv[1], ==, "ls"))
/* Now register with zeroconf, we also need the volumes for that */
if (! (obj->options.flags & OPTION_NOZEROCONF)) {
- load_volumes(obj);
+ load_volumes(obj, lv_all);
zeroconf_register(obj);
}
if (reload_request) {
reload_request = 0;
- load_volumes(AFPobj);
+ load_volumes(AFPobj, lv_none);
}
/* The first SIGINT enables debugging, the next restores the config */
/* Somone has used write_fork, we assume file was changed, register it to file change event api */
if (ofork->of_flags & AFPFORK_MODIFIED) {
struct dir *dir = dirlookup(ofork->of_vol, ofork->of_did);
- bstring forkpath = bformat("%s/%s", bdata(dir->d_fullpath), of_name(ofork));
- fce_register(FCE_FILE_MODIFY, bdata(forkpath), NULL, fce_file);
- bdestroy(forkpath);
+ if (dir) {
+ bstring forkpath = bformat("%s/%s", bdata(dir->d_fullpath), of_name(ofork));
+ fce_register(FCE_FILE_MODIFY, bdata(forkpath), NULL, fce_file);
+ bdestroy(forkpath);
+ }
}
ad_unlock(ofork->of_ad, ofork->of_refnum, ofork->of_flags & AFPFORK_ERROR ? 0 : 1);
size_t len;
uint32_t aint;
- load_volumes(obj);
+ load_volumes(obj, lv_none);
data = rbuf + 5;
for ( vcnt = 0, volume = getvolumes(); volume && vcnt < 255; volume = volume->v_next ) {
if ((len + 1) & 1) /* pad to an even boundary */
ibuf++;
- load_volumes(obj);
+ load_volumes(obj, lv_none);
for ( volume = getvolumes(); volume; volume = volume->v_next ) {
if ( strcasecmp_w( (ucs2_t*) volname, volume->v_name ) == 0 ) {
else
setuplog("default:note", "/dev/tty");
- if (load_volumes(&obj) != 0) {
+ if (load_volumes(&obj, lv_all) != 0) {
dbd_log( LOGSTD, "Couldn't load volumes");
exit(EXIT_FAILURE);
}
return db_cnid;
}
-static void check_orphaned(const char *name)
+static int check_orphaned(const char *name)
{
int rc;
struct stat sb;
if (rc != 0 && errno == ENOENT) {
dbd_log(LOGSTD, "Removing orphaned AppleDouble \"%s/%s\"", cwdbuf, name);
unlink(name);
+ return 1;
}
+ return 0;
}
/*
**************************************************************************/
/* Check for invalid names and orphaned ._ files */
- if (S_ISREG(st.st_mode) && (strncmp(ep->d_name, "._", strlen("._")) == 0))
- check_orphaned(ep->d_name);
-
- if (!vol->vfs->vfs_validupath(vol, ep->d_name)) {
- dbd_log(LOGSTD, "Ignoring \"%s/%s\"", cwdbuf, ep->d_name);
- continue;
+ if (S_ISREG(st.st_mode) && (strncmp(ep->d_name, "._", strlen("._")) == 0)) {
+ if (check_orphaned(ep->d_name))
+ continue;
+ if (vol->vfs->vfs_validupath(vol, ep->d_name)) {
+ dbd_log(LOGSTD, "Bad AppleDouble \"%s/%s\"", cwdbuf, ep->d_name);
+ continue;
+ }
}
/* Check for appledouble file, create if missing, but only if we have addir */
if (afp_config_parse(&obj, "cnid_metad") != 0)
daemon_exit(1);
- if (load_volumes(&obj) != 0)
+ if (load_volumes(&obj, lv_all) != 0)
daemon_exit(1);
(void)setlimits();
LOG(log_debug, logtype_cnid, "main: request for volume: %s", volpath);
- if (load_volumes(&obj) != 0) {
+ if (load_volumes(&obj, lv_all) != 0) {
LOG(log_severe, logtype_cnid, "main: error reloading config");
goto loop_end;
}
EC_ZERO( afp_config_parse(&obj, "cnid_dbd") );
- EC_ZERO( load_volumes(&obj) );
+ EC_ZERO( load_volumes(&obj, lv_all) );
EC_NULL( vol = getvolbypath(&obj, volpath) );
EC_ZERO( load_charset(vol) );
pack_setvol(vol);
if (afp_config_parse(&obj, "netatalk") != 0)
netatalk_exit(EXITERR_CONF);
- load_volumes(&obj);
+ load_volumes(&obj, lv_all);
event_set_log_callback(libevent_logmsg_cb);
event_set_fatal_callback(netatalk_exit);
extern int afp_config_parse(AFPObj *obj, char *processname);
extern void afp_config_free(AFPObj *obj);
extern int load_charset(struct vol *vol);
-extern int load_volumes(AFPObj *obj);
+extern int load_volumes(AFPObj *obj, lv_flags_t flags);
extern void unload_volumes(AFPObj *obj);
extern struct vol *getvolumes(void);
extern struct vol *getvolbyvid(const uint16_t);
};
/* load_volumes() flags */
-#define LV_ALL (1 << 0)
+typedef enum {lv_none = 0, lv_all = 1} lv_flags_t;
/* volume flags */
#define AFPVOL_OPEN (1<<0)
if(tmpname[i] == '/') tmpname[i] = ':';
- if (!atalk_iniparser_getboolean(obj->iniconfig, INISEC_GLOBAL, "vol dbnest", 0)) {
+ if (atalk_iniparser_getboolean(obj->iniconfig, INISEC_GLOBAL, "vol dbnest", 0)) {
+ EC_NULL( volume->v_dbpath = strdup(path) );
+ } else {
bstring dbpath;
- EC_NULL( val = atalk_iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "vol dbpath", _PATH_STATEDIR "CNID/") );
- EC_NULL( dbpath = bformat("%s/%s/", val, tmpname) );
- EC_NULL( volume->v_dbpath = strdup(cfrombstr(dbpath)) );
+ val = atalk_iniparser_getstring(obj->iniconfig, section, "vol dbpath", NULL);
+ if (val == NULL) {
+ EC_NULL( dbpath = bformat("%s/%s/", _PATH_STATEDIR "CNID/", tmpname) );
+ } else {
+ EC_NULL( dbpath = bfromcstr(val));
+ }
+ EC_NULL( volume->v_dbpath = volxlate(obj, NULL, MAXPATHLEN + 1,
+ cfrombstr(dbpath), pwd, NULL, NULL) );
bdestroy(dbpath);
- } else {
- EC_NULL( volume->v_dbpath = strdup(path) );
}
if ((val = getoption(obj->iniconfig, section, "cnid scheme", preset, NULL)))
/*!
* Initialize volumes and load ini configfile
*
- * Depending on the value of obj->uid either access checks are done (!=0) or skipped (=0)
- *
- * @param obj (r) handle
- * @param delvol_fn (r) callback called for deleted volumes
+ * @param obj (r) handle
+ * @param flags (r) flags controlling volume load behaviour
*/
-int load_volumes(AFPObj *obj)
+int load_volumes(AFPObj *obj, lv_flags_t flags)
{
EC_INIT;
EC_NULL( pwbuf = malloc(bufsize) );
}
- if (obj->uid) {
+ if (!(flags & lv_all) && obj->uid) {
ret = getpwuid_r(obj->uid, &pwent, pwbuf, bufsize, &pwresult);
if (pwresult == NULL) {
LOG(log_error, logtype_afpd, "load_volumes: getpwuid_r: %s", strerror(errno));
.\" Title: afp.conf
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 13 Sep 2013
+.\" Date: 09 Feb 2013
.\" Manual: @NETATALK_VERSION@
.\" Source: @NETATALK_VERSION@
.\" Language: English
.\"
-.TH "AFP\&.CONF" "5" "13 Sep 2013" "@NETATALK_VERSION@" "@NETATALK_VERSION@"
+.TH "AFP\&.CONF" "5" "09 Feb 2013" "@NETATALK_VERSION@" "@NETATALK_VERSION@"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
Specifies the IP address and port of a cnid_metad server, required for CNID dbd backend\&. Defaults to localhost:4700\&. The network address may be specified either in dotted\-decimal format for IPv4 or in hexadecimal format for IPv6\&.\-
.RE
.PP
+dbus daemon = \fIpath\fR \fB(G)\fR
+.RS 4
+Sets the path to dbus\-daemon binary used by Spotlight feature\&. The default is
+/bin/dbus\-daemon\&.
+.RE
+.PP
dircachesize = \fInumber\fR \fB(G)\fR
.RS 4
Maximum possible entries in the directory cache\&. The cache stores directories and files\&. It is used to cache the full path to directories and CNIDs which considerably speeds up directory enumeration\&.
\fIuser\*(Aqs home\fR\&.
.RE
.PP
-login message = \fImessage\fR \fB(G)/(V)\fR
-.RS 4
-Sets a message to be displayed when clients logon to the server\&. The message should be in
-\fBunix charset\fR
-and should be quoted\&. Extended characters are allowed\&.
-.RE
-.PP
ignored attributes = \fIall | nowrite | nodelete | norename\fR \fB(G)/(V)\fR
.RS 4
Speficy a set of file and directory attributes that shall be ignored by the server,
\fIignored attributes = all\fR\&.
.RE
.PP
+login message = \fImessage\fR \fB(G)/(V)\fR
+.RS 4
+Sets a message to be displayed when clients logon to the server\&. The message should be in
+\fBunix charset\fR
+and should be quoted\&. Extended characters are allowed\&.
+.RE
+.PP
mimic model = \fImodel\fR \fB(G)\fR
.RS 4
Specifies the icon model that appears on clients\&. Defaults to off\&. Note that afpd must support Zeroconf\&. Examples: RackMac (same as Xserve), PowerBook, PowerMac, Macmini, iMac, MacBook, MacBookPro, MacBookAir, MacPro, AppleTV1,1, AirPort\&.
.PP
spotlight = \fIBOOLEAN\fR (default: \fIno\fR) \fB(G)/(V)\fR
.RS 4
-Whether to enable Spotlight searches\&. Note: once the global option is enabled, any volume that is not enabled won\*(Aqt be searchable at all\&.
+Whether to enable Spotlight searches\&. Note: once the global option is enabled, any volume that is not enabled won\*(Aqt be searchable at all\&. See also
+\fIdbus daemon\fR
+option\&.
.RE
.PP
veto message = \fIBOOLEAN\fR (default: \fIno\fR) \fB(G)\fR
.PP
veto files = \fIvetoed names\fR \fB(V)\fR
.RS 4
-hide files and directories,where the path matches one of the \*(Aq/\*(Aq delimited vetoed names\&. The veto string must always be terminated with a \*(Aq/\*(Aq, eg\&. "veto1/", "veto1/veto2/"\&.
+hide files and directories,where the path matches one of the \*(Aq/\*(Aq delimited vetoed names\&. The veto string must always be terminated with a \*(Aq/\*(Aq, eg\&. "veto files = veto1/", "veto files = veto1/veto2/"\&.
.RE
.SS "Volume options"
.PP
TEST_int( afp_config_parse(&obj, NULL), 0);
TEST_int( configinit(&obj), 0);
TEST( cnid_init() );
- TEST( load_volumes(&obj) );
+ TEST( load_volumes(&obj, lv_all) );
TEST_int( dircache_init(8192), 0);
obj.afp_version = 32;