+Changes in 3.0.2
+================
+* NEW: afpd: Put file extension type/creator mapping back in which had
+ been removed in 3.0.
+* NEW: afpd: new option 'ad domain'. From FR #66.
+* FIX: volumes and home share with symlinks in the path
+* FIX: Copying packages to a Netatalk share could fail, bug #469
+* FIX: Reloading volumes from config file was broken. Fixes bug #474.
+* FIX: Fix _device-info service type registered with dns-sd API
+* FIX: Fix pathname bug for FCE modified event.
+* FIX: Remove length limitation of options like "valid users".
+ Fixes bug #473.
+* FIX: Dont copy our metadata EA in copyfile(). Fixes bug #452.
+* FIX: Fix an error where catalog search gave incomplete results.
+ Fixes bug #479.
+* REM: Remove TimeMachine volume used size FCE event.
+* UPD: Add quoting support to '[in]valid users' option. Fixes bug #472.
+* FIX: Install working PAM config on Solaris 11. Fixes bug #481.
+* FIX: Fix a race condition between dbd and the cnid_dbd daemon
+ which could result in users being disconnected from volumes
+ when dbd was scanning their volumes. Fixes bug #477.
+* FIX: Netatalk didn't start when the last line of the config file
+ afp.conf wasn't terminated by a newline. Fixes bug #476.
+* NEW: Add a new volumes option 'follow symlinks'. The default setting is
+ false, symlinks are not followed on the server. This is the same
+ behaviour as OS X's AFP server.
+ Setting the option to true causes afpd to follow symlinks on the
+ server. symlinks may point outside of the AFP volume, currently
+ afpd doesn't do any checks for "wide symlinks".
+* FIX: Automatic AppleDouble conversion to EAs failing for directories.
+ Fixes bug #486.
+* FIX: dbd failed to convert appledouble files of symlinks.
+ Fixes bug #490.
+
Changes in 3.0.1
================
* NEW: afpd: Optional "ldap uuid encoding = string | ms-guid" parameter to
-3.0.1
\ No newline at end of file
+3.0.2
\ No newline at end of file
setuplog("default:note", "/dev/tty");
- if (load_volumes(&obj, NULL) != 0)
+ if (load_volumes(&obj) != 0)
return 1;
if (STRCMP(argv[1], ==, "ls"))
static int badcp, rval;
static int ftw_options = FTW_MOUNT | FTW_PHYS | FTW_ACTIONRETVAL;
-static char *netatalk_dirs[] = {
- ".AppleDouble",
- ".AppleDB",
- ".AppleDesktop",
- NULL
-};
-
/* Forward declarations */
static int copy(const char *fpath, const struct stat *sb, int tflag, struct FTW *ftwbuf);
static int ftw_copy_file(const struct FTW *, const char *, const struct stat *, int);
static int ftw_copy_link(const struct FTW *, const char *, const struct stat *, int);
static int setfile(const struct stat *, int);
-static int preserve_dir_acls(const struct stat *, char *, char *);
+// static int preserve_dir_acls(const struct stat *, char *, char *);
static int preserve_fd_acls(int, int);
-/*
- Check for netatalk special folders e.g. ".AppleDB" or ".AppleDesktop"
- Returns pointer to name or NULL.
-*/
-static const char *check_netatalk_dirs(const char *name)
-{
- int c;
-
- for (c=0; netatalk_dirs[c]; c++) {
- if ((strcmp(name, netatalk_dirs[c])) == 0)
- return netatalk_dirs[c];
- }
- return NULL;
-}
-
static void upfunc(void)
{
did = pdid;
return (0);
}
+#if 0
static int preserve_dir_acls(const struct stat *fs, char *source_dir, char *dest_dir)
{
-#if 0
acl_t (*aclgetf)(const char *, acl_type_t);
int (*aclsetf)(const char *, acl_type_t, acl_t);
struct acl *aclp;
return (1);
}
acl_free(acl);
-#endif
return (0);
}
+#endif
static afpvol_t svolume, dvolume;
static cnid_t did, pdid;
static volatile sig_atomic_t alarmed;
-static char *netatalk_dirs[] = {
- ".AppleDouble",
- ".AppleDB",
- ".AppleDesktop",
- NULL
-};
static int copy(const char *, const char *);
static int do_move(const char *, const char *);
-static void preserve_fd_acls(int source_fd, int dest_fd, const char *source_path,
- const char *dest_path);
-/*
- Check for netatalk special folders e.g. ".AppleDB" or ".AppleDesktop"
- Returns pointer to name or NULL.
-*/
-static const char *check_netatalk_dirs(const char *name)
-{
- int c;
-
- for (c=0; netatalk_dirs[c]; c++) {
- if ((strcmp(name, netatalk_dirs[c])) == 0)
- return netatalk_dirs[c];
- }
- return NULL;
-}
/*
SIGNAL handling:
}
}
-exit:
closevol(&dvolume);
return rval;
}
}
return 0;
}
-
-static void
-preserve_fd_acls(int source_fd,
- int dest_fd,
- const char *source_path,
- const char *dest_path)
-{
- ;
-}
static void change_attributes(char *path, afpvol_t *vol, const struct stat *st, struct adouble *ad, char *new_attributes)
{
- char *FinderInfo;
uint16_t AFPattributes;
ad_getattr(ad, &AFPattributes);
int ad_set(int argc, char **argv, AFPObj *obj)
{
- int c, firstarg;
+ int c;
afpvol_t vol;
struct stat st;
int adflags = 0;
#
# Upgrade version 1 CNID databases to version 2
#
-# $Id: cnid2_create.in,v 1.2 2005-04-28 20:49:19 bfernhomberg Exp $
#
# Copyright (C) Joerg Lenneis 2003
# All Rights Reserved. See COPYING.
/*
- * $Id: asingle.c,v 1.14 2010-01-27 21:27:53 didg Exp $
*/
#ifdef HAVE_CONFIG_H
/*
- * $Id: asingle.h,v 1.4 2010-01-27 21:27:53 didg Exp $
*/
#ifndef _ASINGLE_H
/*
- * $Id: hqx.c,v 1.18 2010-01-27 21:27:53 didg Exp $
*/
#ifdef HAVE_CONFIG_H
/*
- * $Id: hqx.h,v 1.3 2010-01-27 21:27:53 didg Exp $
*/
#ifndef _HQX_H
/*
- * $Id: macbin.c,v 1.15 2010-01-27 21:27:53 didg Exp $
*/
#ifdef HAVE_CONFIG_H
/*
- * $Id: macbin.h,v 1.4 2010-01-27 21:27:53 didg Exp $
*/
#ifndef _MACBIN_H
/*
- * $Id: megatron.h,v 1.5 2009-10-14 01:38:28 didg Exp $
*/
#ifndef _MEGATRON_H
/*
- * $Id: nad.c,v 1.18 2010-01-27 21:27:53 didg Exp $
*/
#ifdef HAVE_CONFIG_H
/*
- * $Id: nad.h,v 1.5 2010-01-27 21:27:53 didg Exp $
*/
#ifndef _NAD_H
/*
- * $Id: updcrc.c,v 1.5 2009-10-13 22:55:36 didg Exp $
*
* updcrc(3), crc(1) - calculate crc polynomials
*
/*
- * $Id: updcrc.h,v 1.1 2009-10-13 22:55:36 didg Exp $
*/
#ifndef _UPDCRC_H
"FCE_FILE_DELETE",
"FCE_DIR_DELETE",
"FCE_FILE_CREATE",
- "FCE_DIR_CREATE",
- "FCE_TM_SIZE"
+ "FCE_DIR_CREATE"
};
-// get sockaddr, IPv4 or IPv6:
-static void *get_in_addr(struct sockaddr *sa)
-{
- if (sa->sa_family == AF_INET) {
- return &(((struct sockaddr_in*)sa)->sin_addr);
- }
-
- return &(((struct sockaddr_in6*)sa)->sin6_addr);
-}
-
static int unpack_fce_packet(unsigned char *buf, struct fce_packet *packet)
{
unsigned char *p = buf;
packet->datalen = ntohs(packet->datalen);
memcpy(&packet->data[0], p, packet->datalen);
+ packet->data[packet->datalen] = 0; /* 0 terminate strings */
p += packet->datalen;
return 0;
struct sockaddr_storage their_addr;
char buf[MAXBUFLEN];
socklen_t addr_len;
- char s[INET6_ADDRSTRLEN];
- uint64_t tmsize;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // set to AF_INET to force IPv4
exit(1);
}
- unpack_fce_packet(buf, &packet);
+ unpack_fce_packet((unsigned char *)buf, &packet);
if (memcmp(packet.magic, FCE_PACKET_MAGIC, sizeof(packet.magic)) == 0) {
switch (packet.mode) {
- case FCE_TM_SIZE:
- memcpy(&tmsize, packet.data, sizeof(uint64_t));
- tmsize = ntoh64(tmsize);
- printf("ID: %" PRIu32 ", Event: %s, Volume: %s, TM used size: %" PRIu64 " \n",
- packet.event_id, fce_ev_names[packet.mode], packet.data + sizeof(uint64_t), tmsize);
- break;
-
case FCE_CONN_START:
printf("FCE Start\n");
break;
+/*
+ Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
#include <stdio.h>
#include <stdbool.h>
struct flag_map flag_map[] = {
flag(CONV_ESCAPEHEX),
- flag(CONV_ALLOW_COLON),
flag(CONV_UNESCAPEHEX),
flag(CONV_ESCAPEDOTS),
flag(CONV_IGNORE),
{
int opt;
uint16_t flags = 0;
- char *string;
+ char *string, *macName = MACCHARSET;
char *f = NULL, *t = NULL;
charset_t from, to, mac;
- while ((opt = getopt(argc, argv, ":o:f:t:")) != -1) {
+ while ((opt = getopt(argc, argv, "m:o:f:t:")) != -1) {
switch(opt) {
+ case 'm':
+ macName = strdup(optarg);
+ break;
case 'o':
for (int i = 0; i < sizeof(flag_map)/sizeof(struct flag_map) - 1; i++)
if ((strcmp(flag_map[i].flagname, optarg)) == 0)
flags |= flag_map[i].flag;
break;
case 'f':
- f = optarg;
+ f = strdup(optarg);
break;
case 't':
- t = optarg;
+ t = strdup(optarg);
break;
}
}
if ((optind + 1) != argc) {
- printf("Usage: test [-o <conversion option> [...]] [-f <from charset>] [-t <to charset>] <string>\n");
- printf("Defaults: -f: UTF8-MAC , -t: UTF8 \n");
+ printf("Usage: test [-o <conversion option> [...]] [-f <from charset>] [-t <to charset>] [-m legacy Mac charset] <string>\n");
+ printf("Defaults: -f: UTF8-MAC, -t: UTF8, -m MAC_ROMAN\n");
printf("Available conversion options:\n");
for (int i = 0; i < (sizeof(flag_map)/sizeof(struct flag_map) - 1); i++) {
printf("%s\n", flag_map[i].flagname);
}
string = argv[optind];
+ set_charset_name(CH_UNIX, "UTF8");
+ set_charset_name(CH_MAC, macName);
+
if ( (charset_t) -1 == (from = add_charset(f ? f : "UTF8-MAC")) ) {
fprintf( stderr, "Setting codepage %s as from codepage failed\n", f ? f : "UTF8-MAC");
return (-1);
return (-1);
}
- if ( (charset_t) -1 == (mac = add_charset(MACCHARSET)) ) {
+ if ( (charset_t) -1 == (mac = add_charset(macName)) ) {
fprintf( stderr, "Setting codepage %s as Mac codepage failed\n", MACCHARSET);
return (-1);
}
TMPLFILES = afp.conf.tmpl
GENFILES = afp.conf
CLEANFILES = $(GENFILES)
-EXTRA_DIST = afp.conf.tmpl
+EXTRA_DIST = afp.conf.tmpl extmap.conf
OVERWRITE_CONFIG = @OVERWRITE_CONFIG@
-CONFFILES =
+CONFFILES = extmap.conf
pkgconfdir = @PKGCONFDIR@
#
--- /dev/null
+# Netatalk file extension -> OS X type/creator mapping configuration file
+#
+# Delete a '#' character at the head of line to uncomment and enable a mapping
+#
+### Default translation:
+#. "????" "????" Unix Binary Unix application/octet-stream
+#. "BINA" "UNIX" Unix Binary Unix application/octet-stream
+#. "TEXT" "ttxt" ASCII Text SimpleText text/plain
+
+#.1st "TEXT" "ttxt" Text Readme SimpleText application/text
+#.669 "6669" "SNPL" 669 MOD Music PlayerPro
+#.8med "STrk" "SCPL" Amiga OctaMed music SoundApp
+#.8svx "8SVX" "SCPL" Amiga 8-bit sound SoundApp
+#.a "TEXT" "ttxt" Assembly Source SimpleText
+#.aif "AIFF" "SCPL" AIFF Sound SoundApp audio/x-aiff
+#.aifc "AIFC" "SCPL" AIFF Sound Compressed SoundApp audio/x-aiff
+#.aiff "AIFF" "SCPL" AIFF Sound SoundApp audio/x-aiff
+#.al "ALAW" "SCPL" ALAW Sound SoundApp
+#.ani "ANIi" "GKON" Animated NeoChrome GraphicConverter
+#.apd "TEXT" "ALD3" Aldus Printer Description Aldus PageMaker
+#.arc "mArc" "SITx" PC ARChive StuffIt Expander
+#.arj "BINA" "DArj" ARJ Archive DeArj
+#.arr "ARR " "GKON" Amber ARR image GraphicConverter
+#.art "ART " "GKON" First Publisher GraphicConverter
+#.asc "TEXT" "ttxt" ASCII Text SimpleText text/plain
+#.ascii "TEXT" "ttxt" ASCII Text SimpleText text/plain
+#.asf "ASF_" "Ms01" Netshow Player Netshow Server video/x-ms-asf
+#.asm "TEXT" "ttxt" Assembly Source SimpleText
+#.asx "ASX_" "Ms01" Netshow Player Netshow Server video/x-ms-asf
+#.au "ULAW" "TVOD" Sun Sound QuickTime Player audio/basic
+#.avi "VfW " "TVOD" AVI Movie QuickTime Player video/avi
+#.bar "BARF" "S691" Unix BAR Archive SunTar
+#.bas "TEXT" "ttxt" BASIC Source SimpleText
+#.bat "TEXT" "ttxt" MS-DOS Batch File SimpleText
+#.bga "BMPp" "ogle" OS/2 Bitmap PictureViewer
+#.bib "TEXT" "ttxt" BibTex Bibliography SimpleText
+#.bin "SIT!" "SITx" MacBinary StuffIt Expander application/macbinary
+#.binary "BINA" "hDmp" Untyped Binary Data HexEdit application/octet-stream
+#.bmp "BMPp" "ogle" Windows Bitmap PictureViewer
+#.boo "TEXT" "ttxt" BOO encoded SimpleText
+#.bst "TEXT" "ttxt" BibTex Style SimpleText
+#.bw "SGI " "GKON" SGI Image GraphicConverter
+#.c "TEXT" "CWIE" C Source CodeWarrior
+#.cgm "CGMm" "GKON" Computer Graphics Meta GraphicConverter
+#.class "Clss" "CWIE" Java Class File CodeWarrior
+#.clp "CLPp" "GKON" Windows Clipboard GraphicConverter
+#.cmd "TEXT" "ttxt" OS/2 Batch File SimpleText
+#.com "PCFA" "SWIN" MS-DOS Executable SoftWindows
+#.cp "TEXT" "CWIE" C++ Source CodeWarrior
+#.cpp "TEXT" "CWIE" C++ Source CodeWarrior
+#.cpt "PACT" "SITx" Compact Pro Archive StuffIt Expander
+#.csv "TEXT" "XCEL" Comma Separated Vars Excel
+#.ct "..CT" "GKON" Scitex-CT GraphicConverter
+#.cut "Halo" "GKON" Dr Halo Image GraphicConverter
+#.cvs "drw2" "DAD2" Canvas Drawing Canvas
+#.dbf "COMP" "FOX+" DBase Document FoxBase+
+#.dcx "DCXx" "GKON" Some PCX Images GraphicConverter
+#.dif "TEXT" "XCEL" Data Interchange Format Excel
+#.diz "TEXT" "R*Ch" BBS Descriptive Text BBEdit
+#.dl "DL " "AnVw" DL Animation MacAnim Viewer
+#.dll "PCFL" "SWIN" Windows DLL SoftWindows
+#.doc "WDBN" "MSWD" Word Document Microsoft Word application/msword
+#.dot "sDBN" "MSWD" Word for Windows Template Microsoft Word
+#.dvi "ODVI" "xdvi" TeX DVI Document xdvi application/x-dvi
+#.dwt "TEXT" "DmWr" Dreamweaver Template Dreamweaver
+#.dxf "TEXT" "SWVL" AutoCAD 3D Data Swivel Pro
+#.eps "EPSF" "vgrd" Postscript LaserWriter 8 application/postscript
+#.epsf "EPSF" "vgrd" Postscript LaserWriter 8 application/postscript
+#.etx "TEXT" "ezVu" SEText Easy View text/x-setext
+#.evy "EVYD" "ENVY" Envoy Document Envoy
+#.exe "PCFA" "SWIN" MS-DOS Executable SoftWindows
+#.faq "TEXT" "ttxt" ASCII Text SimpleText text/x-usenet-faq
+#.fit "FITS" "GKON" Flexible Image Transport GraphicConverter image/x-fits
+#.fla "SPA " "MFL2" Flash source Macromedia Flash
+#.flc "FLI " "TVOD" FLIC Animation QuickTime Player
+#.fli "FLI " "TVOD" FLI Animation QuickTime Player
+#.fm "FMPR" "FMPR" FileMaker Pro Database FileMaker Pro
+#.for "TEXT" "MPS " Fortran Source MPW Shell
+#.fts "FITS" "GKON" Flexible Image Transport GraphicConverter
+#.gem "GEM-" "GKON" GEM Metafile GraphicConverter
+#.gif "GIFf" "ogle" GIF Picture PictureViewer image/gif
+#.gl "GL " "AnVw" GL Animation MacAnim Viewer
+#.grp "GRPp" "GKON" GRP Image GraphicConverter
+#.gz "SIT!" "SITx" Gnu ZIP Archive StuffIt Expander application/x-gzip
+#.h "TEXT" "CWIE" C Include File CodeWarrior
+#.hcom "FSSD" "SCPL" SoundEdit Sound ex SOX SoundApp
+#.hp "TEXT" "CWIE" C Include File CodeWarrior
+#.hpgl "HPGL" "GKON" HP GL/2 GraphicConverter
+#.hpp "TEXT" "CWIE" C Include File CodeWarrior
+#.hqx "TEXT" "SITx" BinHex StuffIt Expander application/mac-binhex40
+#.htm "TEXT" "MOSS" HyperText Netscape Communicator text/html
+#.html "TEXT" "MOSS" HyperText Netscape Communicator text/html
+#.i3 "TEXT" "R*ch" Modula 3 Interface BBEdit
+#.ic1 "IMAG" "GKON" Atari Image GraphicConverter
+#.ic2 "IMAG" "GKON" Atari Image GraphicConverter
+#.ic3 "IMAG" "GKON" Atari Image GraphicConverter
+#.icn "ICO " "GKON" Windows Icon GraphicConverter
+#.ico "ICO " "GKON" Windows Icon GraphicConverter
+#.ief "IEF " "GKON" IEF image GraphicConverter image/ief
+#.iff "ILBM" "GKON" Amiga IFF Image GraphicConverter
+#.ilbm "ILBM" "GKON" Amiga ILBM Image GraphicConverter
+#.image "dImg" "ddsk" Apple DiskCopy Image Disk Copy
+#.img "IMGg" "GKON" GEM bit image/XIMG GraphicConverter
+#.ini "TEXT" "ttxt" Windows INI File SimpleText
+#.java "TEXT" "CWIE" Java Source File CodeWarrior
+#.jfif "JPEG" "ogle" JFIF Image PictureViewer
+#.jpe "JPEG" "ogle" JPEG Picture PictureViewer image/jpeg
+#.jpeg "JPEG" "ogle" JPEG Picture PictureViewer image/jpeg
+#.jpg "JPEG" "ogle" JPEG Picture PictureViewer image/jpeg
+#.latex "TEXT" "OTEX" Latex OzTex application/x-latex
+#.lbm "ILBM" "GKON" Amiga IFF Image GraphicConverter
+#.lha "LHA " "SITx" LHArc Archive StuffIt Expander
+#.lzh "LHA " "SITx" LHArc Archive StuffIt Expander
+#.m1a "MPEG" "TVOD" MPEG-1 audiostream MoviePlayer audio/x-mpeg
+#.m1s "MPEG" "TVOD" MPEG-1 systemstream MoviePlayer
+#.m1v "M1V " "TVOD" MPEG-1 IPB videostream MoviePlayer video/mpeg
+#.m2 "TEXT" "R*ch" Modula 2 Source BBEdit
+#.m2v "MPG2" "MPG2" MPEG-2 IPB videostream MPEG2decoder
+#.m3 "TEXT" "R*ch" Modula 3 Source BBEdit
+#.mac "PICT" "ogle" PICT Picture PictureViewer image/x-pict
+#.mak "TEXT" "R*ch" Makefile BBEdit
+#.mcw "WDBN" "MSWD" Mac Word Document Microsoft Word
+#.me "TEXT" "ttxt" Text Readme SimpleText
+#.med "STrk" "SCPL" Amiga MED Sound SoundApp
+#.mf "TEXT" "*MF*" Metafont Metafont
+#.mid "Midi" "TVOD" MIDI Music MoviePlayer
+#.midi "Midi" "TVOD" MIDI Music MoviePlayer
+#.mif "TEXT" "Fram" FrameMaker MIF FrameMaker application/x-framemaker
+#.mime "TEXT" "SITx" MIME Message StuffIt Expander message/rfc822
+#.ml "TEXT" "R*ch" ML Source BBEdit
+#.mod "STrk" "SCPL" MOD Music SoundApp
+#.mol "TEXT" "RSML" MDL Molfile RasMac
+#.moov "MooV" "TVOD" QuickTime Movie MoviePlayer video/quicktime
+#.mov "MooV" "TVOD" QuickTime Movie MoviePlayer video/quicktime
+#.mp2 "MPEG" "TVOD" MPEG-1 audiostream MoviePlayer audio/x-mpeg
+#.mp3 "MPG3" "TVOD" MPEG-3 audiostream MoviePlayer audio/x-mpeg
+#.mpa "MPEG" "TVOD" MPEG-1 audiostream MoviePlayer audio/x-mpeg
+#.mpe "MPEG" "TVOD" MPEG Movie of some sort MoviePlayer video/mpeg
+#.mpeg "MPEG" "TVOD" MPEG Movie of some sort MoviePlayer video/mpeg
+#.mpg "MPEG" "TVOD" MPEG Movie of some sort MoviePlayer video/mpeg
+#.msp "MSPp" "GKON" Microsoft Paint GraphicConverter
+#.mtm "MTM " "SNPL" MultiMOD Music PlayerPro
+#.mw "MW2D" "MWII" MacWrite Document MacWrite II application/macwriteii
+#.mwii "MW2D" "MWII" MacWrite Document MacWrite II application/macwriteii
+#.neo "NeoC" "GKON" Atari NeoChrome GraphicConverter
+#.nfo "TEXT" "ttxt" Info Text SimpleText application/text
+#.nst "STrk" "SCPL" MOD Music SoundApp
+#.obj "PCFL" "SWIN" Object (DOS/Windows) SoftWindows
+#.oda "ODIF" "ODA " ODA Document MacODA XTND Translator application/oda
+#.okt "OKTA" "SCPL" Oktalyser MOD Music SoundApp
+#.out "BINA" "hDmp" Output File HexEdit
+#.ovl "PCFL" "SWIN" Overlay (DOS/Windows) SoftWindows
+#.p "TEXT" "CWIE" Pascal Source CodeWarrior
+#.pac "STAD" "GKON" Atari STAD Image GraphicConverter
+#.pas "TEXT" "CWIE" Pascal Source CodeWarrior
+#.pbm "PPGM" "GKON" Portable Bitmap GraphicConverter image/x-portable-bitmap
+#.pc1 "Dega" "GKON" Atari Degas Image GraphicConverter
+#.pc2 "Dega" "GKON" Atari Degas Image GraphicConverter
+#.pc3 "Dega" "GKON" Atari Degas Image GraphicConverter
+#.pcs "PICS" "GKON" Animated PICTs GraphicConverter
+#.pct "PICT" "ogle" PICT Picture PictureViewer image/x-pict
+#.pcx "PCXx" "GKON" PC PaintBrush GraphicConverter
+#.pdb "TEXT" "RSML" Brookhaven PDB file RasMac
+#.pdf "PDF " "CARO" Portable Document Format Acrobat Reader application/pdf
+#.pdx "TEXT" "ALD5" Printer Description PageMaker
+#.pf "CSIT" "SITx" Private File StuffIt Expander
+#.pgm "PPGM" "GKON" Portable Graymap GraphicConverter image/x-portable-graymap
+#.pi1 "Dega" "GKON" Atari Degas Image GraphicConverter
+#.pi2 "Dega" "GKON" Atari Degas Image GraphicConverter
+#.pi3 "Dega" "GKON" Atari Degas Image GraphicConverter
+#.pic "PICT" "ogle" PICT Picture PictureViewer image/x-pict
+#.pict "PICT" "ogle" PICT Picture PictureViewer image/x-macpict
+#.pit "PIT " "SITx" PackIt Archive StuffIt Expander
+#.pkg "HBSF" "SITx" AppleLink Package StuffIt Expander
+#.pl "TEXT" "McPL" Perl Source MacPerl
+#.plt "HPGL" "GKON" HP GL/2 GraphicConverter
+#.pm "PMpm" "GKON" Bitmap from xv GraphicConverter
+#.pm3 "ALB3" "ALD3" PageMaker 3 Document PageMaker
+#.pm4 "ALB4" "ALD4" PageMaker 4 Document PageMaker
+#.pm5 "ALB5" "ALD5" PageMaker 5 Document PageMaker
+#.png "PNG " "ogle" Portable Network Graphic PictureViewer
+#.pntg "PNTG" "ogle" Macintosh Painting PictureViewer
+#.ppd "TEXT" "ALD5" Printer Description PageMaker
+#.ppm "PPGM" "GKON" Portable Pixmap GraphicConverter image/x-portable-pixmap
+#.prn "TEXT" "R*ch" Printer Output File BBEdit
+#.ps "TEXT" "vgrd" PostScript LaserWriter 8 application/postscript
+#.psd "8BPS" "8BIM" PhotoShop Document Photoshop
+#.pt4 "ALT4" "ALD4" PageMaker 4 Template PageMaker
+#.pt5 "ALT5" "ALD5" PageMaker 5 Template PageMaker
+#.pxr "PXR " "8BIM" Pixar Image Photoshop
+#.qdv "QDVf" "GKON" QDV image GraphicConverter
+#.qt "MooV" "TVOD" QuickTime Movie MoviePlayer video/quicktime
+#.qxd "XDOC" "XPR3" QuarkXpress Document QuarkXpress
+#.qxt "XTMP" "XPR3" QuarkXpress Template QuarkXpress
+#.raw "BINA" "GKON" Raw Image GraphicConverter
+#.readme "TEXT" "ttxt" Text Readme SimpleText application/text
+#.rgb "SGI " "GKON" SGI Image GraphicConverter image/x-rgb
+#.rgba "SGI " "GKON" SGI Image GraphicConverter image/x-rgb
+#.rib "TEXT" "RINI" Renderman 3D Data Renderman
+#.rif "RIFF" "GKON" RIFF Graphic GraphicConverter
+#.rle "RLE " "GKON" RLE image GraphicConverter
+#.rme "TEXT" "ttxt" Text Readme SimpleText
+#.rpl "FRL!" "REP!" Replica Document Replica
+#.rsc "rsrc" "RSED" Resource File ResEdit
+#.rsrc "rsrc" "RSED" Resource File ResEdit
+#.rtf "TEXT" "MSWD" Rich Text Format Microsoft Word application/rtf
+#.rtx "TEXT" "R*ch" Rich Text BBEdit text/richtext
+#.s3m "S3M " "SNPL" ScreamTracker 3 MOD PlayerPro
+#.scc "MSX " "GKON" MSX pitcure GraphicConverter
+#.scg "RIX3" "GKON" ColoRIX GraphicConverter
+#.sci "RIX3" "GKON" ColoRIX GraphicConverter
+#.scp "RIX3" "GKON" ColoRIX GraphicConverter
+#.scr "RIX3" "GKON" ColoRIX GraphicConverter
+#.scu "RIX3" "GKON" ColoRIX GraphicConverter
+#.sea "APPL" "????" Self-Extracting Archive Self Extracting Archive
+#.sf "IRCM" "SDHK" IRCAM Sound SoundHack
+#.sgi ".SGI" "ogle" SGI Image PictureViewer
+#.sha "TEXT" "UnSh" Unix Shell Archive UnShar application/x-shar
+#.shar "TEXT" "UnSh" Unix Shell Archive UnShar application/x-shar
+#.shp "SHPp" "GKON" Printmaster Icon Library GraphicConverter
+#.sit "SIT!" "SITx" StuffIt 1.5.1 Archive StuffIt Expander application/x-stuffit
+#.sithqx "TEXT" "SITx" BinHexed StuffIt Archive StuffIt Expander application/mac-binhex40
+#.six "SIXE" "GKON" SIXEL image GraphicConverter
+#.slk "TEXT" "XCEL" SYLK Spreadsheet Excel
+#.snd "BINA" "SCPL" Sound of various types SoundApp
+#.spc "Spec" "GKON" Atari Spectrum 512 GraphicConverter
+#.sr "SUNn" "GKON" Sun Raster Image GraphicConverter
+#.sty "TEXT" "*TEX" TeX Style Textures
+#.sun "SUNn" "GKON" Sun Raster Image GraphicConverter
+#.sup "SCRN" "GKON" StartupScreen GraphicConverter
+#.svx "8SVX" "SCPL" Amiga IFF Sound SoundApp
+#.syk "TEXT" "XCEL" SYLK Spreadsheet Excel
+#.sylk "TEXT" "XCEL" SYLK Spreadsheet Excel
+#.tar "TARF" "SITx" Unix Tape ARchive StuffIt Expander application/x-tar
+#.targa "TPIC" "GKON" Truevision Image GraphicConverter
+#.taz "ZIVU" "SITx" Compressed Tape ARchive StuffIt Expander application/x-compress
+#.tex "TEXT" "OTEX" TeX Document OzTeX application/x-tex
+#.texi "TEXT" "OTEX" TeX Document OzTeX
+#.texinfo "TEXT" "OTEX" TeX Document OzTeX application/x-texinfo
+#.text "TEXT" "ttxt" ASCII Text SimpleText text/plain
+#.tga "TPIC" "GKON" Truevision Image GraphicConverter
+#.tgz "Gzip" "SITx" Gnu ZIPed Tape ARchive StuffIt Expander application/x-gzip
+#.tif "TIFF" "ogle" TIFF Picture PictureViewer image/tiff
+#.tiff "TIFF" "ogle" TIFF Picture PictureViewer image/tiff
+#.tny "TINY" "GKON" Atari TINY Bitmap GraphicConverter
+#.tsv "TEXT" "XCEL" Tab Separated Values Excel text/tab-separated-values
+#.tx8 "TEXT" "ttxt" 8-bit ASCII Text SimpleText
+#.txt "TEXT" "ttxt" ASCII Text SimpleText text/plain
+#.ul "ULAW" "TVOD" Mu-Law Sound MoviePlayer audio/basic
+#.url "AURL" "Arch" URL Bookmark Anarchie message/external-body
+#.uu "TEXT" "SITx" UUEncode StuffIt Expander
+#.uue "TEXT" "SITx" UUEncode StuffIt Expander
+#.vff "VFFf" "GKON" DESR VFF Greyscale Image GraphicConverter
+#.vga "BMPp" "ogle" OS/2 Bitmap PictureViewer
+#.voc "VOC " "SCPL" VOC Sound SoundApp
+#.w51 ".WP5" "WPC2" WordPerfect PC 5.1 Doc WordPerfect application/wordperfect5.1
+#.wav "WAVE" "TVOD" Windows WAV Sound MoviePlayer audio/x-wav
+#.wk1 "XLBN" "XCEL" Lotus Spreadsheet r2.1 Excel
+#.wks "XLBN" "XCEL" Lotus Spreadsheet r1.x Excel
+#.wmf "WMF " "GKON" Windows Metafile GraphicConverter
+#.wp ".WP5" "WPC2" WordPerfect PC 5.1 Doc WordPerfect application/wordperfect5.1
+#.wp4 ".WP4" "WPC2" WordPerfect PC 4.2 Doc WordPerfect
+#.wp5 ".WP5" "WPC2" WordPerfect PC 5.x Doc WordPerfect application/wordperfect5.1
+#.wp6 ".WP6" "WPC2" WordPerfect PC 6.x Doc WordPerfect
+#.wpg "WPGf" "GKON" WordPerfect Graphic GraphicConverter
+#.wpm "WPD1" "WPC2" WordPerfect Mac WordPerfect
+#.wri "WDBN" "MSWD" MS Write/Windows Microsoft Word
+#.wve "BINA" "SCPL" PSION sound SoundApp
+#.x10 "XWDd" "GKON" X-Windows Dump GraphicConverter image/x-xwd
+#.x11 "XWDd" "GKON" X-Windows Dump GraphicConverter image/x-xwd
+#.xbm "XBM " "GKON" X-Windows Bitmap GraphicConverter image/x-xbm
+#.xl "XLS " "XCEL" Excel Spreadsheet Excel
+#.xlc "XLC " "XCEL" Excel Chart Excel
+#.xlm "XLM " "XCEL" Excel Macro Excel
+#.xls "XLS " "XCEL" Excel Spreadsheet Excel
+#.xlw "XLW " "XCEL" Excel Workspace Excel
+#.xm "XM " "SNPL" FastTracker MOD Music PlayerPro
+#.xpm "XPM " "GKON" X-Windows Pixmap GraphicConverter image/x-xpm
+#.xwd "XWDd" "GKON" X-Windows Dump GraphicConverter image/x-xwd
+#.Z "ZIVU" "SITx" Unix Compress Archive StuffIt Expander application/x-compress
+#.zip "ZIP " "SITx" PC ZIP Archive StuffIt Expander application/zip
+#.zoo "Zoo " "Booz" Zoo Archive MacBooz
+
+# I'd like to dedicate this as follows code to Miss.Tamaki Imazu
+#
+# Kazuhiko Okudaira the Nursery Teacher
+# kokudaira@hotmail.com
+
+#.bld "BLD " "GKON" BLD GraphicConverter
+#.bum ".bMp" "GKON" QuickTime Importer(QuickDraw) GraphicConverter
+#.cel "CEL " "GKON" KISS CEL GraphicConverter
+#.cur "CUR " "GKON" Windows Cursor GraphicConverter
+#.cwj "CWSS" "cwkj" ClarisWorks Document ClarisWorks 4.0
+#.dat "TCLl" "GKON" TCL image GraphicConverter
+#.hr "TR80" "GKON" TSR-80 HR GraphicConverter
+#.iss "ISS " "GKON" ISS GraphicConverter
+#.jif "JIFf" "GKON" JIF99a GraphicConverter
+#.lwf "lwfF" "GKON" LuraWave(LWF) GraphicConverter
+#.mbm "MBM " "GKON" PSION 5(MBM) GraphicConverter
+#.ngg "NGGC" "GKON" Mobile Phone(Nokia)Format GraphicConverter
+#.nol "NOL " "GKON" Mobile Phone(Nokia)Format GraphicConverter
+#.pal "8BCT" "8BIM" Color Table GraphicConverter
+#.pgc "PGCF" "GKON" PGC/PGF Atari Portfolio PCG GraphicConverter
+#.pics "PICS" "GKON" PICS-PICT Sequence GraphicConverter
+#.swf "SWFL" "SWF2" Flash Macromedia Flash
+#.vpb "VPB " "GKON" VPB QUANTEL GraphicConverter
+#.wbmp "WBMP" "GKON" WBMP GraphicConverter
+#.x-face "TEXT" "GKON" X-Face GraphicConverter
dnl these tests have been comfirmed to be needed in 2011
AC_CHECK_FUNCS(backtrace_symbols dirfd getusershell pread pwrite pselect)
-AC_CHECK_FUNCS(setlinebuf strlcat strlcpy strnlen)
+AC_CHECK_FUNCS(setlinebuf strlcat strlcpy strnlen mempcpy)
AC_CHECK_FUNCS(mmap utime getpagesize) dnl needed by tbd
dnl search for necessary libraries
AC_SEARCH_LIBS(gethostbyname, nsl)
AC_SEARCH_LIBS(connect, socket)
-AC_SEARCH_LIBS(pthread_sigmask, pthread,,[AC_MSG_ERROR([missing pthread_sigmask])])
-if test x"$ac_cv_search_pthread_sigmask" != x"none required" ; then
- PTHREAD_LIBS=$ac_cv_search_pthread_sigmask
-fi
-AC_SUBST(PTHREAD_LIBS)
+AX_PTHREAD(, [AC_MSG_ERROR([missing pthread_sigmask])])
AC_DEFINE(OPEN_NOFOLLOW_ERRNO, ELOOP, errno returned by open with O_NOFOLLOW)
use File::Spec;
use File::Temp qw /tempfile/;
use bigint; # require perl >= 5.8
+use IPC::Open2 qw /open2/;
# check command for extended attributes -----------------------------------
sub checkea {
my ($file) = @_;
- $file =~ s/\\/\\\\/g;
- $file =~ s/\"/\\\"/g;
- $file =~ s/\$/\\\$/g;
- $file =~ s/\`/\\\`/g;
if ( $eacommand == 1 ) {
- open(EALIST, "getfattr \"$file\" |");
+ open2(\*EALIST, \*EAIN, 'getfattr', $file) or die $@;
while(<EALIST>) {
if ( $_ eq "user.org.netatalk.Metadata\n" ) {
- close (EALIST);
+ close (EALIST, EAIN);
return 1;
}
}
- close (EALIST);
+ close (EALIST, EAIN);
return 0;
} elsif ( $eacommand == 2 ) {
- open(EALIST, "attr -q -l \"$file\" |");
+ open2(\*EALIST, \*EAIN, 'attr', '-q', '-l', $file) or die $@;
while(<EALIST>) {
if ( $_ eq "org.netatalk.Metadata\n" ) {
- close (EALIST);
+ close (EALIST, EAIN);
return 1;
}
}
- close (EALIST);
+ close (EALIST, EAIN);
return 0;
} elsif ( $eacommand == 3 ) {
- open(EALIST, "runat \"$file\" ls -1 |");
+ open2(\*EALIST, \*EAIN, 'runat', $file, 'ls', '-1') or die $@;
while(<EALIST>) {
if ( $_ eq "org.netatalk.Metadata\n" ) {
- close (EALIST);
+ close (EALIST, EAIN);
return 1;
}
}
- close (EALIST);
+ close (EALIST, EAIN);
return 0;
} elsif ( $eacommand == 4 ) {
- open(EALIST, "lsextattr -q user \"$file\" |");
+ open2(\*EALIST, \*EAIN, 'lsextattr', '-q', 'user', $file) or die $@;
while(<EALIST>) {
$_ = "\t".$_;
if ( $_ =~ /\torg\.netatalk\.Metadata[\n\t]/ ) {
- close (EALIST);
+ close (EALIST, EAIN);
return 1;
}
}
- close (EALIST);
+ close (EALIST, EAIN);
return 0;
} else {
return 0;
sub eaopenfile {
my ($file) = @_;
-
- $file =~ s/\\/\\\\/g;
- $file =~ s/\"/\\\"/g;
- $file =~ s/\$/\\\$/g;
- $file =~ s/\`/\\\`/g;
- ($eatempfh, $eatempfile) = tempfile(UNLINK => 1);
+ my @eacommands = ();
if ( $eacommand == 1 ) {
- system("getfattr --only-values -n user.org.netatalk.Metadata \"$file\" > $eatempfile");
+ @eacommands = ('getfattr', '--only-values', '-n', 'user.org.netatalk.Metadata', $file);
} elsif ( $eacommand == 2 ) {
- system("attr -q -g org.netatalk.Metadata \"$file\" > $eatempfile");
+ @eacommands = ('attr', '-q', '-g', 'org.netatalk.Metadata', $file);
} elsif ( $eacommand == 3 ) {
- system("runat \"$file\" cat org.netatalk.Metadata > $eatempfile");
+ @eacommands = ('runat', $file, 'cat', 'org.netatalk.Metadata',);
} elsif ( $eacommand == 4 ) {
- system("getextattr -q user org.netatalk.Metadata \"$file\" > $eatempfile");
+ @eacommands = ('getextattr', '-q', 'user', 'org.netatalk.Metadata', $file);
} else {
return "";
}
+ my ($eatempfh, $eatempfile) = tempfile(UNLINK => 1);
+ open2(my $ealist, my $eain, @eacommands) or die $@;
+ print $eatempfh $_ while(<$ealist>);
+ close($ealist, $eain);
close($eatempfh);
return $eatempfile;
}
CLEANFILES = $(GENERATED_FILES) $(sysv_SCRIPTS) $(service_DATA) afpd cnid_metad
EXTRA_DIST = $(TEMPLATES)
+noinst_DATA = $(GENERATED_FILES)
# overwrite automake uninstall
# not beautiful, but this way we can call the OS specific init script
[Unit]
Description=Netatalk AFP fileserver for Macintosh clients
+Documentation=man:afp.conf(5) man:netatalk(8) man:afpd(8) man:cnid_metad(8) man:cnid_dbd(8)
+Documentation=http://netatalk.sourceforge.net/
After=syslog.target network.target avahi-daemon.service
[Service]
file.c \
filedir.c \
fork.c \
- gettok.c \
hash.c \
main.c \
mangle.c \
afpd_LDFLAGS = -export-dynamic
afpd_CFLAGS = \
- @ZEROCONF_CFLAGS@ @GSSAPI_CFLAGS@ @KRB5_CFLAGS@\
+ @ZEROCONF_CFLAGS@ @GSSAPI_CFLAGS@ @KRB5_CFLAGS@ @PTHREAD_CFLAGS@\
-DAPPLCNAME \
-DSERVERTEXT=\"$(SERVERTEXT)/\" \
-D_PATH_AFPDPWFILE=\"$(pkgconfdir)/afppasswd\" \
EC_EXIT;
}
+#if 0
/*!
* Add entries of one acl to another acl
*
EC_CLEANUP:
EC_EXIT;
}
+#endif
/*!
* Map Darwin ACE rights to POSIX 1e perm
acl_entry_t entry;
acl_tag_t tag;
int entry_id = ACL_FIRST_ENTRY;
- int has_def_acl = 0;
/* flags to indicate if the object has a minimal default acl and/or an extended
* default acl.
*/
int ret;
uint32_t allowed_rights = 0;
char *username = NULL;
- uuidtype_t uuidtype;
struct stat st;
bstring parent = NULL;
int is_dir;
}
#endif
- EC_ZERO_LOG_ERR(lstat(path, &st), AFPERR_PARAM);
+ EC_ZERO_LOG_ERR(ostat(path, &st, vol_syml_opt(vol)), AFPERR_PARAM);
is_dir = !strcmp(path, ".");
LOG(log_debug, logtype_afpd, "afp_getacl: client requested files owner user UUID");
if (NULL == (pw = getpwuid(s_path->st.st_uid))) {
LOG(log_debug, logtype_afpd, "afp_getacl: local uid: %u", s_path->st.st_uid);
- localuuid_from_id(rbuf, UUID_USER, s_path->st.st_uid);
+ localuuid_from_id((unsigned char *)rbuf, UUID_USER, s_path->st.st_uid);
} else {
LOG(log_debug, logtype_afpd, "afp_getacl: got uid: %d, name: %s", s_path->st.st_uid, pw->pw_name);
- if ((ret = getuuidfromname(pw->pw_name, UUID_USER, rbuf)) != 0)
+ if ((ret = getuuidfromname(pw->pw_name, UUID_USER, (unsigned char *)rbuf)) != 0)
return AFPERR_MISC;
}
rbuf += UUID_BINSIZE;
LOG(log_debug, logtype_afpd, "afp_getacl: client requested files owner group UUID");
if (NULL == (gr = getgrgid(s_path->st.st_gid))) {
LOG(log_debug, logtype_afpd, "afp_getacl: local gid: %u", s_path->st.st_gid);
- localuuid_from_id(rbuf, UUID_GROUP, s_path->st.st_gid);
+ localuuid_from_id((unsigned char *)rbuf, UUID_GROUP, s_path->st.st_gid);
} else {
LOG(log_debug, logtype_afpd, "afp_getacl: got gid: %d, name: %s", s_path->st.st_gid, gr->gr_name);
- if ((ret = getuuidfromname(gr->gr_name, UUID_GROUP, rbuf)) != 0)
+ if ((ret = getuuidfromname(gr->gr_name, UUID_GROUP, (unsigned char *)rbuf)) != 0)
return AFPERR_MISC;
}
rbuf += UUID_BINSIZE;
int acltoownermode(const AFPObj *obj, const struct vol *vol, char *path, struct stat *st, struct maccess *ma)
{
EC_INIT;
- uint32_t rights = 0;
if ( ! (obj->options.flags & OPTION_ACL2MACCESS)
|| ! (vol->v_flags & AFPVOL_ACLS))
getcwdpath(), path, ma->ma_user);
#ifdef HAVE_SOLARIS_ACLS
+ uint32_t rights = 0;
EC_ZERO_LOG(solaris_acl_rights(obj, path, st, &rights));
LOG(log_maxdebug, logtype_afpd, "rights: 0x%08x", rights);
/*!
- * Free and cleanup all linked DSI objects from config
+ * Free and cleanup config and DSI
*
- * Preserve object pointed to by "dsi".
- * "dsi" can be NULL in which case all DSI objects _and_ the options object are freed
+ * "dsi" can be NULL in which case all DSI objects and the config object is freed,
+ * otherwise its an afpd session child and only any unneeded DSI objects are freed
*/
void configfree(AFPObj *obj, DSI *dsi)
{
DSI *p, *q;
- /* the master loaded the volumes for zeroconf, get rid of that */
+ if (!dsi) {
+ /* Master afpd reloading config */
+ auth_unload();
+ if (! (obj->options.flags & OPTION_NOZEROCONF)) {
+ zeroconf_deregister();
+ }
+ }
+
unload_volumes(obj);
+ /* Master and child releasing unneeded DSI handles */
for (p = obj->dsi; p; p = q) {
q = p->next;
if (p == dsi)
continue;
- close(p->socket);
+ dsi_free(p);
free(p);
}
+ obj->dsi = NULL;
+ /* afpd session child passes dsi handle to obj handle */
if (dsi) {
dsi->next = NULL;
obj->dsi = dsi;
- } else {
- afp_options_free(&obj->options);
}
}
auth_load(obj->options.uampath, obj->options.uamlist);
set_signature(&obj->options);
+#ifdef HAVE_LDAP
+ acl_ldap_freeconfig();
+#endif /* HAVE_LDAP */
LOG(log_debug, logtype_afpd, "DSIConfigInit: hostname: %s, listen: %s, port: %s",
obj->options.hostname,
/* Now register with zeroconf, we also need the volumes for that */
if (! (obj->options.flags & OPTION_NOZEROCONF)) {
- load_volumes(obj, NULL);
+ load_volumes(obj);
zeroconf_register(obj);
}
/* SIGQUIT handler */
static void ipc_reconnect_handler(int sig _U_)
{
- DSI *dsi = (DSI *)AFPobj->dsi;
-
if (reconnect_ipc(AFPobj) != 0) {
LOG(log_error, logtype_afpd, "ipc_reconnect_handler: failed IPC reconnect");
afp_dsi_close(AFPobj);
if (reload_request) {
reload_request = 0;
- load_volumes(AFPobj, closevol);
+ load_volumes(AFPobj);
}
/* The first SIGINT enables debugging, the next restores the config */
LOG(log_debug, logtype_afpd, "<== Start AFP command: %s", AfpNum2name(function));
err = (*afp_switch[function])(obj,
- dsi->commands, dsi->cmdlen,
+ (char *)dsi->commands, dsi->cmdlen,
(char *)&dsi->data, &dsi->datalen);
LOG(log_debug, logtype_afpd, "==> Finished AFP command: %s -> %s",
LOG(log_debug, logtype_afpd, "<== Start AFP command: %s", AfpNum2name(function));
err = (*afp_switch[function])(obj,
- dsi->commands, dsi->cmdlen,
+ (char *)dsi->commands, dsi->cmdlen,
(char *)&dsi->data, &dsi->datalen);
LOG(log_debug, logtype_afpd, "==> Finished AFP command: %s -> %s",
free(str); free(key); \
}
+static struct pollfd *fds;
/*
* This is the thread that polls the filehandles
*/
-void *polling_thread(void *arg) {
+static void *polling_thread(void *arg) {
// First we loop through getting the filehandles and adding them to our poll, we
// need to allocate our pollfd's
DNSServiceErrorType error;
- struct pollfd *fds = calloc(svc_ref_count, sizeof(struct pollfd));
+ fds = calloc(svc_ref_count, sizeof(struct pollfd));
assert(fds);
for(int i=0; i < svc_ref_count; i++) {
return(NULL);
}
-
/*
* This is the callback for the service register function ... actually there isn't a lot
* we can do if we get problems, so we don't really need to do anything other than report
* the issue.
*/
-void RegisterReply(DNSServiceRef sdRef, DNSServiceFlags flags, DNSServiceErrorType errorCode,
- const char *name, const char *regtype, const char *domain, void *context) {
-
- if(errorCode != kDNSServiceErr_NoError) {
+static void RegisterReply(DNSServiceRef sdRef, DNSServiceFlags flags, DNSServiceErrorType errorCode,
+ const char *name, const char *regtype, const char *domain, void *context)
+{
+ if (errorCode != kDNSServiceErr_NoError) {
LOG(log_error, logtype_afpd, "Failed to register mDNS service: %s%s%s: code=%d",
name, regtype, domain, errorCode);
}
}
-
/*
* This function unregisters anything we have already
* registered and frees associated memory
*/
static void unregister_stuff() {
- pthread_kill(poller, SIGKILL);
+ pthread_cancel(poller);
+
+ for (int i = 0; i < svc_ref_count; i++)
+ close(fds[i].fd);
+ free(fds);
+ fds = NULL;
+
if(svc_refs) {
for(int i=0; i < svc_ref_count; i++) {
DNSServiceRefDeallocate(svc_refs[i]);
LOG(log_info, logtype_afpd, "Registering server '%s' with model '%s'",
dsi->bonjourname, obj->options.mimicmodel);
TXTRecordCreate(&txt_devinfo, 0, NULL);
- TXTRecordPrintf(&txt_devinfo, "model=%s", obj->options.mimicmodel);
+ TXTRecordPrintf(&txt_devinfo, "model", obj->options.mimicmodel);
error = DNSServiceRegister(&svc_refs[svc_ref_count++],
0, // no flags
0, // all network interfaces
DEV_INFO_SERVICE_TYPE,
"", // default domains
NULL, // default host name
- 0,
+ /*
+ * We would probably use port 0 zero, but we can't, from man DNSServiceRegister:
+ * "A value of 0 for a port is passed to register placeholder services.
+ * Place holder services are not found when browsing, but other
+ * clients cannot register with the same name as the placeholder service."
+ * We therefor use port 9 which is used by the adisk service type.
+ */
+ htons(9),
TXTRecordGetLength(&txt_devinfo),
TXTRecordGetBytesPtr(&txt_devinfo),
RegisterReply, // callback
#define LENGTH 512
-/* get rid of any allocated afp_option buffers. */
-void afp_options_free(struct afp_options *opt)
-{
- if (opt->hostname)
- free(opt->hostname);
- if (opt->adminauthuser)
- free(opt->adminauthuser);
- if (opt->configfile)
- free(opt->configfile);
- if (opt->fqdn)
- free(opt->fqdn);
- if (opt->guest)
- free(opt->guest);
- if (opt->listen)
- free(opt->listen);
- if (opt->k5realm)
- free(opt->k5realm);
- if (opt->k5keytab)
- free(opt->k5keytab);
- if (opt->k5service)
- free(opt->k5service);
- if (opt->logconfig)
- free(opt->logconfig);
- if (opt->logfile)
- free(opt->logfile);
- if (opt->loginmesg)
- free(opt->loginmesg);
- if (opt->maccodepage)
- free(opt->maccodepage);
- if (opt->mimicmodel)
- free(opt->mimicmodel);
- if (opt->ntdomain)
- free(opt->ntdomain);
- if (opt->ntseparator)
- free(opt->ntseparator);
- if (opt->passwdfile)
- free(opt->passwdfile);
- if (opt->port)
- free(opt->port);
- if (opt->signatureopt)
- free(opt->signatureopt);
- if (opt->uamlist)
- free(opt->uamlist);
- if (opt->uampath)
- free(opt->uampath);
- if (opt->unixcodepage)
- free(opt->unixcodepage);
-}
-
/*
* Show version information about afpd.
* Used by "afp -v".
static void show_paths( void )
{
printf( " afp.conf:\t%s\n", _PATH_CONFDIR "afp.conf");
+ printf( " extmap.conf:\t%s\n", _PATH_CONFDIR "extmap.conf");
printf( " state directory:\t%s\n", _PATH_STATEDIR);
printf( " afp_signature.conf:\t%s\n", _PATH_STATEDIR "afp_signature.conf");
printf( " afp_voluuid.conf:\t%s\n", _PATH_STATEDIR "afp_voluuid.conf");
/*
- * $Id: afp_util.c,v 1.10 2010-01-23 14:44:42 franklahm Exp $
*
* Copyright (c) 1999 Adrian Sun (asun@zoology.washington.edu)
* Copyright (c) 1990,1993 Regents of The University of Michigan.
/*
- * $Id: afs.c,v 1.18 2009-10-15 10:43:13 didg Exp $
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
*/
/*
- * $Id: appl.c,v 1.18.4.1 2010-02-01 10:56:08 franklahm Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
#include "config.h"
#endif /* HAVE_CONFIG_H */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
*
*/
struct dsitem {
-// struct dir *dir; /* Structure describing this directory */
-// cnid_t did; /* CNID of this directory */
- int pidx; /* Parent's dsitem structure index. */
- int checked; /* Have we checked this directory ? */
- int path_len;
- char *path; /* absolute UNIX path to this directory */
+ cnid_t ds_did; /* CNID of this directory */
+ int ds_checked; /* Have we checked this directory ? */
};
save_cidx = -1;
while (dsidx > 0) {
dsidx--;
- free(dstack[dsidx].path);
}
}
static int addstack(char *uname, struct dir *dir, int pidx)
{
struct dsitem *ds;
- size_t l, u;
struct dsitem *tmpds = NULL;
/* check if we have some space on stack... */
/* Put new element. Allocate and copy lname and path. */
ds = dstack + dsidx++;
-// ds->did = dir->d_did;
- ds->pidx = pidx;
- ds->checked = 0;
- if (pidx >= 0) {
- l = dstack[pidx].path_len;
- u = strlen(uname) +1;
- if (!(ds->path = malloc(l + u + 1) ))
- return -1;
- memcpy(ds->path, dstack[pidx].path, l);
- ds->path[l] = '/';
- memcpy(&ds->path[l+1], uname, u);
- ds->path_len = l +u;
- }
- else {
- ds->path = strdup(uname);
- ds->path_len = strlen(uname);
- }
+ ds->ds_did = dir->d_did;
+ ds->ds_checked = 0;
return 0;
}
}
while (dsidx > 0) {
- if (dstack[dsidx-1].checked) {
+ if (dstack[dsidx-1].ds_checked) {
dsidx--;
- free(dstack[dsidx].path);
+// free(dstack[dsidx].path);
} else
return dsidx - 1;
}
isdir = S_ISDIR(path->st.st_mode);
- if (!isdir && (of = of_findname(path))) {
+ if (!isdir && (of = of_findname(vol, path))) {
adp = of->of_ad;
} else {
ad_init(&ad, vol);
int num_rounds = NUM_ROUNDS;
int cwd = -1;
int error;
-
+ int unlen;
+
if (*pos != 0 && *pos != cur_pos) {
result = AFPERR_CATCHNG;
goto catsearch_end;
start_time = time(NULL);
while ((cidx = reducestack()) != -1) {
- LOG(log_debug, logtype_afpd, "catsearch: dir: \"%s\"", dstack[cidx].path);
+ if ((currentdir = dirlookup(vol, dstack[cidx].ds_did)) == NULL) {
+ result = AFPERR_MISC;
+ goto catsearch_end;
+ }
+ LOG(log_debug, logtype_afpd, "catsearch: current struct dir: \"%s\"", cfrombstr(currentdir->d_fullpath));
- error = lchdir(dstack[cidx].path);
+ error = movecwd(vol, currentdir);
if (!error && dirpos == NULL)
dirpos = opendir(".");
if (dirpos == NULL)
- dirpos = opendir(dstack[cidx].path);
+ dirpos = opendir(cfrombstr(currentdir->d_fullpath));
if (error || dirpos == NULL) {
switch (errno) {
case EACCES:
- dstack[cidx].checked = 1;
+ dstack[cidx].ds_checked = 1;
continue;
case EMFILE:
case ENFILE:
goto catsearch_end;
}
- if ((currentdir = dirlookup_bypath(vol, dstack[cidx].path)) == NULL) {
- result = AFPERR_MISC;
- goto catsearch_end;
- }
- LOG(log_debug, logtype_afpd, "catsearch: current struct dir: \"%s\"", cfrombstr(currentdir->d_fullpath));
while ((entry = readdir(dirpos)) != NULL) {
(*pos)++;
memset(&path, 0, sizeof(path));
path.u_name = entry->d_name;
- if (of_stat(&path) != 0) {
+ if (of_stat(vol, &path) != 0) {
switch (errno) {
case EACCES:
case ELOOP:
goto catsearch_end;
}
}
- if (S_ISDIR(path.st.st_mode)) {
+ switch (S_IFMT & path.st.st_mode) {
+ case S_IFDIR:
/* here we can short cut
ie if in the same loop the parent dir wasn't in the cache
ALL dirsearch_byname will fail.
*/
- int unlen = strlen(path.u_name);
+ unlen = strlen(path.u_name);
path.d_dir = dircache_search_by_name(vol,
currentdir,
path.u_name,
result = AFPERR_MISC;
goto catsearch_end;
}
- } else {
+ break;
+ case S_IFREG:
path.d_dir = currentdir;
+ break;
+ default:
+ continue;
}
ccr = crit_check(vol, &path);
} /* while ((entry=readdir(dirpos)) != NULL) */
closedir(dirpos);
dirpos = NULL;
- dstack[cidx].checked = 1;
+ dstack[cidx].ds_checked = 1;
} /* while (current_idx = reducestack()) != -1) */
/* We have finished traversing our tree. Return EOF here. */
path.u_name = name;
path.m_name = utompath(vol, name, cnid, utf8_encoding(vol->v_obj));
- if (of_stat(&path) != 0) {
+ if (of_stat(vol, &path) != 0) {
switch (errno) {
case EACCES:
case ELOOP:
#include <atalk/netatalk_conf.h>
#include <atalk/unix.h>
#include <atalk/bstrlib.h>
+#include <atalk/bstradd.h>
#include <atalk/errchk.h>
#include "volume.h"
bstring dtpath = bfromcstr(vol->v_dbpath);
bcatcstr(dtpath, "/" APPLEDESKTOP);
- EC_NEG1( chdir(bdata(dtpath)) );
+ EC_NEG1( chdir(cfrombstr(dtpath)) );
if (( desk = opendir( "." )) == NULL ) {
if ( chdir( wd ) < 0 ) {
bstring dtpath = bfromcstr(vol->v_dbpath);
bcatcstr(dtpath, "/" APPLEDESKTOP);
- EC_NEG1( chdir(bdata(dtpath)) );
+ EC_NEG1( chdir(cfrombstr(dtpath)) );
if (( desk = opendir( "." )) == NULL ) {
if ( chdir( wd ) < 0 ) {
LOG(log_error, logtype_afpd, "setdeskowner: chdir %s: %s", wd, strerror(errno) );
EC_FAIL;
}
- if (chown(bdata(dtpath), uid, gid ) < 0 && errno != EPERM ) {
+ if (chown(cfrombstr(dtpath), uid, gid ) < 0 && errno != EPERM ) {
LOG(log_error, logtype_afpd, "setdeskowner: chown %s: %s", fullpathname(".AppleDouble"), strerror(errno) );
}
dtpath = bfromcstr(vol->v_dbpath);
bcatcstr(dtpath, "/" APPLEDESKTOP);
- if (lstat(bdata(dtpath), &st) != 0) {
+ if (lstat(cfrombstr(dtpath), &st) != 0) {
become_root();
- if (lstat(bdata(olddtpath), &st) == 0) {
+ if (lstat(cfrombstr(olddtpath), &st) == 0) {
cmd_argv[0] = "mv";
cmd_argv[1] = bdata(olddtpath);
cmd_argv[2] = bdata(dtpath);
if (run_cmd("mv", cmd_argv) != 0) {
LOG(log_error, logtype_afpd, "moving .AppleDesktop from \"%s\" to \"%s\" failed",
bdata(olddtpath), bdata(dtpath));
- mkdir(bdata(dtpath), 0777);
+ mkdir(cfrombstr(dtpath), 0777);
}
} else {
- mkdir(bdata(dtpath), 0777);
+ mkdir(cfrombstr(dtpath), 0777);
}
unbecome_root();
}
isadir = path_isadir(path);
- if (isadir || !(of = of_findname(path))) {
+ if (isadir || !(of = of_findname(vol, path))) {
ad_init(&ad, vol);
adp = &ad;
} else
upath = path->u_name;
isadir = path_isadir(path);
- if (isadir || !(of = of_findname(path))) {
+ if (isadir || !(of = of_findname(vol, path))) {
ad_init(&ad, vol);
adp = &ad;
} else
}
isadir = path_isadir(path);
- if (isadir || !(of = of_findname(path))) {
+ if (isadir || !(of = of_findname(vol, path))) {
ad_init(&ad, vol);
adp = &ad;
} else
int dircache_add(const struct vol *vol,
struct dir *dir)
{
- struct dir *cdir = NULL;
struct dir key;
hnode_t *hn;
}
/* ------------------- */
-static int deletedir(int dirfd, char *dir)
+static int deletedir(const struct vol *vol, int dirfd, char *dir)
{
char path[MAXPATHLEN + 1];
DIR *dp;
break;
}
strcpy(path + len, de->d_name);
- if (lstatat(dirfd, path, &st)) {
+ if (ostatat(dirfd, path, &st, vol_syml_opt(vol))) {
continue;
}
if (S_ISDIR(st.st_mode)) {
- err = deletedir(dirfd, path);
+ err = deletedir(vol, dirfd, path);
} else {
err = netatalk_unlinkat(dirfd, path);
}
}
/* do a recursive copy. */
-static int copydir(const struct vol *vol, int dirfd, char *src, char *dst)
+static int copydir(struct vol *vol, struct dir *ddir, int dirfd, char *src, char *dst)
{
char spath[MAXPATHLEN + 1], dpath[MAXPATHLEN + 1];
DIR *dp;
}
strcpy(spath + slen, de->d_name);
- if (lstatat(dirfd, spath, &st) == 0) {
+ if (ostatat(dirfd, spath, &st, vol_syml_opt(vol)) == 0) {
if (strlen(de->d_name) > drem) {
err = AFPERR_PARAM;
break;
strcpy(dpath + dlen, de->d_name);
if (S_ISDIR(st.st_mode)) {
- if (AFP_OK != (err = copydir(vol, dirfd, spath, dpath)))
+ if (AFP_OK != (err = copydir(vol, ddir, dirfd, spath, dpath)))
goto copydir_done;
- } else if (AFP_OK != (err = copyfile(vol, vol, dirfd, spath, dpath, NULL, NULL))) {
+ } else if (AFP_OK != (err = copyfile(vol, vol, ddir, dirfd, spath, dpath, NULL, NULL))) {
goto copydir_done;
} else {
}
/* keep the same time stamp. */
- if (lstatat(dirfd, src, &st) == 0) {
+ if (ostatat(dirfd, src, &st, vol_syml_opt(vol)) == 0) {
ut.actime = ut.modtime = st.st_mtime;
utime(dst, &ut);
}
LOG(log_debug, logtype_afpd, "dirlookup(did: %u): stating \"%s\"",
ntohl(did), cfrombstr(fullpath));
- if (lstat(cfrombstr(fullpath), &st) != 0) { /* 5a */
+ if (ostat(cfrombstr(fullpath), &st, vol_syml_opt(vol)) != 0) { /* 5a */
switch (errno) {
case ENOENT:
afp_errno = AFPERR_NOOBJ;
void dir_free_invalid_q(void)
{
struct dir *dir;
- while (dir = (struct dir *)dequeue(invalid_dircache_entries))
+ while ((dir = (struct dir *)dequeue(invalid_dircache_entries)))
dir_free(dir);
}
* and thus call continue which should terminate the while loop because
* len = 0. Ok?
*/
- if (of_stat(&ret) != 0) { /* 9 */
+ if (of_stat(vol, &ret) != 0) { /* 9 */
/*
* ret.u_name doesn't exist, might be afp_createfile|dir
* that means it should have been the last part
LOG(log_debug, logtype_afpd, "movecwd(to: did: %u, \"%s\")",
ntohl(dir->d_did), cfrombstr(dir->d_fullpath));
- if ((ret = lchdir(cfrombstr(dir->d_fullpath))) != 0 ) {
+ if ((ret = ochdir(cfrombstr(dir->d_fullpath), vol_syml_opt(vol))) != 0 ) {
LOG(log_debug, logtype_afpd, "movecwd(\"%s\"): %s",
cfrombstr(dir->d_fullpath), strerror(errno));
if (ret == 1) {
return err;
}
- if (of_stat(s_path) < 0) {
+ if (of_stat(vol, s_path) < 0) {
return AFPERR_MISC;
}
ad_setname(&ad, s_path->m_name);
ad_setid( &ad, s_path->st.st_dev, s_path->st.st_ino, dir->d_did, did, vol->v_stamp);
- fce_register_new_dir(s_path);
+ fce_register(FCE_DIR_CREATE, bdata(curdir->d_fullpath), NULL, fce_dir);
ad_flush(&ad);
ad_close(&ad, ADFLAGS_HF);
-createdir_done:
memcpy( rbuf, &dir->d_did, sizeof( uint32_t ));
*rbuflen = sizeof( uint32_t );
setvoltime(obj, vol );
* newparent curdir
* dirfd -1 means ignore dirfd (or use AT_FDCWD), otherwise src is relative to dirfd
*/
-int renamedir(const struct vol *vol,
+int renamedir(struct vol *vol,
int dirfd,
char *src,
char *dst,
case EXDEV:
/* this needs to copy and delete. bleah. that means we have
* to deal with entire directory hierarchies. */
- if ((err = copydir(vol, dirfd, src, dst)) < 0) {
- deletedir(-1, dst);
+ if ((err = copydir(vol, newparent, dirfd, src, dst)) < 0) {
+ deletedir(vol, -1, dst);
return err;
}
- if ((err = deletedir(dirfd, src)) < 0)
+ if ((err = deletedir(vol, dirfd, src)) < 0)
return err;
break;
default :
/* bail if it's not a symlink */
if ((lstat(de->d_name, &st) == 0) && !S_ISLNK(st.st_mode)) {
LOG(log_error, logtype_afpd, "deletecurdir(\"%s\"): not empty",
- curdir->d_fullpath);
+ bdata(curdir->d_fullpath));
closedir(dp);
return AFPERR_DIRNEMPT;
}
return path_error(path, AFPERR_NOOBJ);
}
- if ( !path->st_valid && of_stat(path ) < 0 ) {
+ if ( !path->st_valid && of_stat(vol, path) < 0 ) {
return( AFPERR_NOOBJ );
}
if ( path->st_errno ) {
struct dir *, char *, size_t *);
extern int setdirparams(struct vol *, struct path *, uint16_t, char *);
-extern int renamedir(const struct vol *, int, char *, char *, struct dir *,
+extern int renamedir(struct vol *, int, char *, char *, struct dir *,
struct dir *, char *);
extern int path_error(struct path *, int error);
extern void setdiroffcnt(struct dir *dir, struct stat *st, uint32_t count);
if ( sindex == 1 || curdir->d_did != sd.sd_did || vid != sd.sd_vid ) {
sd.sd_last = sd.sd_buf;
/* if dir was in the cache we don't have the inode */
- if (( !o_path->st_valid && lstat( ".", &o_path->st ) < 0 ) ||
+ if (( !o_path->st_valid && ostat(".", &o_path->st, vol_syml_opt(vol)) < 0 ) ||
(ret = for_each_dirent(vol, ".", enumerate_loop, (void *)&sd)) < 0)
{
LOG(log_error, logtype_afpd, "enumerate: loop error: %s (%d)", strerror(errno), errno);
sd.sd_last += len + 1;
continue;
}
- memset(&s_path, 0, sizeof(s_path));
- /* conversions on the fly */
- const char *convname;
+ memset(&s_path, 0, sizeof(s_path));
s_path.u_name = sd.sd_last;
- if (ad_convert(sd.sd_last, &s_path.st, vol, &convname) == 0 && convname) {
- s_path.u_name = (char *)convname;
- }
-
- if (of_stat( &s_path) < 0 ) {
+ if (of_stat(vol, &s_path) < 0 ) {
/* so the next time it won't try to stat it again
* another solution would be to invalidate the cache with
* sd.sd_did = 0 but if it's not ENOENT error it will start again
continue;
}
+ /* conversions on the fly */
+ const char *convname;
+ if (ad_convert(sd.sd_last, &s_path.st, vol, &convname) == 0 && convname) {
+ s_path.u_name = (char *)convname;
+ }
+
/* Fixup CNID db if ad_convert resulted in a rename (then convname != NULL) */
if (convname) {
s_path.id = cnid_lookup(vol->v_cdb, &s_path.st, curdir->d_did, sd.sd_last, strlen(sd.sd_last));
if (s_path.id != CNID_INVALID) {
- if (cnid_update(vol->v_cdb, s_path.id, &s_path.st, curdir->d_did, convname, strlen(convname)) != 0)
+ if (cnid_update(vol->v_cdb, s_path.id, &s_path.st, curdir->d_did, (char *)convname, strlen(convname)) != 0)
LOG(log_error, logtype_afpd, "enumerate: error updating CNID of \"%s\"", fullpathname(convname));
}
}
/*
- $Id: extattrs.h,v 1.3 2009-10-15 10:43:13 didg Exp $
Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
This program is free software; you can redistribute it and/or modify
/*
* Copyright (c) 2010 Mark Williams
+ * Copyright (c) 2012 Frank Lahm <franklahm@gmail.com>
*
* File change event API for netatalk
*
#include <stdlib.h>
#include <errno.h>
#include <time.h>
-
-
#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
+#include <stdbool.h>
#include <atalk/adouble.h>
#include <atalk/vfs.h>
// ONLY USED IN THIS FILE
#include "fce_api_internal.h"
-#define FCE_TRUE 1
-#define FCE_FALSE 0
-
/* We store our connection data here */
static struct udp_entry udp_socket_list[FCE_MAX_UDP_SOCKS];
static int udp_sockets = 0;
-static int udp_initialized = FCE_FALSE;
+static bool udp_initialized = false;
static unsigned long fce_ev_enabled =
(1 << FCE_FILE_MODIFY) |
(1 << FCE_FILE_DELETE) |
(1 << FCE_FILE_CREATE) |
(1 << FCE_DIR_CREATE);
-static uint64_t tm_used; /* used for passing to event handler */
#define MAXIOBUF 1024
-static char iobuf[MAXIOBUF];
+static unsigned char iobuf[MAXIOBUF];
static const char *skip_files[] =
{
".DS_Store",
};
static struct fce_close_event last_close_event;
+static char *fce_event_names[] = {
+ "",
+ "FCE_FILE_MODIFY",
+ "FCE_FILE_DELETE",
+ "FCE_DIR_DELETE",
+ "FCE_FILE_CREATE",
+ "FCE_DIR_CREATE"
+};
+
/*
*
* Initialize network structs for any listeners
int rv;
struct addrinfo hints, *servinfo, *p;
- if (udp_initialized == FCE_TRUE)
+ if (udp_initialized == true)
return;
memset(&hints, 0, sizeof hints);
close(udp_entry->sock);
if ((rv = getaddrinfo(udp_entry->addr, udp_entry->port, &hints, &servinfo)) != 0) {
- LOG(log_error, logtype_afpd, "fce_init_udp: getaddrinfo(%s:%s): %s",
+ LOG(log_error, logtype_fce, "fce_init_udp: getaddrinfo(%s:%s): %s",
udp_entry->addr, udp_entry->port, gai_strerror(rv));
continue;
}
/* loop through all the results and make a socket */
for (p = servinfo; p != NULL; p = p->ai_next) {
if ((udp_entry->sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
- LOG(log_error, logtype_afpd, "fce_init_udp: socket(%s:%s): %s",
+ LOG(log_error, logtype_fce, "fce_init_udp: socket(%s:%s): %s",
udp_entry->addr, udp_entry->port, strerror(errno));
continue;
}
}
if (p == NULL) {
- LOG(log_error, logtype_afpd, "fce_init_udp: no socket for %s:%s",
+ LOG(log_error, logtype_fce, "fce_init_udp: no socket for %s:%s",
udp_entry->addr, udp_entry->port);
}
udp_entry->addrinfo = *p;
freeaddrinfo(servinfo);
}
- udp_initialized = FCE_TRUE;
+ udp_initialized = true;
}
void fce_cleanup()
{
- if (udp_initialized == FCE_FALSE )
+ if (udp_initialized == false )
return;
for (int i = 0; i < udp_sockets; i++)
udp_entry->sock = -1;
}
}
- udp_initialized = FCE_FALSE;
+ udp_initialized = false;
}
/*
* Construct a UDP packet for our listeners and return packet size
* */
-static ssize_t build_fce_packet( struct fce_packet *packet, char *path, int mode, uint32_t event_id )
+static ssize_t build_fce_packet( struct fce_packet *packet, const char *path, int event, uint32_t event_id )
{
size_t pathlen = 0;
ssize_t data_len = 0;
- uint64_t *t;
/* Set content of packet */
memcpy(packet->magic, FCE_PACKET_MAGIC, sizeof(packet->magic) );
packet->version = FCE_PACKET_VERSION;
- packet->mode = mode;
+ packet->mode = event;
packet->event_id = event_id;
/* This is the payload len. Means: the packet has len bytes more until packet is finished */
data_len = FCE_PACKET_HEADER_SIZE + pathlen;
- switch (mode) {
- case FCE_TM_SIZE:
- t = (uint64_t *)packet->data;
- *t = hton64(tm_used);
- memcpy(packet->data + sizeof(tm_used), path, pathlen);
-
- packet->datalen = pathlen + sizeof(tm_used);
- data_len += sizeof(tm_used);
- break;
- default:
- memcpy(packet->data, path, pathlen);
- break;
- }
+ memcpy(packet->data, path, pathlen);
/* return the packet len */
return data_len;
* Send the fce information to all (connected) listeners
* We dont give return code because all errors are handled internally (I hope..)
* */
-static void send_fce_event( char *path, int mode )
+static void send_fce_event(const char *path, int event)
{
- static int first_event = FCE_TRUE;
+ static bool first_event = true;
struct fce_packet packet;
- void *data = &packet;
static uint32_t event_id = 0; /* the unique packet couter to detect packet/data loss. Going from 0xFFFFFFFF to 0x0 is a valid increment */
time_t now = time(NULL);
- LOG(log_debug, logtype_afpd, "send_fce_event: start");
+ LOG(log_debug, logtype_fce, "send_fce_event: start");
/* initialized ? */
- if (first_event == FCE_TRUE) {
- first_event = FCE_FALSE;
+ if (first_event == true) {
+ first_event = false;
fce_init_udp();
/* Notify listeners the we start from the beginning */
send_fce_event( "", FCE_CONN_START );
}
/* build our data packet */
- ssize_t data_len = build_fce_packet( &packet, path, mode, ++event_id );
+ ssize_t data_len = build_fce_packet( &packet, path, event, ++event_id );
pack_fce_packet(&packet, iobuf, MAXIOBUF);
for (int i = 0; i < udp_sockets; i++)
if (udp_entry->sock == -1) {
/* failed again, so go to rest again */
- LOG(log_error, logtype_afpd, "Cannot recreate socket for fce UDP connection: errno %d", errno );
+ LOG(log_error, logtype_fce, "Cannot recreate socket for fce UDP connection: errno %d", errno );
udp_entry->next_try_on_error = now + FCE_SOCKET_RETRY_DELAY_S;
continue;
udp_entry->addrinfo.ai_addrlen);
/* Rebuild our original data packet */
- data_len = build_fce_packet( &packet, path, mode, event_id );
+ data_len = build_fce_packet(&packet, path, event, event_id);
pack_fce_packet(&packet, iobuf, MAXIOBUF);
}
/* Problems ? */
if (sent_data != data_len) {
/* Argh, socket broke, we close and retry later */
- LOG(log_error, logtype_afpd, "send_fce_event: error sending packet to %s:%s, transfered %d of %d: %s",
+ LOG(log_error, logtype_fce, "send_fce_event: error sending packet to %s:%s, transfered %d of %d: %s",
udp_entry->addr, udp_entry->port, sent_data, data_len, strerror(errno));
close( udp_entry->sock );
target_port = FCE_DEFAULT_PORT_STRING;
if (udp_sockets >= FCE_MAX_UDP_SOCKS) {
- LOG(log_error, logtype_afpd, "Too many file change api UDP connections (max %d allowed)", FCE_MAX_UDP_SOCKS );
+ LOG(log_error, logtype_fce, "Too many file change api UDP connections (max %d allowed)", FCE_MAX_UDP_SOCKS );
return AFPERR_PARAM;
}
send_fce_event(last_close_event.path, FCE_FILE_MODIFY);
}
- LOG(log_debug, logtype_afpd, "save_close_event: %s", path);
+ LOG(log_debug, logtype_fce, "save_close_event: %s", path);
last_close_event.time = now;
strncpy(last_close_event.path, path, MAXPATHLEN);
* Dispatcher for all incoming file change events
*
* */
-static int register_fce(const char *u_name, int is_dir, int mode)
+int fce_register(fce_ev_t event, const char *path, const char *oldpath, fce_obj_t type)
{
- static int first_event = FCE_TRUE;
+ static bool first_event = true;
+ const char *bname;
+
+ if (!(fce_ev_enabled & (1 << event)))
+ return AFP_OK;
+
+ AFP_ASSERT(event >= FCE_FIRST_EVENT && event <= FCE_LAST_EVENT);
+
+ LOG(log_debug, logtype_fce, "register_fce(path: %s, type: %s, event: %s",
+ path , type == fce_dir ? "dir" : "file", fce_event_names[event]);
+
+ bname = basename_safe(path);
if (udp_sockets == 0)
/* No listeners configured */
return AFP_OK;
- if (u_name == NULL)
+ if (path == NULL)
return AFPERR_PARAM;
/* do some initialization on the fly the first time */
if (first_event) {
fce_initialize_history();
- first_event = FCE_FALSE;
+ first_event = false;
}
/* handle files which should not cause events (.DS_Store atc. ) */
- for (int i = 0; skip_files[i] != NULL; i++)
- {
- if (!strcmp( u_name, skip_files[i]))
+ for (int i = 0; skip_files[i] != NULL; i++) {
+ if (strcmp(bname, skip_files[i]) == 0)
return AFP_OK;
}
-
- char full_path_buffer[MAXPATHLEN + 1] = {""};
- const char *cwd = getcwdpath();
-
- if (mode == FCE_TM_SIZE) {
- strlcpy(full_path_buffer, u_name, MAXPATHLEN);
- } else if (!is_dir || mode == FCE_DIR_DELETE) {
- if (strlen( cwd ) + strlen( u_name) + 1 >= MAXPATHLEN) {
- LOG(log_error, logtype_afpd, "FCE file name too long: %s/%s", cwd, u_name );
- return AFPERR_PARAM;
- }
- sprintf( full_path_buffer, "%s/%s", cwd, u_name );
- } else {
- if (strlen( cwd ) >= MAXPATHLEN) {
- LOG(log_error, logtype_afpd, "FCE directory name too long: %s", cwd);
- return AFPERR_PARAM;
- }
- strcpy( full_path_buffer, cwd);
- }
-
/* Can we ignore this event based on type or history? */
- if (!(mode & FCE_TM_SIZE) && fce_handle_coalescation( full_path_buffer, is_dir, mode ))
- {
- LOG(log_debug9, logtype_afpd, "Coalesced fc event <%d> for <%s>", mode, full_path_buffer );
+ if (fce_handle_coalescation(event, path, type)) {
+ LOG(log_debug9, logtype_fce, "Coalesced fc event <%d> for <%s>", event, path);
return AFP_OK;
}
- LOG(log_debug9, logtype_afpd, "Detected fc event <%d> for <%s>", mode, full_path_buffer );
-
- if (mode & FCE_FILE_MODIFY) {
- save_close_event(full_path_buffer);
- return AFP_OK;
+ switch (event) {
+ case FCE_FILE_MODIFY:
+ save_close_event(path);
+ break;
+ default:
+ send_fce_event(path, event);
+ break;
}
- send_fce_event( full_path_buffer, mode );
-
return AFP_OK;
}
/* check if configured holdclose time has passed */
if (last_close_event.time && ((last_close_event.time + fmodwait) < now)) {
- LOG(log_debug, logtype_afpd, "check_saved_close_events: sending event: %s", last_close_event.path);
+ LOG(log_debug, logtype_fce, "check_saved_close_events: sending event: %s", last_close_event.path);
/* yes, send event */
send_fce_event(&last_close_event.path[0], FCE_FILE_MODIFY);
last_close_event.path[0] = 0;
/*
* API-Calls for file change api, called form outside (file.c directory.c ofork.c filedir.c)
* */
-#ifndef FCE_TEST_MAIN
-
void fce_pending_events(AFPObj *obj)
{
- vol_fce_tm_event();
check_saved_close_events(obj->options.fce_fmodwait);
}
-int fce_register_delete_file( struct path *path )
-{
- int ret = AFP_OK;
-
- if (path == NULL)
- return AFPERR_PARAM;
-
- if (!(fce_ev_enabled & (1 << FCE_FILE_DELETE)))
- return ret;
-
- ret = register_fce( path->u_name, false, FCE_FILE_DELETE );
-
- return ret;
-}
-int fce_register_delete_dir( char *name )
-{
- int ret = AFP_OK;
-
- if (name == NULL)
- return AFPERR_PARAM;
-
- if (!(fce_ev_enabled & (1 << FCE_DIR_DELETE)))
- return ret;
-
- ret = register_fce( name, true, FCE_DIR_DELETE);
-
- return ret;
-}
-
-int fce_register_new_dir( struct path *path )
-{
- int ret = AFP_OK;
-
- if (path == NULL)
- return AFPERR_PARAM;
-
- if (!(fce_ev_enabled & (1 << FCE_DIR_CREATE)))
- return ret;
-
- ret = register_fce( path->u_name, true, FCE_DIR_CREATE );
-
- return ret;
-}
-
-
-int fce_register_new_file( struct path *path )
-{
- int ret = AFP_OK;
-
- if (path == NULL)
- return AFPERR_PARAM;
-
- if (!(fce_ev_enabled & (1 << FCE_FILE_CREATE)))
- return ret;
-
- ret = register_fce( path->u_name, false, FCE_FILE_CREATE );
-
- return ret;
-}
-
-int fce_register_file_modification( struct ofork *ofork )
-{
- int ret = AFP_OK;
-
- if (ofork == NULL)
- return AFPERR_PARAM;
-
- if (!(fce_ev_enabled & (1 << FCE_FILE_MODIFY)))
- return ret;
-
- ret = register_fce(of_name(ofork), false, FCE_FILE_MODIFY );
-
- return ret;
-}
-
-int fce_register_tm_size(const char *vol, size_t used)
-{
- int ret = AFP_OK;
-
- if (vol == NULL)
- return AFPERR_PARAM;
-
- if (!(fce_ev_enabled & (1 << FCE_TM_SIZE)))
- return ret;
-
- tm_used = used; /* oh what a hack */
- ret = register_fce(vol, false, FCE_TM_SIZE);
-
- return ret;
-}
-#endif
-
/*
*
* Extern connect to afpd parameter, can be called multiple times for multiple listeners (up to MAX_UDP_SOCKS times)
fce_ev_enabled |= (1 << FCE_FILE_CREATE);
} else if (strcmp(p, "dcre") == 0) {
fce_ev_enabled |= (1 << FCE_DIR_CREATE);
- } else if (strcmp(p, "tmsz") == 0) {
- fce_ev_enabled |= (1 << FCE_TM_SIZE);
}
}
}
int main( int argc, char*argv[] )
{
- int c,ret;
+ int c;
char *port = FCE_DEFAULT_PORT_STRING;
char *host = "localhost";
if (end_time && now >= end_time)
break;
- register_fce( path, 0, event_code );
+ fce_register(event_code, path, NULL, 0);
ev_cnt++;
#include <stdbool.h>
+#include <atalk/fce_api.h>
+
#define FCE_MAX_UDP_SOCKS 5 /* Allow a maximum of udp listeners for file change events */
#define FCE_SOCKET_RETRY_DELAY_S 600 /* Pause this time in s after socket was broken */
#define FCE_PACKET_VERSION 1
#define FCE_COALESCE_DELETE (1 << 1)
#define FCE_COALESCE_ALL (FCE_COALESCE_CREATE | FCE_COALESCE_DELETE)
-struct udp_entry
-{
+struct udp_entry {
int sock;
char *addr;
char *port;
time_t next_try_on_error; /* In case of error set next timestamp to retry */
};
-struct fce_history
-{
- unsigned char mode;
- int is_dir;
- char path[MAXPATHLEN + 1];
- struct timeval tv;
+struct fce_history {
+ fce_ev_t fce_h_event;
+ fce_obj_t fce_h_type;
+ char fce_h_path[MAXPATHLEN + 1];
+ struct timeval fce_h_tv;
};
struct fce_close_event {
#define PACKET_HDR_LEN (sizeof(struct fce_packet) - FCE_MAX_PATH_LEN)
-bool fce_handle_coalescation( char *path, int is_dir, int mode );
+bool fce_handle_coalescation(int event, const char *path, fce_obj_t type);
void fce_initialize_history();
// ONLY USED IN THIS FILE
#include "fce_api_internal.h"
-#define FCE_TRUE 1
-#define FCE_FALSE 0
-
/* We store our connection data here */
static uint32_t coalesce = 0;
static struct fce_history fce_history_list[FCE_HISTORY_LEN];
}
}
-bool fce_handle_coalescation( char *path, int is_dir, int mode )
+bool fce_handle_coalescation(int event, const char *path, fce_obj_t type)
{
/* These two are used to eval our next index in history */
/* the history is unsorted, speed should not be a problem, length is 10 */
return false;
/* After a file creation *ALWAYS* a file modification is produced */
- if ((mode == FCE_FILE_CREATE) && (coalesce & FCE_COALESCE_CREATE))
+ if ((event == FCE_FILE_CREATE) && (coalesce & FCE_COALESCE_CREATE))
return true;
/* get timestamp */
struct fce_history *fh = &fce_history_list[i];
/* Not inited ? */
- if (fh->tv.tv_sec == 0) {
+ if (fh->fce_h_tv.tv_sec == 0) {
/* we can use it for new elements */
oldest_entry = 0;
oldest_entry_idx = i;
}
/* Too old ? */
- if (get_ms_difftime( &fh->tv, &tv ) > MAX_COALESCE_TIME_MS) {
+ if (get_ms_difftime(&fh->fce_h_tv, &tv ) > MAX_COALESCE_TIME_MS) {
/* Invalidate entry */
- fh->tv.tv_sec = 0;
+ fh->fce_h_tv.tv_sec = 0;
oldest_entry = 0;
oldest_entry_idx = i;
continue;
/* If we find a parent dir wich was created we are done */
- if ((coalesce & FCE_COALESCE_CREATE) && (fh->mode == FCE_DIR_CREATE)) {
+ if ((coalesce & FCE_COALESCE_CREATE) && (fh->fce_h_event == FCE_DIR_CREATE)) {
/* Parent dir ? */
- if (!strncmp(fh->path, path, strlen(fh->path)))
+ if (!strncmp(fh->fce_h_path, path, strlen(fh->fce_h_path)))
return true;
}
/* If we find a parent dir we should be DELETED we are done */
if ((coalesce & FCE_COALESCE_DELETE)
- && fh->is_dir
- && (mode == FCE_FILE_DELETE || mode == FCE_DIR_DELETE)) {
+ && fh->fce_h_type
+ && (event == FCE_FILE_DELETE || event == FCE_DIR_DELETE)) {
/* Parent dir ? */
- if (!strncmp(fh->path, path, strlen(fh->path)))
+ if (!strncmp(fh->fce_h_path, path, strlen(fh->fce_h_path)))
return true;
}
/* Detect oldest entry for next new entry */
- if (oldest_entry_idx == -1 || fh->tv.tv_sec < oldest_entry) {
- oldest_entry = fh->tv.tv_sec;
+ if (oldest_entry_idx == -1 || fh->fce_h_tv.tv_sec < oldest_entry) {
+ oldest_entry = fh->fce_h_tv.tv_sec;
oldest_entry_idx = i;
}
}
/* We have a new entry for the history, register it */
- fce_history_list[oldest_entry_idx].tv = tv;
- fce_history_list[oldest_entry_idx].mode = mode;
- fce_history_list[oldest_entry_idx].is_dir = is_dir;
- strncpy( fce_history_list[oldest_entry_idx].path, path, MAXPATHLEN);
+ fce_history_list[oldest_entry_idx].fce_h_tv = tv;
+ fce_history_list[oldest_entry_idx].fce_h_event = event;
+ fce_history_list[oldest_entry_idx].fce_h_type = type;
+ strncpy(fce_history_list[oldest_entry_idx].fce_h_path, path, MAXPATHLEN);
/* we have to handle this event */
return false;
/* 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;
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);
+ chk_ext = 1;
if (vol_inv_dots(vol) && *upath == '.') { /* make it invisible */
uint16_t ashort;
}
}
- if (islink){
+ if (islink && !vol_syml_opt(vol)) {
uint16_t linkflag;
memcpy(&linkflag, (char *)data + FINDERINFO_FRFLAGOFF, 2);
linkflag |= htons(FINDERINFO_ISALIAS);
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;
}
struct adouble ad, *adp;
int opened = 0;
int rc;
- int flags;
+ int flags; /* uninitialized ok */
LOG(log_debug, logtype_afpd, "getfilparams(\"%s\")", path->u_name);
}
}
rc = getmetadata(obj, vol, bitmap, path, dir, buf, buflen, adp);
- ad_close(adp, ADFLAGS_HF | flags);
+
+ if (opened)
+ ad_close(adp, ADFLAGS_HF | flags);
return( rc );
}
ad_init(&ad, vol);
/* if upath is deleted we already in trouble anyway */
- if ((of = of_findname(s_path))) {
+ if ((of = of_findname(vol, s_path))) {
if (creatf)
return AFPERR_BUSY;
else
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++;
setvoltime(obj, 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);
+ int fp;
+ ssize_t len;
+ char symbuf[MAXPATHLEN+1];
#ifdef DEBUG
LOG(log_debug9, logtype_afpd, "begin setfilparams:");
break;
case FILPBIT_FINFO :
change_mdate = 1;
- memcpy(finder_buf, buf, 32 );
- if (memcmp(buf, "slnkrhap", 8) == 0 && !S_ISLNK(path->st.st_mode)) {
- int fp;
- ssize_t len;
- int erc=1;
- char buf[PATH_MAX+1];
- if ((fp = open(path->u_name, O_RDONLY)) >= 0) {
- if ((len = read(fp, buf, PATH_MAX+1))) {
- if (unlink(path->u_name) == 0) {
- buf[len] = 0;
- erc = symlink(buf, path->u_name);
- if (!erc)
- of_stat(path);
- }
- }
- close(fp);
+ if (memcmp(buf,"slnkrhap",8) == 0
+ && !(S_ISLNK(path->st.st_mode))
+ && !(vol->v_flags & AFPVOL_FOLLOWSYM)) {
+ /* request to turn this into a symlink */
+ if ((fp = open(path->u_name, O_RDONLY)) == -1) {
+ err = AFPERR_MISC;
+ goto setfilparam_done;
+ }
+ len = read(fp, symbuf, MAXPATHLEN);
+ close(fp);
+ if (!(len > 0)) {
+ err = AFPERR_MISC;
+ goto setfilparam_done;
}
- if (erc != 0) {
- err=AFPERR_BITMAP;
+ if (unlink(path->u_name) != 0) {
+ err = AFPERR_MISC;
goto setfilparam_done;
}
+ symbuf[len] = 0;
+ if (symlink(symbuf, path->u_name) != 0) {
+ err = AFPERR_MISC;
+ goto setfilparam_done;
+ }
+ of_stat(vol, path);
symlinked = 1;
}
+ memcpy(finder_buf, buf, 32 );
buf += 32;
break;
case FILPBIT_UNIXPR :
isad = 0;
} else if ((ad_get_MD_flags( adp ) & O_CREAT) ) {
ad_setname(adp, path->m_name);
+ cnid_t id;
+ if ((id = get_id(vol, adp, &path->st, curdir->d_did, upath, strlen(upath))) == CNID_INVALID) {
+ LOG(log_error, logtype_afpd, "afp_createfile(\"%s\"): CNID error", upath);
+ return AFPERR_MISC;
+ }
+ (void)ad_setid(adp, path->st.st_dev, path->st.st_ino, id, curdir->d_did, vol->v_stamp);
}
bit = 0;
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 :
* 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;
/* 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 );
}
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;
}
* 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,
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;
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) {
cnid_t did = param->did;
cnid_t aint;
- if ( lstat(de->d_name, &path.st) < 0 )
+ if (ostat(de->d_name, &path.st, vol_syml_opt(vol)) < 0)
return 0;
/* update or add to cnid */
}
/* FIXME use of_statdir ? */
- if (lstat(name, &st)) {
+ if (ostat(name, &st, vol_syml_opt(vol))) {
return -1;
}
memset(&path, 0, sizeof(path));
path.u_name = upath;
- if ( of_stat(&path) < 0 ) {
+ if (of_stat(vol, &path) < 0 ) {
#ifdef ESTALE
/* with nfs and our working directory is deleted */
if (errno == ESTALE) {
}
err = AFP_OK;
- if ((movecwd(vol, dir) < 0) || (lstat(upath, &st) < 0)) {
+ if ((movecwd(vol, dir) < 0) || (ostat(upath, &st, vol_syml_opt(vol)) < 0)) {
switch (errno) {
case EACCES:
case EPERM:
return NULL;
}
- if ((*of = of_findname(path))) {
+ if ((*of = of_findname(vol, path))) {
/* reuse struct adouble so it won't break locks */
adp = (*of)->of_ad;
}
* NOTE: the temp file will be in the dest file's directory. it
* will also be inaccessible from AFP. */
memcpy(temp, APPLETEMP, sizeof(APPLETEMP));
- if (!mktemp(temp)) {
+ int fd;
+ if ((fd = mkstemp(temp)) == -1) {
err = AFPERR_MISC;
goto err_exchangefile;
}
-
+ close(fd);
+
if (crossdev) {
/* FIXME we need to close fork for copy, both s_of and d_of are null */
ad_close(adsp, ADFLAGS_HF);
}
/* 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);
if (did)
cnid_delete(vol->v_cdb, did);
- if ((did && ( (crossdev && lstat( upath, &srcst) < 0) ||
+ if ((did && ( (crossdev && ostat(upath, &srcst, vol_syml_opt(vol)) < 0) ||
cnid_update(vol->v_cdb, did, &srcst, curdir->d_did,upath, dlen) < 0))
||
- (sid && ( (crossdev && lstat(p, &destst) < 0) ||
+ (sid && ( (crossdev && ostat(p, &destst, vol_syml_opt(vol)) < 0) ||
cnid_update(vol->v_cdb, sid, &destst, sdir->d_did,supath, slen) < 0))
) {
switch (errno) {
* 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:
#define FILPBIT_EXTRFLEN 14
#define FILPBIT_UNIXPR 15
-struct extmap {
- char *em_ext;
- char em_creator[ 4 ];
- char em_type[ 4 ];
-};
-
#define kTextEncodingUTF8 0x08000103
typedef enum {
extern int getfilparams (const AFPObj *obj, struct vol *, uint16_t, struct path *,
struct dir *, char *buf, size_t *, int);
extern int setfilparams (const AFPObj *obj, struct vol *, struct path *, uint16_t, char *);
-extern int renamefile (const struct vol *, int, char *, char *, char *, struct adouble *);
-extern int copyfile (const struct vol *, const struct vol *, int, char *, char *, char *, struct adouble *);
+extern int renamefile (struct vol *, struct dir *, int, char *, char *, char *, struct adouble *);
+extern int copyfile (struct vol *, struct vol *, struct dir *, int, char *, char *, char *, struct adouble *);
extern int deletefile (const struct vol *, int, char *, int);
extern int getmetadata (const AFPObj *obj, struct vol *vol, uint16_t bitmap, struct path *path,
move and rename sdir:oldname to curdir:newname in volume vol
special care is needed for lock
*/
-static int moveandrename(const struct vol *vol,
+static int moveandrename(struct vol *vol,
struct dir *sdir,
int sdir_fd,
char *oldname,
if ( !isdir ) {
path.st_valid = 1;
path.st_errno = errno;
- if (of_findname(&path)) {
+ if (of_findname(vol, &path)) {
rc = AFPERR_EXIST; /* was AFPERR_BUSY; */
} else {
- rc = renamefile(vol, sdir_fd, oldunixname, upath, newname, adp );
+ rc = renamefile(vol, curdir, sdir_fd, oldunixname, upath, newname, adp );
if (rc == AFP_OK)
of_rename(vol, opened, sdir, oldname, curdir, newname);
}
delcnid = cnid_get(vol->v_cdb, curdir->d_did, upath, strlen(upath));
if (delcnid != CNID_INVALID)
cnid_delete(vol->v_cdb, delcnid);
- fce_register_delete_dir(upath);
+ fce_register(FCE_DIR_DELETE, fullpathname(upath), NULL, fce_dir);
} else {
/* we have to cache this, the structs are lost in deletcurdir*/
/* but we need the positive returncode to send our event */
if ((dname = bstrcpy(curdir->d_u_name)) == NULL)
return AFPERR_MISC;
if ((rc = deletecurdir(vol)) == AFP_OK)
- fce_register_delete_dir(cfrombstr(dname));
+ fce_register(FCE_DIR_DELETE, fullpathname(cfrombstr(dname)), NULL, fce_dir);
bdestroy(dname);
}
- } else if (of_findname(s_path)) {
+ } else if (of_findname(vol, s_path)) {
rc = AFPERR_BUSY;
} else {
/* it's a file st_valid should always be true
rc = AFPERR_NOOBJ;
} else {
if ((rc = deletefile(vol, -1, upath, 1)) == AFP_OK) {
- fce_register_delete_file( s_path );
+ fce_register(FCE_FILE_DELETE, fullpathname(upath), NULL, fce_file);
if (vol->v_tm_used < s_path->st.st_size)
vol->v_tm_used = 0;
else
if (!isdir && !vol_unix_priv(vol)) {
int admode = ad_mode("", 0777) | vol->v_fperm;
- setfilmode(upath, admode, NULL, vol->v_umask);
- vol->vfs->vfs_setfilmode(vol, upath, admode, NULL);
+ setfilmode(vol, upath, admode, path->st_valid ? &path->st : NULL);
+ vol->vfs->vfs_setfilmode(vol, upath, admode, path->st_valid ? &path->st : NULL);
}
setvoltime(obj, vol );
}
#include <atalk/logger.h>
#include <atalk/util.h>
#include <atalk/cnid.h>
+#include <atalk/bstrlib.h>
#include <atalk/bstradd.h>
#include <atalk/globals.h>
#include <atalk/netatalk_conf.h>
struct stat *st;
uint16_t bshort;
struct path *s_path;
- struct stat xxx;
ibuf++;
fork = *ibuf++;
}
}
- if ((opened = of_findname(s_path))) {
+ if ((opened = of_findname(vol, s_path))) {
adsame = opened->of_ad;
}
static int read_file(const struct ofork *ofork, int eid, off_t offset, char *rbuf, size_t *rbuflen)
{
ssize_t cc;
- int eof = 0;
- char *p, *q;
cc = ad_read(ofork->of_ad, eid, offset, rbuf, *rbuflen);
if ( cc < 0 ) {
off_t offset, char *rbuf,
size_t rbuflen)
{
- char *p, *q;
ssize_t cc;
LOG(log_debug, logtype_afpd, "write_file(off: %ju, size: %zu)",
uint16_t ofrefnum;
ssize_t cc;
DSI *dsi = obj->dsi;
- char *rcvbuf = dsi->commands;
+ char *rcvbuf = (char *)dsi->commands;
size_t rcvbuflen = dsi->server_quantum;
/* figure out parameters */
struct stat *);
extern void of_dealloc (struct ofork *);
extern struct ofork *of_find (const uint16_t);
-extern struct ofork *of_findname (struct path *);
+extern struct ofork *of_findname (const struct vol *vol, struct path *);
extern int of_rename (const struct vol *,
struct ofork *,
struct dir *, const char *,
struct dir *, const char *);
extern int of_flush (const struct vol *);
-extern int of_stat (struct path *);
+extern int of_stat (const struct vol *vol, struct path *);
extern int of_statdir (struct vol *vol, struct path *);
extern int of_closefork (const AFPObj *obj, struct ofork *ofork);
extern void of_closevol (const AFPObj *obj, const struct vol *vol);
+++ /dev/null
-/*
- * $Id: gettok.c,v 1.6 2009-10-13 22:55:37 didg Exp $
- *
- * Copyright (c) 1990,1994 Regents of The University of Michigan.
- * All Rights Reserved. See COPYRIGHT.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif /* HAVE_CONFIG_H */
-
-#include <sys/param.h>
-#include <string.h>
-#include <ctype.h>
-#include <pwd.h>
-
-#include <atalk/globals.h>
-
-static char *l_curr;
-static char *l_end;
-
-void initline( int len, char *line)
-{
- l_curr = line;
- l_end = line + len;
-}
-
-#define ST_QUOTE 0
-#define ST_WORD 1
-#define ST_BEGIN 2
-
-int
-parseline(int len, char *token)
-{
- char *p, *e;
- int state;
-
- state = ST_BEGIN;
- p = token;
- e = token + len;
-
- for (;;) {
- if ( l_curr > l_end ) { /* end of line */
- *token = '\0';
- return( -1 );
- }
-
- switch ( *l_curr ) {
- case '"' :
- if ( state == ST_QUOTE ) {
- state = ST_WORD;
- } else {
- state = ST_QUOTE;
- }
- break;
-
- case '\0' :
- case '\t' :
- case '\n' :
- case ' ' :
- if ( state == ST_WORD ) {
- *p = '\0';
- return( p - token );
- }
- if ( state != ST_QUOTE ) {
- break;
- }
- /* FALL THROUGH */
-
- default :
- if ( state == ST_BEGIN ) {
- state = ST_WORD;
- }
- if ( p > e ) { /* end of token */
- *token = '\0';
- return( -1 );
- }
- *p++ = *l_curr;
- break;
- }
-
- l_curr++;
- }
-}
-
-#ifdef notdef
-void parseline(char *token, char *user)
-{
- char *p = pos, *t = token, *u, *q, buf[ MAXPATHLEN ];
- struct passwd *pwent;
- int quoted = 0;
-
- while ( isspace( *p )) {
- p++;
- }
-
- /*
- * If we've reached the end of the line, or a comment,
- * don't return any more tokens.
- */
- if ( *p == '\0' || *p == '#' ) {
- *token = '\0';
- return;
- }
-
- if ( *p == '"' ) {
- p++;
- quoted = 1;
- }
- while ( *p != '\0' && ( quoted || !isspace( *p ))) {
- if ( *p == '"' ) {
- if ( quoted ) {
- *t = '\0';
- break;
- }
- quoted = 1;
- p++;
- } else {
- *t++ = *p++;
- }
- }
- pos = p;
- *t = '\0';
-
- /*
- * We got to the end of the line without closing an open quote
- */
- if ( *p == '\0' && quoted ) {
- *token = '\0';
- return;
- }
-
- t = token;
- if ( *t == '~' ) {
- t++;
- if ( *t == '\0' || *t == '/' ) {
- u = user;
- if ( *t == '/' ) {
- t++;
- }
- } else {
- u = t;
- if (( q = strchr( t, '/' )) == NULL ) {
- t = "";
- } else {
- *q = '\0';
- t = q + 1;
- }
- }
- if ( u == NULL || ( pwent = getpwnam( u )) == NULL ) {
- *token = '\0';
- return;
- }
- strcpy( buf, pwent->pw_dir );
- if ( *t != '\0' ) {
- strcat( buf, "/" );
- strcat( buf, t );
- }
- strcpy( token, buf );
- }
- return;
-}
-#endif /* notdef */
* into proprietary software; there is no requirement for such software to
* contain a copyright notice related to this source.
*
- * $Id: hash.c,v 1.4 2009-11-19 10:37:43 franklahm Exp $
* $Name: $
*/
#define NDEBUG
#include "hash.h"
#ifdef KAZLIB_RCSID
-static const char rcsid[] = "$Id: hash.c,v 1.4 2009-11-19 10:37:43 franklahm Exp $";
#endif
#define INIT_BITS 6
static hnode_t *hnode_alloc(void *context);
static void hnode_free(hnode_t *node, void *context);
static hash_val_t hash_fun_default(const void *key);
-static hash_val_t hash_fun2(const void *key);
static int hash_comp_default(const void *key1, const void *key2);
int hash_val_t_bit;
+(uint32_t)(((const uint8_t *)(d))[0]) )
#endif
+static int hash_comp_default(const void *key1, const void *key2)
+{
+ return strcmp(key1, key2);
+}
+
+#ifdef KAZLIB_TEST_MAIN
+
static hash_val_t hash_fun2(const void *key)
{
int len, rem;
return hash;
}
-static int hash_comp_default(const void *key1, const void *key2)
-{
- return strcmp(key1, key2);
-}
-
-#ifdef KAZLIB_TEST_MAIN
-
#include <stdio.h>
#include <ctype.h>
#include <stdarg.h>
* into proprietary software; there is no requirement for such software to
* contain a copyright notice related to this source.
*
- * $Id: hash.h,v 1.2 2009-10-02 09:32:40 franklahm Exp $
* $Name: $
*/
int main(int ac, char **av)
{
- fd_set rfds;
- void *ipc;
struct sigaction sv;
sigset_t sigs;
int ret;
afp_exit(EXITERR_SYS);
}
#endif
+
+ sv.sa_handler = SIG_IGN;
+ sigemptyset( &sv.sa_mask );
+ if (sigaction(SIGPIPE, &sv, NULL ) < 0 ) {
+ LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) );
+ afp_exit(EXITERR_SYS);
+ }
sv.sa_handler = afp_goaway; /* handler for all sigs */
if (reloadconfig) {
nologin++;
- auth_unload();
+
fd_reset_listening_sockets(&obj);
LOG(log_info, logtype_afpd, "re-reading configuration file");
configfree(&obj, NULL);
+ afp_config_free(&obj);
+
+ if (afp_config_parse(&obj, "afpd") != 0)
+ afp_exit(EXITERR_CONF);
+
if (configinit(&obj) != 0) {
LOG(log_error, logtype_afpd, "config re-read: no servers configured");
afp_exit(EXITERR_CONF);
switch (polldata[i].fdtype) {
case LISTEN_FD:
- if (child = dsi_start(&obj, (DSI *)polldata[i].data, server_children)) {
+ if ((child = dsi_start(&obj, (DSI *)polldata[i].data, server_children))) {
/* Add IPC fd to select fd set */
fdset_add_fd(obj.options.connections + AFP_LISTENERS + FDSET_SAFETY,
&fdset,
/*
- * $Id: mangle.h,v 1.7 2009-10-13 22:55:37 didg Exp $
*
*/
/*
- * $Id: nfsquota.c,v 1.13 2009-10-13 22:55:37 didg Exp $
*
* parts of this are lifted from the bsd quota program and are
* therefore under the following copyright:
}
/* -------------------------- */
-int of_stat(struct path *path)
+int of_stat(const struct vol *vol, struct path *path)
{
int ret;
path->st_errno = 0;
path->st_valid = 1;
- if ((ret = lstat(path->u_name, &path->st)) < 0) {
+ if ((ret = ostat(path->u_name, &path->st, vol_syml_opt(vol))) < 0) {
LOG(log_debug, logtype_afpd, "of_stat('%s/%s': %s)",
cfrombstr(curdir->d_fullpath), path->u_name, strerror(errno));
path->st_errno = errno;
if (*path->m_name) {
/* not curdir */
- return of_stat (path);
+ return of_stat(vol, path);
}
path->st_errno = 0;
path->st_valid = 1;
LOG(log_debug, logtype_afpd, "of_statdir: stating: '%s'", pathname);
- if (!(ret = lstat(pathname, &path->st)))
+ if (!(ret = ostat(pathname, &path->st, vol_syml_opt(vol))))
return 0;
path->st_errno = errno;
return -1;
path->st_errno = 0;
- if ((ret = lstat(cfrombstr(path->d_dir->d_u_name), &path->st)) < 0)
+ if ((ret = ostat(cfrombstr(path->d_dir->d_u_name), &path->st, vol_syml_opt(vol))) < 0)
path->st_errno = errno;
}
}
/* -------------------------- */
-struct ofork *of_findname(struct path *path)
+struct ofork *of_findname(const struct vol *vol, struct path *path)
{
struct ofork *of;
struct file_key key;
if (!path->st_valid) {
- of_stat(path);
+ of_stat(vol, path);
}
if (path->st_errno)
/* Somone has used write_fork, we assume file was changed, register it to file change event api */
if (ofork->of_flags & AFPFORK_MODIFIED) {
- fce_register_file_modification(ofork);
+ 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);
}
ad_unlock(ofork->of_ad, ofork->of_refnum, ofork->of_flags & AFPFORK_ERROR ? 0 : 1);
struct ofork *of;
struct adouble *adp;
- if ((of = of_findname(path))) {
+ if ((of = of_findname(vol, path))) {
adp = of->of_ad;
} else {
ad_init(ad, vol);
/*
- * $Id: quota.c,v 1.35 2010-04-03 07:11:35 franklahm Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
#include <atalk/afp.h>
#include <atalk/compat.h>
#include <atalk/unix.h>
+#include <atalk/util.h>
#include "auth.h"
#include "volume.h"
dev_t devno;
static struct mnttab mnt;
- if ( lstat( file, &sb ) < 0 ) {
+ if (stat(file, &sb) < 0) {
return( NULL );
}
devno = sb.st_dev;
while ( getmntent( mtab, &mnt ) == 0 ) {
/* local fs */
- if ( (lstat( mnt.mnt_special, &sb ) == 0) && (devno == sb.st_rdev)) {
+ if ( (stat( mnt.mnt_special, &sb ) == 0) && (devno == sb.st_rdev)) {
fclose( mtab );
return mnt.mnt_mountp;
}
/* check for nfs. we probably should use
* strcmp(mnt.mnt_fstype, MNTTYPE_NFS), but that's not as fast. */
- if ((lstat(mnt.mnt_mountp, &sb) == 0) && (devno == sb.st_dev) &&
+ if ((stat(mnt.mnt_mountp, &sb) == 0) && (devno == sb.st_dev) &&
strchr(mnt.mnt_special, ':')) {
*nfs = 1;
fclose( mtab );
struct mntent *mnt;
int found=0;
- if ( lstat( file, &sb ) < 0 ) {
+ if (stat(file, &sb) < 0 ) {
return( NULL );
}
devno = sb.st_dev;
while (( mnt = getmntent( mtab )) != NULL ) {
/* check for local fs */
- if ( (lstat( mnt->mnt_fsname, &sb ) == 0) && devno == sb.st_rdev) {
+ if ( (stat( mnt->mnt_fsname, &sb ) == 0) && devno == sb.st_rdev) {
found = 1;
break;
}
/* check for an nfs mount entry. the alternative is to use
* strcmp(mnt->mnt_type, MNTTYPE_NFS) instead of the strchr. */
- if ((lstat(mnt->mnt_dir, &sb) == 0) && (devno == sb.st_dev) &&
+ if ((stat(mnt->mnt_dir, &sb) == 0) && (devno == sb.st_dev) &&
strchr(mnt->mnt_fsname, ':')) {
*nfs = 1;
found = 1;
static int status_server(char *data, const char *server, const struct afp_options *options)
{
char *start = data;
- char *Obj, *Type, *Zone;
+ char *Obj;
char buf[32];
uint16_t status;
size_t len;
data += offset;
char *DirectoryNamesCount = data++;
- char *DirectoryNames = data;
size_t size = sizeof(uint8_t);
*DirectoryNamesCount = 0;
}
krb5_unparse_name(context, entry.principal, &principal);
+#ifdef HAVE_KRB5_FREE_KEYTAB_ENTRY_CONTENTS
+ krb5_free_keytab_entry_contents(context, &entry);
+#elif defined(HAVE_KRB5_KT_FREE_ENTRY)
krb5_kt_free_entry(context, &entry);
-
+#endif
append_directoryname(&data,
offset,
&size,
uint16_t namelen;
size_t len;
char *begin = data;
- uint16_t offset, status;
+ uint16_t offset;
memcpy(&offset, data + *nameoffset, sizeof(offset));
offset = ntohs(offset);
char *servername_conf;
int header = 0;
char buf[1024], *p;
- FILE *fp = NULL, *randomp;
+ FILE *fp = NULL;
size_t len;
char *server_tmp;
/*
- * $Id: switch.h,v 1.4 2009-10-15 10:43:13 didg Exp $
*
* Copyright (c) 1990,1991 Regents of The University of Michigan.
* All Rights Reserved.
/*
- * $Id: uam.c,v 1.35 2009-11-08 01:15:31 didg Exp $
*
* Copyright (c) 1999 Adrian Sun (asun@zoology.washington.edu)
* All Rights Reserved. See COPYRIGHT.
#include <atalk/util.h>
#include <atalk/globals.h>
#include <atalk/volume.h>
+#include <atalk/bstrlib.h>
#include "afp_config.h"
#include "auth.h"
return pwent;
/* if we have a NT domain name try with it */
- if (obj->options.ntdomain && obj->options.ntseparator) {
+ if (obj->options.addomain || (obj->options.ntdomain && obj->options.ntseparator)) {
/* FIXME What about charset ? */
- size_t ulen = strlen(obj->options.ntdomain) + strlen(obj->options.ntseparator) + strlen(name);
- if ((p = malloc(ulen +1))) {
- strcpy(p, obj->options.ntdomain);
- strcat(p, obj->options.ntseparator);
- strcat(p, name);
- pwent = getpwnam(p);
- free(p);
- if (pwent) {
- int len = strlen(pwent->pw_name);
- if (len < MAXUSERLEN) {
- strncpy(name,pwent->pw_name, MAXUSERLEN);
- }else{
- LOG(log_error, logtype_uams, "MAJOR:The name %s is longer than %d",pwent->pw_name,MAXUSERLEN);
- }
-
- return pwent;
+ bstring princ;
+ if (obj->options.addomain)
+ princ = bformat("%s@%s", name, obj->options.addomain);
+ else
+ princ = bformat("%s%s%s", obj->options.ntdomain, obj->options.ntseparator, name);
+ pwent = getpwnam(bdata(princ));
+ bdestroy(princ);
+
+ if (pwent) {
+ int len = strlen(pwent->pw_name);
+ if (len < MAXUSERLEN) {
+ strncpy(name,pwent->pw_name, MAXUSERLEN);
+ } else {
+ LOG(log_error, logtype_uams, "The name '%s' is longer than %d", pwent->pw_name, MAXUSERLEN);
}
+ return pwent;
}
}
#ifndef NO_REAL_USER_NAME
/*
- * $Id: uid.c,v 1.14 2005-04-28 20:49:45 bfernhomberg Exp $
* code: jeff@univrel.pr.uconn.edu
*
* These functions are abstracted here, so that all calls for resolving
/*
- * $Id: uid.h,v 1.6 2002-08-30 19:32:41 didg Exp $
* code: jeff@univrel.pr.uconn.edu
*/
ma->ma_user = ma->ma_owner = ma->ma_world = ma->ma_group = 0;
if (!st) {
- if (lstat(path, &sb) != 0)
+ if (ostat(path, &sb, vol_syml_opt(vol)) != 0)
return;
st = &sb;
}
int setfilunixmode (const struct vol *vol, struct path* path, mode_t mode)
{
if (!path->st_valid) {
- of_stat(path);
+ of_stat(vol, path);
}
if (path->st_errno) {
mode |= vol->v_fperm;
- if (setfilmode( path->u_name, mode, &path->st, vol->v_umask) < 0)
+ if (setfilmode(vol, path->u_name, mode, &path->st) < 0)
return -1;
/* we need to set write perm if read set for resource fork */
return vol->vfs->vfs_setfilmode(vol, path->u_name, mode, &path->st);
/* --------------------- */
-int setdirunixmode(const struct vol *vol, const char *name, mode_t mode)
+int setdirunixmode(const struct vol *vol, char *name, mode_t mode)
{
LOG(log_debug, logtype_afpd, "setdirunixmode('%s', mode:%04o) {v_dperm:%04o}",
fullpathname(name), mode, vol->v_dperm);
/* ----------------------------- */
int setfilowner(const struct vol *vol, const uid_t uid, const gid_t gid, struct path* path)
{
- if (lchown(path->u_name, uid, gid) < 0 && errno != EPERM) {
+ if (ochown( path->u_name, uid, gid, vol_syml_opt(vol)) < 0 && errno != EPERM ) {
LOG(log_debug, logtype_afpd, "setfilowner: chown %d/%d %s: %s",
uid, gid, path->u_name, strerror(errno));
return -1;
* co-opting some bits. */
int setdirowner(const struct vol *vol, const char *name, const uid_t uid, const gid_t gid)
{
- if (lchown(name, uid, gid ) < 0 && errno != EPERM ) {
+ if (ochown(name, uid, gid, vol_syml_opt(vol)) < 0 && errno != EPERM ) {
LOG(log_debug, logtype_afpd, "setdirowner: chown %d/%d %s: %s",
uid, gid, fullpathname(name), strerror(errno) );
}
return( 0 );
}
-
extern struct afp_options default_options;
-extern int setdirunixmode (const struct vol *, const char *, mode_t);
+extern int setdirunixmode (const struct vol *, char *, mode_t);
extern int setdirmode (const struct vol *, const char *, mode_t);
extern int setdirowner (const struct vol *, const char *, const uid_t, const gid_t);
extern int setfilunixmode (const struct vol *, struct path*, const mode_t);
DIR *dir = NULL;
const struct dirent *entry;
const char *p;
- struct stat st;
long int links;
time_t now = time(NULL);
{
int spaceflag, rc;
uint32_t maxsize;
- VolSpace used;
#ifndef NO_QUOTA_SUPPORT
VolSpace qfree, qtotal;
#endif
return( AFP_OK );
}
-#define FCE_TM_DELTA 10 /* send notification every 10 seconds */
-void vol_fce_tm_event(void)
-{
- static time_t last;
- time_t now = time(NULL);
- struct vol *vol = getvolumes();
-
- if ((last + FCE_TM_DELTA) < now) {
- last = now;
- for ( ; vol; vol = vol->v_next ) {
- if (vol->v_flags & AFPVOL_TM)
- (void)fce_register_tm_size(vol->v_path, vol->v_tm_used + vol->v_appended);
- }
- }
-}
-
/* -----------------------
* set volume creation date
* avoid duplicate, well at least it tries
int vcnt;
size_t len;
- load_volumes(obj, closevol);
+ load_volumes(obj);
data = rbuf + 5;
for ( vcnt = 0, volume = getvolumes(); volume; volume = volume->v_next ) {
{
struct stat st;
char *volname;
- char *p;
struct vol *volume;
struct dir *dir;
int len, ret;
size_t namelen;
uint16_t bitmap;
- char path[ MAXPATHLEN + 1];
char *vol_uname;
char *vol_mname;
char *volname_tmp;
if ((len + 1) & 1) /* pad to an even boundary */
ibuf++;
- load_volumes(obj, closevol);
+ load_volumes(obj);
for ( volume = getvolumes(); volume; volume = volume->v_next ) {
if ( strcasecmp_w( (ucs2_t*) volname, volume->v_name ) == 0 ) {
return AFPERR_PARAM;
}
- if ( NULL == getcwd(path, MAXPATHLEN)) {
- /* shouldn't be fatal but it will fail later */
- LOG(log_error, logtype_afpd, "afp_openvol(%s): volume pathlen too long", volume->v_path);
- return AFPERR_MISC;
- }
-
- /* Normalize volume path */
-#ifdef REALPATH_TAKES_NULL
- if ((volume->v_path = realpath(path, NULL)) == NULL)
- return AFPERR_MISC;
-#else
- if ((volume->v_path = malloc(MAXPATHLEN+1)) == NULL)
- return AFPERR_MISC;
- if (realpath(path, volume->v_path) == NULL) {
- free(volume->v_path);
- return AFPERR_MISC;
- }
- /* Safe some memory */
- char *tmp;
- if ((tmp = strdup(volume->v_path)) == NULL) {
- free(volume->v_path);
- return AFPERR_MISC;
- }
- free(volume->v_path);
- volume->v_path = tmp;
-#endif
-
if (volume_codepage(obj, volume) < 0) {
ret = AFPERR_MISC;
goto openvol_err;
goto openvol_err;
}
- if ((vol_uname = strrchr(path, '/')) == NULL)
- vol_uname = path;
- else if (*(vol_uname + 1) != '\0')
+ if ((vol_uname = strrchr(volume->v_path, '/')) == NULL)
+ vol_uname = volume->v_path;
+ else if (vol_uname[1] != '\0')
vol_uname++;
if ((dir = dir_new(vol_mname,
uint32_t *);
extern void setvoltime (AFPObj *, struct vol *);
extern int pollvoltime (AFPObj *);
-extern void vol_fce_tm_event(void);
/* FP functions */
int afp_openvol (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen);
#include <errno.h>
#include <atalk/logger.h>
-#include <atalk/cnid_dbd_private.h>
#include <atalk/globals.h>
#include <atalk/netatalk_conf.h>
#include <atalk/util.h>
+#include <atalk/errchk.h>
#include "cmd_dbd.h"
-#include "dbd.h"
-#include "dbif.h"
-#include "db_param.h"
-#include "pack.h"
-#define DBOPTIONS (DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN)
+enum dbd_cmd {dbd_scan, dbd_rebuild};
-int nocniddb = 0; /* Dont open CNID database, only scan filesystem */
+/* Global variables */
volatile sig_atomic_t alarmed; /* flags for signals */
-int db_locked; /* have we got the fcntl lock on lockfile ? */
-
-static DBD *dbd;
-static int verbose; /* Logging flag */
-static int exclusive; /* Exclusive volume access */
-static struct db_param db_param = {
- NULL, /* Volume dirpath */
- 1, /* bdb logfile autoremove */
- 64 * 1024, /* bdb cachesize (64 MB) */
- DEFAULT_MAXLOCKS, /* maxlocks */
- DEFAULT_MAXLOCKOBJS, /* maxlockobjs */
- 0, /* flush_interval */
- 0, /* flush_frequency */
- 0, /* usock_file */
- -1, /* fd_table_size */
- -1, /* idle_timeout */
- -1 /* max_vols */
-};
-static char dbpath[MAXPATHLEN+1]; /* Path to the dbd database */
-/*
- Provide some logging
- */
-void dbd_log(enum logtype lt, char *fmt, ...)
-{
- int len;
- static char logbuffer[1024];
- va_list args;
+/* Local variables */
+static dbd_flags_t flags;
- if ( (lt == LOGSTD) || (verbose == 1)) {
- va_start(args, fmt);
- len = vsnprintf(logbuffer, 1023, fmt, args);
- va_end(args);
- logbuffer[1023] = 0;
+/***************************************************************************
+ * Local functions
+ ***************************************************************************/
- printf("%s\n", logbuffer);
- }
-}
-
-/*
- SIGNAL handling:
- catch SIGINT and SIGTERM which cause clean exit. Ignore anything else.
+/*
+ * SIGNAL handling:
+ * catch SIGINT and SIGTERM which cause clean exit. Ignore anything else.
*/
-
static void sig_handler(int signo)
{
alarmed = 1;
static void usage (void)
{
- printf("dbd (Netatalk %s)\n"
- "Usage: dbd [-CeFtvx] -d [-i] | -s [-c|-n]| -r [-c|-f] | -u <path to netatalk volume>\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"
- " 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"
- " Options: -c Don't create .AppleDouble stuff, only cleanup orphaned.\n"
- " -f wipe database and rebuild from IDs stored in AppleDouble\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"
+ printf("Usage: dbd [-cfFstvV] <path to netatalk volume>\n\n"
+ "dbd scans all file and directories of AFP volumes, updating the\n"
+ "CNID database of the volume. dbd must be run with appropiate\n"
+ "permissions i.e. as root.\n\n"
+ "Options:\n"
+ " -s scan volume: treat the volume as read only and don't\n"
+ " perform any filesystem modifications\n"
+ " -c convert from adouble:v2 to adouble:ea\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"
+ " -f delete and recreate CNID database\n"
" -t show statistics while running\n"
- " -v verbose\n\n"
- , VERSION
+ " -v verbose\n"
+ " -V show version info\n\n"
);
}
-int main(int argc, char **argv)
+/***************************************************************************
+ * Global functions
+ ***************************************************************************/
+
+void dbd_log(enum logtype lt, char *fmt, ...)
{
- int c, lockfd, ret = -1;
- int dump=0, scan=0, rebuild=0, prep_upgrade=0, rebuildindexes=0, dumpindexes=0, force=0;
- dbd_flags_t flags = 0;
- char *volpath;
- int cdir;
- AFPObj obj = { 0 };
- struct vol *vol;
+ int len;
+ static char logbuffer[1024];
+ va_list args;
- if (geteuid() != 0) {
- usage();
- exit(EXIT_FAILURE);
+ if ( (lt == LOGSTD) || (flags & DBD_FLAGS_VERBOSE)) {
+ va_start(args, fmt);
+ len = vsnprintf(logbuffer, 1023, fmt, args);
+ va_end(args);
+ logbuffer[1023] = 0;
+
+ printf("%s\n", logbuffer);
}
- /* Inhereting perms in ad_mkdir etc requires this */
- ad_setfuid(0);
+}
- while ((c = getopt(argc, argv, ":cCdefFinrstuvx")) != -1) {
+int main(int argc, char **argv)
+{
+ EC_INIT;
+ int dbd_cmd = dbd_rebuild;
+ int cdir = -1;
+ AFPObj obj = { 0 };
+ struct vol *vol = NULL;
+ const char *volpath = NULL;
+
+ int c;
+ while ((c = getopt(argc, argv, ":cfF:rstvV")) != -1) {
switch(c) {
case 'c':
- flags |= DBD_FLAGS_CLEANUP;
- break;
- case 'C':
flags |= DBD_FLAGS_V2TOEA;
break;
- case 'd':
- dump = 1;
+ case 'f':
+ flags |= DBD_FLAGS_FORCE;
+ break;
+ case 'F':
+ obj.cmdlineconfigfile = strdup(optarg);
break;
- case 'i':
- dumpindexes = 1;
+ case 'r':
+ /* the default */
break;
case 's':
- scan = 1;
+ dbd_cmd = dbd_scan;
flags |= DBD_FLAGS_SCAN;
break;
- case 'n':
- nocniddb = 1; /* FIXME: this could/should be a flag too for consistency */
- break;
- case 'r':
- rebuild = 1;
- break;
case 't':
flags |= DBD_FLAGS_STATS;
break;
- case 'u':
- prep_upgrade = 1;
- break;
case 'v':
- verbose = 1;
- break;
- case 'e':
- exclusive = 1;
- flags |= DBD_FLAGS_EXCL;
- break;
- case 'x':
- rebuildindexes = 1;
- break;
- case 'f':
- force = 1;
- exclusive = 1;
- flags |= DBD_FLAGS_FORCE | DBD_FLAGS_EXCL;
- break;
- case 'F':
- obj.cmdlineconfigfile = strdup(optarg);
+ flags |= DBD_FLAGS_VERBOSE;
break;
+ case 'V':
+ printf("dbd %s\n", VERSION);
+ exit(0);
case ':':
case '?':
usage();
}
}
- if ((dump + scan + rebuild + prep_upgrade) != 1) {
+ if ( (optind + 1) != argc ) {
usage();
exit(EXIT_FAILURE);
}
+ volpath = argv[optind];
- if ( (optind + 1) != argc ) {
+ if (geteuid() != 0) {
usage();
exit(EXIT_FAILURE);
}
- volpath = argv[optind];
+ /* Inhereting perms in ad_mkdir etc requires this */
+ ad_setfuid(0);
setvbuf(stdout, (char *) NULL, _IONBF, 0);
exit(EXIT_FAILURE);
}
+ /* Initialize CNID subsystem */
+ cnid_init();
+
/* Setup logging. Should be portable among *NIXes */
- if (!verbose)
- setuplog("default:info", "/dev/tty");
+ if (flags & DBD_FLAGS_VERBOSE)
+ setuplog("default:note, cnid:debug", "/dev/tty");
else
- setuplog("default:debug", "/dev/tty");
+ setuplog("default:note", "/dev/tty");
- if (load_volumes(&obj, NULL) != 0) {
+ if (load_volumes(&obj) != 0) {
dbd_log( LOGSTD, "Couldn't load volumes");
exit(EXIT_FAILURE);
}
exit(EXIT_FAILURE);
}
- pack_setvol(vol);
+ /* open volume */
+ if (STRCMP(vol->v_cnidscheme, != , "dbd")) {
+ dbd_log(LOGSTD, "\"%s\" isn't a \"dbd\" CNID volume", vol->v_path);
+ exit(EXIT_FAILURE);
+ }
+ if ((vol->v_cdb = cnid_open(vol->v_path,
+ 0000,
+ "dbd",
+ vol->v_flags & AFPVOL_NODEV ? CNID_FLAG_NODEV : 0,
+ vol->v_cnidserver,
+ vol->v_cnidport)) == NULL) {
+ dbd_log(LOGSTD, "Cant initialize CNID database connection for %s", vol->v_path);
+ exit(EXIT_FAILURE);
+ }
if (vol->v_adouble == AD_VERSION_EA)
dbd_log( LOGDEBUG, "adouble:ea volume");
exit(EXIT_FAILURE);
}
- /* Enuser dbpath is there, create if necessary */
- struct stat st;
- if (stat(vol->v_dbpath, &st) != 0) {
- if (errno != ENOENT) {
- dbd_log( LOGSTD, "Can't stat dbpath \"%s\": %s", vol->v_dbpath, strerror(errno));
- exit(EXIT_FAILURE);
- }
- if ((mkdir(vol->v_dbpath, 0755)) != 0) {
- dbd_log( LOGSTD, "Can't create dbpath \"%s\": %s", vol->v_dbpath, strerror(errno));
- exit(EXIT_FAILURE);
- }
- }
-
- /* Put "/.AppleDB" at end of volpath, get path from volinfo file */
- if ( (strlen(vol->v_dbpath) + strlen("/.AppleDB")) > MAXPATHLEN ) {
- dbd_log( LOGSTD, "Volume pathname too long");
- exit(EXIT_FAILURE);
- }
- strncpy(dbpath, vol->v_dbpath, MAXPATHLEN - strlen("/.AppleDB"));
- strcat(dbpath, "/.AppleDB");
-
- /* Check or create dbpath */
- int dbdirfd = open(dbpath, O_RDONLY);
- if (dbdirfd == -1 && errno == ENOENT) {
- if (errno == ENOENT) {
- if ((mkdir(dbpath, 0755)) != 0) {
- dbd_log( LOGSTD, "Can't create .AppleDB for \"%s\": %s", dbpath, strerror(errno));
- exit(EXIT_FAILURE);
- }
- } else {
- dbd_log( LOGSTD, "Somethings wrong with .AppleDB for \"%s\", giving up: %s", dbpath, strerror(errno));
- exit(EXIT_FAILURE);
- }
- } else {
- close(dbdirfd);
- }
-
- /* Get db lock */
- if ((db_locked = get_lock(LOCK_EXCL, dbpath)) == -1)
- goto exit_noenv;
- if (db_locked != LOCK_EXCL) {
- dbd_log(LOGDEBUG, "Database is in use, acquiring shared lock");
- /* Couldn't get exclusive lock, try shared lock if -e wasn't requested */
- if (exclusive) {
- dbd_log(LOGSTD, "Database is in use and exlusive was requested");
- goto exit_noenv;
+ if (flags & DBD_FLAGS_FORCE) {
+ if (cnid_wipe(vol->v_cdb) != 0) {
+ dbd_log( LOGSTD, "Failed to wipe CNID db");
+ EC_FAIL;
}
- if ((db_locked = get_lock(LOCK_SHRD, NULL)) != LOCK_SHRD)
- goto exit_noenv;
- }
-
- /* Check if -f is requested and wipe db if yes */
- if ((flags & DBD_FLAGS_FORCE) && rebuild) {
- char cmd[8 + MAXPATHLEN];
- if ((db_locked = get_lock(LOCK_FREE, NULL)) != 0)
- goto exit_noenv;
-
- snprintf(cmd, 8 + MAXPATHLEN, "rm -rf \"%s\"", dbpath);
- dbd_log( LOGDEBUG, "Removing old database of volume: '%s'", volpath);
- system(cmd);
- if ((mkdir(dbpath, 0755)) != 0) {
- dbd_log( LOGSTD, "Can't create dbpath \"%s\": %s", dbpath, strerror(errno));
- exit(EXIT_FAILURE);
- }
- dbd_log( LOGDEBUG, "Removed old database.");
- if ((db_locked = get_lock(LOCK_EXCL, dbpath)) == -1)
- goto exit_noenv;
- }
-
- /*
- Lets start with the BerkeleyDB stuff
- */
- if ( ! nocniddb) {
- if ((dbd = dbif_init(dbpath, "cnid2.db")) == NULL)
- goto exit_noenv;
-
- if (dbif_env_open(dbd,
- &db_param,
- (db_locked == LOCK_EXCL) ? (DBOPTIONS | DB_RECOVER) : DBOPTIONS) < 0) {
- dbd_log( LOGSTD, "error opening database!");
- goto exit_noenv;
- }
-
- if (db_locked == LOCK_EXCL)
- dbd_log( LOGDEBUG, "Finished recovery.");
-
- if (dbif_open(dbd, NULL, rebuildindexes) < 0) {
- dbif_close(dbd);
- goto exit_failure;
- }
-
- /* Prepare upgrade ? We're done */
- if (prep_upgrade) {
- (void)dbif_txn_close(dbd, 1);
- goto cleanup;
- }
- }
-
- /* Downgrade db lock if not running exclusive */
- if (!exclusive && (db_locked == LOCK_EXCL)) {
- if (get_lock(LOCK_UNLOCK, NULL) != 0)
- goto exit_failure;
- if (get_lock(LOCK_SHRD, NULL) != LOCK_SHRD)
- goto exit_failure;
}
/* Now execute given command scan|rebuild|dump */
- if (dump && ! nocniddb) {
- if (dbif_dump(dbd, dumpindexes) < 0) {
- dbd_log( LOGSTD, "Error dumping database");
- }
- } else if ((rebuild && ! nocniddb) || scan) {
- if (cmd_dbd_scanvol(dbd, vol, flags) < 0) {
+ switch (dbd_cmd) {
+ case dbd_scan:
+ case dbd_rebuild:
+ if (cmd_dbd_scanvol(vol, flags) < 0) {
dbd_log( LOGSTD, "Error repairing database.");
}
+ break;
}
-cleanup:
- /* Cleanup */
- dbd_log(LOGDEBUG, "Closing db");
- if (! nocniddb) {
- if (dbif_close(dbd) < 0) {
- dbd_log( LOGSTD, "Error closing database");
- goto exit_failure;
- }
- }
-
-exit_success:
- ret = 0;
-
-exit_failure:
- if (dbif_env_remove(dbpath) < 0) {
- dbd_log( LOGSTD, "Error removing BerkeleyDB database environment");
- ret++;
- }
- get_lock(0, NULL);
+EC_CLEANUP:
+ if (vol)
+ cnid_close(vol->v_cdb);
-exit_noenv:
- if ((fchdir(cdir)) < 0)
+ if (cdir != -1 && (fchdir(cdir) < 0))
dbd_log(LOGSTD, "fchdir: %s", strerror(errno));
if (ret == 0)
#define DBD_FLAGS_SCAN (1 << 0)
#define DBD_FLAGS_FORCE (1 << 1)
-#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 DBD_FLAGS_STATS (1 << 2)
+#define DBD_FLAGS_V2TOEA (1 << 3) /* Convert adouble:v2 to adouble:ea */
+#define DBD_FLAGS_VERBOSE (1 << 4)
#define ADv2_DIRNAME ".AppleDouble"
#define DIR_DOT_OR_DOTDOT(a) \
((strcmp(a, ".") == 0) || (strcmp(a, "..") == 0))
-#define STRCMP(a,b,c) \
- (strcmp(a,c) b 0)
-
-extern int nocniddb; /* Dont open CNID database, only scan filesystem */
-extern int db_locked; /* have we got the fcntl lock on lockfd ? */
extern volatile sig_atomic_t alarmed;
extern void dbd_log(enum logtype lt, char *fmt, ...);
-extern int cmd_dbd_scanvol(DBD *dbd, struct vol *vol, dbd_flags_t flags);
+extern int cmd_dbd_scanvol(struct vol *vol, dbd_flags_t flags);
-/*
- Functions for querying the database which couldn't be reused from the existing
- funcs pool of dbd_* for one reason or another
-*/
-extern int cmd_dbd_add(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply);
#endif /* CMD_DBD_H */
#include <atalk/adouble.h>
#include <atalk/unicode.h>
#include <atalk/netatalk_conf.h>
-#include <atalk/cnid_dbd_private.h>
#include <atalk/volume.h>
#include <atalk/ea.h>
#include <atalk/util.h>
#include <atalk/acl.h>
#include <atalk/compat.h>
+#include <atalk/cnid.h>
+#include <atalk/errchk.h>
#include "cmd_dbd.h"
#include "dbif.h"
#define ADFILE_OK (adfile_ok == 0)
-static struct vol *myvol;
static char cwdbuf[MAXPATHLEN+1];
-static DBD *dbd;
-static DBD *dbd_rebuild;
+static struct vol *vol;
static dbd_flags_t dbd_flags;
static char stamp[CNID_DEV_LEN];
static char *netatalk_dirs[] = {
u = upath;
outlen = strlen(upath);
- if ((myvol->v_casefold & AFPVOL_UTOMUPPER))
+ if ((vol->v_casefold & AFPVOL_UTOMUPPER))
flags |= CONV_TOUPPER;
- else if ((myvol->v_casefold & AFPVOL_UTOMLOWER))
+ else if ((vol->v_casefold & AFPVOL_UTOMLOWER))
flags |= CONV_TOLOWER;
- if ((myvol->v_flags & AFPVOL_EILSEQ)) {
+ if ((vol->v_flags & AFPVOL_EILSEQ)) {
flags |= CONV__EILSEQ;
}
/* convert charsets */
- if ((size_t)-1 == ( outlen = convert_charset(myvol->v_volcharset,
+ if ((size_t)-1 == ( outlen = convert_charset(vol->v_volcharset,
CH_UTF8_MAC,
- myvol->v_maccharset,
+ vol->v_maccharset,
u, outlen, mpath, MAXPATHLEN, &flags)) ) {
dbd_log( LOGSTD, "Conversion from %s to %s for %s failed.",
- myvol->v_volcodepage, myvol->v_maccodepage, u);
+ vol->v_volcodepage, vol->v_maccodepage, u);
return NULL;
}
return(m);
}
-/*
- Taken form afpd/desktop.c
-*/
-static char *mtoupath(char *mpath)
-{
- static char upath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
- char *m, *u;
- size_t inplen;
- size_t outlen;
- u_int16_t flags = 0;
-
- if (!mpath)
- return NULL;
-
- if ( *mpath == '\0' ) {
- return( "." );
- }
-
- /* set conversion flags */
- if ((myvol->v_casefold & AFPVOL_MTOUUPPER))
- flags |= CONV_TOUPPER;
- else if ((myvol->v_casefold & AFPVOL_MTOULOWER))
- flags |= CONV_TOLOWER;
-
- if ((myvol->v_flags & AFPVOL_EILSEQ)) {
- flags |= CONV__EILSEQ;
- }
-
- m = mpath;
- u = upath;
-
- inplen = strlen(m);
- outlen = MAXPATHLEN;
-
- if ((size_t)-1 == (outlen = convert_charset(CH_UTF8_MAC,
- myvol->v_volcharset,
- myvol->v_maccharset,
- m, inplen, u, outlen, &flags)) ) {
- dbd_log( LOGSTD, "conversion from UTF8-MAC to %s for %s failed.",
- myvol->v_volcodepage, mpath);
- return NULL;
- }
-
- return( upath );
-}
-
/*
Check for netatalk special folders e.g. ".AppleDB" or ".AppleDesktop"
Returns pointer to name or NULL.
*/
static int update_cnid(cnid_t did, const struct stat *sp, const char *oldname, const char *newname)
{
- int ret;
cnid_t id;
- /* Prepare request data */
- memset(&rqst, 0, sizeof(struct cnid_dbd_rqst));
- memset(&rply, 0, sizeof(struct cnid_dbd_rply));
- rqst.did = did;
- rqst.cnid = 0;
- if ( ! (myvol->v_flags & AFPVOL_NODEV))
- rqst.dev = sp->st_dev;
- rqst.ino = sp->st_ino;
- rqst.type = S_ISDIR(sp->st_mode) ? 1 : 0;
- rqst.name = (char *)oldname;
- rqst.namelen = strlen(oldname);
-
/* Query the database */
- ret = dbd_lookup(dbd, &rqst, &rply, (dbd_flags & DBD_FLAGS_SCAN) ? 1 : 0);
- if (dbif_txn_close(dbd, ret) != 0)
- return -1;
- if (rply.result != CNID_DBD_RES_OK)
+ if ((id = cnid_lookup(vol->v_cdb, sp, did, (char *)oldname, strlen(oldname))) == CNID_INVALID)
+ /* not in db, no need to update */
return 0;
- id = rply.cnid;
-
- /* Prepare request data */
- memset(&rqst, 0, sizeof(struct cnid_dbd_rqst));
- memset(&rply, 0, sizeof(struct cnid_dbd_rply));
- rqst.did = did;
- rqst.cnid = id;
- if ( ! (myvol->v_flags & AFPVOL_NODEV))
- rqst.dev = sp->st_dev;
- rqst.ino = sp->st_ino;
- rqst.type = S_ISDIR(sp->st_mode) ? 1 : 0;
- rqst.name = (char *)newname;
- rqst.namelen = strlen(newname);
/* Update the database */
- ret = dbd_update(dbd, &rqst, &rply);
- if (dbif_txn_close(dbd, ret) != 0)
- return -1;
- if (rply.result != CNID_DBD_RES_OK)
+ if (cnid_update(vol->v_cdb, id, sp, did, (char *)newname, strlen(newname)) < 0)
return -1;
return 0;
*newname = NULL;
- if (myvol->v_adouble == AD_VERSION_EA) {
+ if (vol->v_adouble == AD_VERSION_EA) {
if (!(dbd_flags & DBD_FLAGS_V2TOEA))
return 0;
- if (ad_convert(fname, st, myvol, newname) != 0) {
+ if (ad_convert(fname, st, vol, newname) != 0) {
switch (errno) {
case ENOENT:
break;
return 0;
}
- if (dbd_flags & DBD_FLAGS_CLEANUP)
- return 0;
-
if (S_ISDIR(st->st_mode))
adflags |= ADFLAGS_DIR;
- adname = myvol->ad_path(fname, adflags);
+ adname = vol->ad_path(fname, adflags);
if ((ret = access( adname, F_OK)) != 0) {
if (errno != ENOENT) {
return -1;
/* Create ad file */
- ad_init(&ad, myvol);
+ ad_init(&ad, vol);
if ((ret = ad_open(&ad, fname, adflags | ADFLAGS_CREATE | ADFLAGS_RDWR, 0666)) != 0) {
dbd_log( LOGSTD, "Error creating AppleDouble file '%s/%s': %s",
chmod(adname, st->st_mode);
#endif
} else {
- ad_init(&ad, myvol);
+ ad_init(&ad, vol);
if (ad_open(&ad, fname, adflags | ADFLAGS_RDONLY) != 0) {
dbd_log( LOGSTD, "Error opening AppleDouble file for '%s/%s'", cwdbuf, fname);
return -1;
struct stat st;
char *eaname;
- if ((ret = ea_open(myvol, fname, EA_RDWR, &ea)) != 0) {
+ if ((ret = ea_open(vol, fname, EA_RDWR, &ea)) != 0) {
if (errno == ENOENT)
return 0;
dbd_log(LOGSTD, "Error calling ea_open for file: %s/%s, removing EA files", cwdbuf, fname);
struct adouble ad;
char *mname = NULL;
- if (dbd_flags & DBD_FLAGS_CLEANUP)
- return 0;
-
- if (myvol->v_adouble == AD_VERSION_EA)
+ if (vol->v_adouble == AD_VERSION_EA)
return 0;
/* Check for ad-dir */
}
/* Check for ".Parent" */
- if ( (adpar_ok = access(myvol->ad_path(".", ADFLAGS_DIR), F_OK)) != 0) {
+ if ( (adpar_ok = access(vol->ad_path(".", ADFLAGS_DIR), F_OK)) != 0) {
if (errno != ENOENT) {
dbd_log(LOGSTD, "Access error on '%s/%s': %s",
- cwdbuf, myvol->ad_path(".", ADFLAGS_DIR), strerror(errno));
+ cwdbuf, vol->ad_path(".", ADFLAGS_DIR), strerror(errno));
return -1;
}
dbd_log(LOGSTD, "Missing .AppleDouble/.Parent for '%s'", cwdbuf);
}
/* Create ad dir and set name */
- ad_init(&ad, myvol);
+ ad_init(&ad, vol);
if (ad_open(&ad, ".", ADFLAGS_HF | ADFLAGS_DIR | ADFLAGS_CREATE | ADFLAGS_RDWR, 0777) != 0) {
dbd_log( LOGSTD, "Error creating AppleDouble dir in %s: %s", cwdbuf, strerror(errno));
return -1;
}
chown(ADv2_DIRNAME, st.st_uid, st.st_gid);
- chown(myvol->ad_path(".", ADFLAGS_DIR), st.st_uid, st.st_gid);
+ chown(vol->ad_path(".", ADFLAGS_DIR), st.st_uid, st.st_gid);
}
return 0;
char *namep, *namedup = NULL;
/* Check if this is an AFPVOL_EA_AD vol */
- if (myvol->v_vfs_ea == AFPVOL_EA_AD) {
+ if (vol->v_vfs_ea == AFPVOL_EA_AD) {
/* Does the filename contain "::EA" ? */
namedup = strdup(name);
if ((namep = strstr(namedup, "::EA")) == NULL) {
struct stat st;
if ((chdir(ADv2_DIRNAME)) != 0) {
- if (myvol->v_adouble == AD_VERSION_EA) {
+ if (vol->v_adouble == AD_VERSION_EA) {
return 0;
}
dbd_log(LOGSTD, "Couldn't chdir to '%s/%s': %s",
*/
static cnid_t check_cnid(const char *name, cnid_t did, struct stat *st, int adfile_ok)
{
- int ret, adflags = ADFLAGS_HF;
+ int adflags = ADFLAGS_HF;
cnid_t db_cnid, ad_cnid;
struct adouble ad;
adflags = ADFLAGS_HF | (S_ISDIR(st->st_mode) ? ADFLAGS_DIR : 0);
- /* Force checkout every X items */
- static int cnidcount = 0;
- cnidcount++;
- if (cnidcount > 10000) {
- cnidcount = 0;
- if (dbif_txn_checkpoint(dbd, 0, 0, 0) < 0) {
- dbd_log(LOGSTD, "Error checkpointing!");
- return CNID_INVALID;
- }
- }
-
/* Get CNID from ad-file */
- ad_cnid = 0;
+ ad_cnid = CNID_INVALID;
if (ADFILE_OK) {
- ad_init(&ad, myvol);
+ ad_init(&ad, vol);
if (ad_open(&ad, name, adflags | ADFLAGS_RDWR) != 0) {
- if (dbd_flags & DBD_FLAGS_CLEANUP)
- return CNID_INVALID;
-
- if (myvol->v_adouble != AD_VERSION_EA) {
+ if (vol->v_adouble != AD_VERSION_EA) {
dbd_log( LOGSTD, "Error opening AppleDouble file for '%s/%s': %s", cwdbuf, name, strerror(errno));
return CNID_INVALID;
}
dbd_log( LOGDEBUG, "File without meta EA: \"%s/%s\"", cwdbuf, name);
adfile_ok = 1;
} else {
-
- if (dbd_flags & DBD_FLAGS_FORCE) {
- ad_cnid = ad_forcegetid(&ad);
- /* This ensures the changed stamp is written */
- ad_setid( &ad, st->st_dev, st->st_ino, ad_cnid, did, stamp);
- ad_flush(&ad);
- } else
- ad_cnid = ad_getid(&ad, st->st_dev, st->st_ino, 0, stamp);
-
- if (ad_cnid == 0)
+ ad_cnid = ad_getid(&ad, st->st_dev, st->st_ino, 0, stamp);
+ if (ad_cnid == CNID_INVALID)
dbd_log( LOGSTD, "Bad CNID in adouble file of '%s/%s'", cwdbuf, name);
else
dbd_log( LOGDEBUG, "CNID from .AppleDouble file for '%s/%s': %u", cwdbuf, name, ntohl(ad_cnid));
}
/* Get CNID from database */
-
- /* Prepare request data */
- memset(&rqst, 0, sizeof(struct cnid_dbd_rqst));
- memset(&rply, 0, sizeof(struct cnid_dbd_rply));
- rqst.did = did;
- rqst.cnid = ad_cnid;
- if ( ! (myvol->v_flags & AFPVOL_NODEV))
- rqst.dev = st->st_dev;
- rqst.ino = st->st_ino;
- rqst.type = S_ISDIR(st->st_mode)?1:0;
- rqst.name = (char *)name;
- rqst.namelen = strlen(name);
-
- /* Query the database */
- ret = dbd_lookup(dbd, &rqst, &rply, (dbd_flags & DBD_FLAGS_SCAN) ? 1 : 0);
- if (dbif_txn_close(dbd, ret) != 0)
+ if ((db_cnid = cnid_add(vol->v_cdb, st, did, (char *)name, strlen(name), ad_cnid)) == CNID_INVALID)
return CNID_INVALID;
- if (rply.result == CNID_DBD_RES_OK) {
- db_cnid = rply.cnid;
- } else if (rply.result == CNID_DBD_RES_NOTFOUND) {
- if ( ! (dbd_flags & DBD_FLAGS_FORCE))
- dbd_log( LOGSTD, "No CNID for '%s/%s' in database", cwdbuf, name);
- db_cnid = 0;
- } else {
- dbd_log( LOGSTD, "Fatal error resolving '%s/%s'", cwdbuf, name);
- db_cnid = 0;
- }
- /* Compare results from both CNID searches */
- if (ad_cnid && db_cnid && (ad_cnid == db_cnid)) {
- /* Everything is fine */
- return db_cnid;
- } else if (ad_cnid && db_cnid && (ad_cnid != db_cnid)) {
+ /* Compare CNID from db and adouble file */
+ if (ad_cnid != db_cnid && adfile_ok == 0) {
/* Mismatch, overwrite ad file with value from db */
- dbd_log( LOGSTD, "CNID mismatch for '%s/%s', db: %u, ad-file: %u", cwdbuf, name, ntohl(db_cnid), ntohl(ad_cnid));
- if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
- dbd_log(LOGSTD, "Updating AppleDouble file for '%s/%s' with CNID: %u from database",
- cwdbuf, name, ntohl(db_cnid));
- ad_init(&ad, myvol);
- if (ad_open(&ad, name, adflags | ADFLAGS_HF | ADFLAGS_RDWR) != 0) {
- dbd_log(LOGSTD, "Error opening AppleDouble file for '%s/%s': %s",
- cwdbuf, name, strerror(errno));
- return CNID_INVALID;
- }
- ad_setid( &ad, st->st_dev, st->st_ino, db_cnid, did, stamp);
- ad_flush(&ad);
- ad_close(&ad, ADFLAGS_HF);
- }
- return db_cnid;
- } else if (ad_cnid && (db_cnid == 0)) {
- /* in ad-file but not in db */
- if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
- /* Ensure the cnid from the ad-file is not already occupied by another file */
- dbd_log(LOGDEBUG, "Checking whether CNID %u from ad-file is occupied",
- ntohl(ad_cnid));
-
- rqst.cnid = ad_cnid;
- ret = dbd_resolve(dbd, &rqst, &rply);
- if (rply.result == CNID_DBD_RES_OK) {
- /* Occupied! Choose another, update ad-file */
- ret = dbd_add(dbd, &rqst, &rply, 1);
- if (dbif_txn_close(dbd, ret) != 0)
- return CNID_INVALID;
- db_cnid = rply.cnid;
- dbd_log(LOGSTD, "New CNID for '%s/%s': %u", cwdbuf, name, ntohl(db_cnid));
-
- 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(&ad, myvol);
- if (ad_open(&ad, name, adflags | ADFLAGS_RDWR) != 0) {
- dbd_log(LOGSTD, "Error opening AppleDouble file for '%s/%s': %s",
- cwdbuf, name, strerror(errno));
- return CNID_INVALID;
- }
- ad_setid( &ad, st->st_dev, st->st_ino, db_cnid, did, stamp);
- ad_flush(&ad);
- ad_close(&ad, ADFLAGS_HF);
- }
- return db_cnid;
- }
-
- dbd_log(LOGDEBUG, "CNID rebuild add '%s/%s' with CNID from ad-file %u",
- cwdbuf, name, ntohl(ad_cnid));
- rqst.cnid = ad_cnid;
- ret = dbd_rebuild_add(dbd, &rqst, &rply);
- if (dbif_txn_close(dbd, ret) != 0)
- return CNID_INVALID;
- }
- return ad_cnid;
- } else if ((db_cnid == 0) && (ad_cnid == 0)) {
- /* No CNID at all, we clearly have to allocate a fresh one... */
- /* Note: the next test will use this new CNID too! */
- if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
- /* add to db */
- ret = dbd_add(dbd, &rqst, &rply, 1);
- if (dbif_txn_close(dbd, ret) != 0)
- return CNID_INVALID;
- db_cnid = rply.cnid;
- dbd_log(LOGSTD, "New CNID for '%s/%s': %u", cwdbuf, name, ntohl(db_cnid));
- }
- }
-
- if ((ad_cnid == 0) && db_cnid) {
- /* in db but zeroID in ad-file, write it to ad-file */
- 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(&ad, myvol);
- if (ad_open(&ad, name, adflags | ADFLAGS_RDWR) != 0) {
- dbd_log(LOGSTD, "Error opening AppleDouble file for '%s/%s': %s",
- cwdbuf, name, strerror(errno));
- return CNID_INVALID;
- }
- ad_setid( &ad, st->st_dev, st->st_ino, db_cnid, did, stamp);
- ad_flush(&ad);
- ad_close(&ad, ADFLAGS_HF);
+ dbd_log(LOGSTD, "CNID mismatch for '%s/%s', CNID db: %u, ad-file: %u",
+ cwdbuf, name, ntohl(db_cnid), ntohl(ad_cnid));
+ ad_init(&ad, vol);
+ if (ad_open(&ad, name, adflags | ADFLAGS_HF | ADFLAGS_RDWR) != 0) {
+ dbd_log(LOGSTD, "Error opening AppleDouble file for '%s/%s': %s",
+ cwdbuf, name, strerror(errno));
+ return CNID_INVALID;
}
- return db_cnid;
+ ad_setid( &ad, st->st_dev, st->st_ino, db_cnid, did, stamp);
+ ad_flush(&ad);
+ ad_close(&ad, ADFLAGS_HF);
}
- return CNID_INVALID;
+ return db_cnid;
}
/*
*/
static int dbd_readdir(int volroot, cnid_t did)
{
- int cwd, ret = 0, adfile_ok, addir_ok, encoding_ok;
+ int cwd, ret = 0, adfile_ok, addir_ok;
cnid_t cnid = 0;
const char *name;
DIR *dp;
if (STRCMP(ep->d_name, == , ADv2_DIRNAME))
continue;
- if (!myvol->vfs->vfs_validupath(myvol, ep->d_name)) {
+ if (!vol->vfs->vfs_validupath(vol, ep->d_name)) {
dbd_log(LOGDEBUG, "Ignoring \"%s\"", ep->d_name);
continue;
}
switch (st.st_mode & S_IFMT) {
case S_IFREG:
case S_IFDIR:
- break;
case S_IFLNK:
- dbd_log(LOGDEBUG, "Ignoring symlink %s/%s", cwdbuf, ep->d_name);
- continue;
+ break;
default:
dbd_log(LOGSTD, "Bad filetype: %s/%s", cwdbuf, ep->d_name);
if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
if (ADDIR_OK)
adfile_ok = check_adfile(ep->d_name, &st, &name);
- if (name == NULL) {
- name = ep->d_name;
- } else {
- update_cnid(did, &st, ep->d_name, name);
- }
+ if (!S_ISLNK(st.st_mode)) {
+ if (name == NULL) {
+ name = ep->d_name;
+ } else {
+ update_cnid(did, &st, ep->d_name, name);
+ }
- if ( ! nocniddb) {
/* Check CNIDs */
cnid = check_cnid(name, did, &st, adfile_ok);
- /* Now add this object to our rebuild dbd */
- if (cnid && dbd_rebuild) {
- static uint count = 0;
- rqst.cnid = rply.cnid;
- ret = dbd_rebuild_add(dbd_rebuild, &rqst, &rply);
- if (dbif_txn_close(dbd_rebuild, ret) != 0)
- return -1;
- if (rply.result != CNID_DBD_RES_OK) {
- dbd_log( LOGSTD, "Fatal error adding CNID: %u for '%s/%s' to in-memory rebuild-db",
- cnid, cwdbuf, name);
- return -1;
- }
- count++;
- if (count == 10000) {
- if (dbif_txn_checkpoint(dbd_rebuild, 0, 0, 0) < 0) {
- dbd_log(LOGSTD, "Error checkpointing!");
- return -1;
- }
- count = 0;
- }
- }
+ /* Check EA files */
+ if (vol->v_vfs_ea == AFPVOL_EA_AD)
+ check_eafiles(name);
}
- /* Check EA files */
- if (myvol->v_vfs_ea == AFPVOL_EA_AD)
- check_eafiles(name);
-
/**************************************************************************
Recursion
**************************************************************************/
- if (S_ISDIR(st.st_mode) && (cnid || nocniddb)) { /* If we have no cnid for it we cant recur */
+ if (S_ISDIR(st.st_mode) && cnid) { /* If we have no cnid for it we cant enter recursion */
strcat(cwdbuf, "/");
strcat(cwdbuf, name);
dbd_log( LOGDEBUG, "Entering directory: %s", cwdbuf);
/*
Use results of previous checks
*/
- if ((myvol->v_adouble == AD_VERSION_EA) && (dbd_flags & DBD_FLAGS_V2TOEA)) {
+ if ((vol->v_adouble == AD_VERSION_EA) && (dbd_flags & DBD_FLAGS_V2TOEA)) {
if (rmdir(ADv2_DIRNAME) != 0) {
switch (errno) {
case ENOENT:
return ret;
}
-static int scanvol(struct vol *vol, dbd_flags_t flags)
+/*
+ Main func called from cmd_dbd.c
+*/
+int cmd_dbd_scanvol(struct vol *vol_in, dbd_flags_t flags)
{
+ EC_INIT;
struct stat st;
- /* Make this stuff accessible from all funcs easily */
- myvol = vol;
- dbd_flags = flags;
-
/* Run with umask 0 */
umask(0);
- strcpy(cwdbuf, myvol->v_path);
- chdir(myvol->v_path);
+ /* Make vol accessible for all funcs */
+ vol = vol_in;
+ dbd_flags = flags;
- if ((myvol->v_adouble == AD_VERSION_EA) && (dbd_flags & DBD_FLAGS_V2TOEA)) {
+ /* We only support unicode volumes ! */
+ if (vol->v_volcharset != CH_UTF8) {
+ dbd_log(LOGSTD, "Not a Unicode volume: %s, %u != %u", vol->v_volcodepage, vol->v_volcharset, CH_UTF8);
+ EC_FAIL;
+ }
+
+ /*
+ * Get CNID database stamp, cnid_getstamp() passes the buffer,
+ * then cnid_resolve() actually gets the value from the db
+ */
+ cnid_getstamp(vol->v_cdb, stamp, sizeof(stamp));
+
+ if (setjmp(jmp) != 0) {
+ EC_EXIT_STATUS(0); /* Got signal, jump from dbd_readdir */
+ }
+
+ strcpy(cwdbuf, vol->v_path);
+ chdir(vol->v_path);
+
+ if ((vol->v_adouble == AD_VERSION_EA) && (dbd_flags & DBD_FLAGS_V2TOEA)) {
if (lstat(".", &st) != 0)
- return -1;
+ EC_FAIL;
if (ad_convert(".", &st, vol, NULL) != 0) {
switch (errno) {
case ENOENT:
break;
default:
- dbd_log(LOGSTD, "Conversion error for \"%s\": %s", myvol->v_path, strerror(errno));
+ dbd_log(LOGSTD, "Conversion error for \"%s\": %s", vol->v_path, strerror(errno));
break;
}
}
}
/* Start recursion */
- if (dbd_readdir(1, htonl(2)) < 0) /* 2 = volumeroot CNID */
- return -1;
-
- return 0;
-}
-
-/*
- Remove all CNIDs from dbd that are not in dbd_rebuild
-*/
-static void delete_orphaned_cnids(DBD *dbd, DBD *dbd_rebuild, dbd_flags_t flags)
-{
- int ret = 0, deleted = 0;
- cnid_t dbd_cnid = 0, rebuild_cnid = 0;
- struct cnid_dbd_rqst rqst;
- struct cnid_dbd_rply rply;
-
- /* jump over rootinfo key */
- if ( dbif_idwalk(dbd, &dbd_cnid, 0) != 1)
- return;
- if ( dbif_idwalk(dbd_rebuild, &rebuild_cnid, 0) != 1)
- return;
-
- /* Get first id from dbd_rebuild */
- if ((dbif_idwalk(dbd_rebuild, &rebuild_cnid, 0)) == -1)
- return;
-
- /* Start main loop through dbd: get CNID from dbd */
- while ((dbif_idwalk(dbd, &dbd_cnid, 0)) == 1) {
- /* Check if we got a termination signal */
- if (alarmed)
- longjmp(jmp, 1); /* this jumps back to cmd_dbd_scanvol() */
-
- if (deleted > 1000) {
- deleted = 0;
- if (dbif_txn_checkpoint(dbd, 0, 0, 0) < 0) {
- dbd_log(LOGSTD, "Error checkpointing!");
- goto cleanup;
- }
- }
-
- /* This should be the normal case: CNID is in both dbs */
- if (dbd_cnid == rebuild_cnid) {
- /* Get next CNID from rebuild db */
- if ((ret = dbif_idwalk(dbd_rebuild, &rebuild_cnid, 0)) == -1) {
- /* Some error */
- goto cleanup;
- } else if (ret == 0) {
- /* end of rebuild_cnid, delete all remaining CNIDs from dbd */
- while ((dbif_idwalk(dbd, &dbd_cnid, 0)) == 1) {
- dbd_log(LOGSTD, "Orphaned CNID in database: %u", dbd_cnid);
- if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
- rqst.cnid = htonl(dbd_cnid);
- if ((ret = dbd_delete(dbd, &rqst, &rply, DBIF_CNID)) == -1) {
- dbd_log(LOGSTD, "Error deleting CNID %u", dbd_cnid);
- (void)dbif_txn_abort(dbd);
- goto cleanup;
- }
-
- if (dbif_txn_close(dbd, ret) != 0)
- return;
- deleted++;
- }
- /* Check if we got a termination signal */
- if (alarmed)
- longjmp(jmp, 1); /* this jumps back to cmd_dbd_scanvol() */
- }
- return;
- } else
- /* Normal case (ret=1): continue while loop */
- continue;
- }
-
- if (dbd_cnid < rebuild_cnid) {
- /* CNID is orphaned -> delete */
- dbd_log(LOGSTD, "One orphaned CNID in database: %u.", dbd_cnid);
- if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
- rqst.cnid = htonl(dbd_cnid);
- if ((ret = dbd_delete(dbd, &rqst, &rply, DBIF_CNID)) == -1) {
- dbd_log(LOGSTD, "Error deleting CNID %u", dbd_cnid);
- (void)dbif_txn_abort(dbd);
- goto cleanup;
- }
- if (dbif_txn_close(dbd, ret) != 0)
- return;
- deleted++;
- }
- continue;
- }
-
- if (dbd_cnid > rebuild_cnid) {
- dbif_idwalk(dbd, NULL, 1); /* Close cursor */
- dbif_idwalk(dbd_rebuild, NULL, 1); /* Close cursor */
- (void)dbif_txn_close(dbd, 2);
- (void)dbif_txn_close(dbd_rebuild, 2);
- dbd_log(LOGSTD, "Ghost CNID: %u. This is fatal! Dumping rebuild db:\n", rebuild_cnid);
- dbif_dump(dbd_rebuild, 0);
- dbd_log(LOGSTD, "Send this dump and a `dbd -d ...` dump to the Netatalk Dev team!");
- goto cleanup;
- }
- } /* while ((dbif_idwalk(dbd, &dbd_cnid, 0)) == 1) */
-
-cleanup:
- dbif_idwalk(dbd, NULL, 1); /* Close cursor */
- dbif_idwalk(dbd_rebuild, NULL, 1); /* Close cursor */
- return;
-}
-
-static const char *get_tmpdb_path(void)
-{
- pid_t pid = getpid();
- static char path[MAXPATHLEN];
- snprintf(path, MAXPATHLEN, "/tmp/tmpdb-dbd.%u", pid);
- if (mkdir(path, 0755) != 0)
- return NULL;
- return path;
-}
-
-/*
- Main func called from cmd_dbd.c
-*/
-int cmd_dbd_scanvol(DBD *dbd_ref, struct vol *vol, dbd_flags_t flags)
-{
- int ret = 0;
- struct db_param db_param = { 0 };
- const char *tmpdb_path = NULL;
-
- /* Set cachesize for in-memory rebuild db */
- db_param.cachesize = 64 * 1024; /* 64 MB */
- db_param.maxlocks = DEFAULT_MAXLOCKS;
- db_param.maxlockobjs = DEFAULT_MAXLOCKOBJS;
- db_param.logfile_autoremove = 1;
-
- /* Make it accessible for all funcs */
- dbd = dbd_ref;
-
- /* We only support unicode volumes ! */
- if (vol->v_volcharset != CH_UTF8) {
- dbd_log( LOGSTD, "Not a Unicode volume: %s, %u != %u", vol->v_volcodepage, vol->v_volcharset, CH_UTF8);
- return -1;
- }
-
- /* Get volume stamp */
- dbd_getstamp(dbd, &rqst, &rply);
- if (rply.result != CNID_DBD_RES_OK) {
- ret = -1;
- goto exit;
- }
- memcpy(stamp, rply.name, CNID_DEV_LEN);
-
- /* temporary rebuild db, used with -re rebuild to delete unused CNIDs, not used with -f */
- if (! nocniddb && (flags & DBD_FLAGS_EXCL) && !(flags & DBD_FLAGS_FORCE)) {
- tmpdb_path = get_tmpdb_path();
- if (NULL == (dbd_rebuild = dbif_init(tmpdb_path, "cnid2.db"))) {
- ret = -1;
- goto exit;
- }
-
- if (dbif_env_open(dbd_rebuild,
- &db_param,
- DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN) < 0) {
- dbd_log(LOGSTD, "error opening tmp database!");
- goto exit;
- }
+ EC_NEG1( dbd_readdir(1, htonl(2)) ); /* 2 = volumeroot CNID */
- if (0 != (dbif_open(dbd_rebuild, NULL, 0))) {
- ret = -1;
- goto exit;
- }
-
- if (0 != (dbif_copy_rootinfokey(dbd, dbd_rebuild))) {
- ret = -1;
- goto exit;
- }
- }
-
- if (setjmp(jmp) != 0) {
- ret = 0; /* Got signal, jump from dbd_readdir */
- goto exit;
- }
-
- /* scanvol */
- if ((scanvol(vol, flags)) != 0) {
- ret = -1;
- goto exit;
- }
-
-exit:
- if (! nocniddb) {
- if (dbif_txn_close(dbd, ret == 0 ? 1 : 0) != 0)
- ret = -1;
- if (dbd_rebuild)
- if (dbif_txn_close(dbd_rebuild, ret == 0 ? 1 : 0) != 0)
- ret = -1;
- if ((ret == 0) && dbd_rebuild && (flags & DBD_FLAGS_EXCL) && !(flags & DBD_FLAGS_FORCE))
- /* We can only do this in exclusive mode, otherwise we might delete CNIDs added from
- other clients in between our pass 1 and 2 */
- delete_orphaned_cnids(dbd, dbd_rebuild, flags);
- }
-
- if (dbd_rebuild) {
- dbd_log(LOGDEBUG, "Closing tmp db");
- dbif_close(dbd_rebuild);
-
- if (tmpdb_path) {
- char cmd[8 + MAXPATHLEN];
- snprintf(cmd, 8 + MAXPATHLEN, "rm -f %s/*", tmpdb_path);
- dbd_log( LOGDEBUG, "Removing temp database '%s'", tmpdb_path);
- system(cmd);
- snprintf(cmd, 8 + MAXPATHLEN, "rmdir %s", tmpdb_path);
- system(cmd);
- }
- }
- return ret;
+EC_CLEANUP:
+ EC_EXIT;
}
#include <atalk/compat.h>
#include <atalk/errchk.h>
#include <atalk/bstrlib.h>
+#include <atalk/bstradd.h>
#include <atalk/netatalk_conf.h>
#include <atalk/volume.h>
static int set_dbdir(const char *dbdir, const char *vpath)
{
EC_INIT;
- int status;
struct stat st;
bstring oldpath, newpath;
char *cmd_argv[4];
EC_FAIL;
}
- if (lstat(bdata(oldpath), &st) == 0 && lstat(bdata(newpath), &st) != 0 && errno == ENOENT) {
+ if (lstat(cfrombstr(oldpath), &st) == 0 && lstat(cfrombstr(newpath), &st) != 0 && errno == ENOENT) {
/* There's an .AppleDB in the volume root, we move it */
cmd_argv[0] = "mv";
cmd_argv[1] = bdata(oldpath);
}
- if (lstat(bdata(newpath), &st) < 0 && mkdir(bdata(newpath), 0755 ) < 0) {
+ if (lstat(cfrombstr(newpath), &st) < 0 && mkdir(cfrombstr(newpath), 0755 ) < 0) {
LOG(log_error, logtype_cnid, "set_dbdir: mkdir failed for %s", bdata(newpath));
EC_FAIL;
}
EC_EXIT;
}
-/* ------------------ */
-static uid_t user_to_uid (char *username)
-{
- struct passwd *this_passwd;
-
- /* check for anything */
- if ( !username || strlen ( username ) < 1 ) return 0;
-
- /* grab the /etc/passwd record relating to username */
- this_passwd = getpwnam ( username );
-
- /* return false if there is no structure returned */
- if (this_passwd == NULL) return 0;
-
- /* return proper uid */
- return this_passwd->pw_uid;
-
-}
-
-/* ------------------ */
-static gid_t group_to_gid ( char *group)
-{
- struct group *this_group;
-
- /* check for anything */
- if ( !group || strlen ( group ) < 1 ) return 0;
-
- /* grab the /etc/groups record relating to group */
- this_group = getgrnam ( group );
-
- /* return false if there is no structure returned */
- if (this_group == NULL) return 0;
-
- /* return proper gid */
- return this_group->gr_gid;
-
-}
-
/* ------------------ */
static void catch_child(int sig _U_)
{
int cc;
uid_t uid = 0;
gid_t gid = 0;
- int err = 0;
int debug = 0;
int ret;
sigset_t set;
if (afp_config_parse(&obj, "cnid_metad") != 0)
daemon_exit(1);
- if (load_volumes(&obj, NULL) != 0)
+ if (load_volumes(&obj) != 0)
daemon_exit(1);
(void)setlimits();
host = iniparser_getstrdup(obj.iniconfig, INISEC_GLOBAL, "cnid listen", "localhost:4700");
- if (port = strrchr(host, ':'))
+ if ((port = strrchr(host, ':')))
*port++ = 0;
else
port = DEFAULTPORT;
LOG(log_debug, logtype_cnid, "main: request for volume: %s", volpath);
- if (load_volumes(&obj, NULL) != 0) {
+ if (load_volumes(&obj) != 0) {
LOG(log_severe, logtype_cnid, "main: error reloading config");
goto loop_end;
}
/*
- * $Id: db_param.c,v 1.9 2009-11-23 19:04:14 franklahm Exp $
*
* Copyright (C) Joerg Lenneis 2003
* Copyright (c) Frank Lahm 2009
extern int add_cnid(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply);
extern int get_cnid(DBD *dbd, struct cnid_dbd_rply *rply);
-extern int dbd_add(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *, int nolookup);
-extern int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *, int roflag);
+extern int dbd_add(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *);
+extern int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *);
extern int dbd_get(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *);
extern int dbd_resolve(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *);
extern int dbd_update(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *);
{
static cnid_t id;
static char buf[ROOTINFO_DATALEN];
- DBT rootinfo_key, rootinfo_data;
+ DBT rootinfo_key, rootinfo_data, key, data;
int rc;
cnid_t hint;
rootinfo_key.data = ROOTINFO_KEY;
rootinfo_key.size = ROOTINFO_KEYLEN;
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+
if (id == 0) {
- if ((rc = dbif_get(dbd, DBIF_CNID, &rootinfo_key, &rootinfo_data, 0)) < 0) {
+ if ((rc = dbif_get(dbd, DBIF_CNID, &rootinfo_key, &rootinfo_data, 0)) != 1) {
rply->result = CNID_DBD_RES_ERR_DB;
return -1;
}
- if (rc == 0) {
- /* no rootinfo key yet */
- memcpy(buf, ROOTINFO_DATA, ROOTINFO_DATALEN);
+ memcpy(buf, (char *)rootinfo_data.data, ROOTINFO_DATALEN);
+ memcpy(&hint, buf + CNID_TYPE_OFS, sizeof(hint));
+ id = ntohl(hint);
+ if (id < CNID_START - 1)
id = CNID_START - 1;
- } else {
- memcpy(buf, (char *)rootinfo_data.data, ROOTINFO_DATALEN);
- memcpy(&hint, buf + CNID_TYPE_OFS, sizeof(hint));
- id = ntohl(hint);
- if (id < CNID_START - 1)
- id = CNID_START - 1;
- }
}
- /* If we've hit the max CNID allowed, we return an error. CNID
- * needs to be recycled before proceding. */
- if (++id == CNID_INVALID) {
- rply->result = CNID_DBD_RES_ERR_MAX;
- return -1;
+ cnid_t trycnid, tmp;
+
+ while (true) {
+ if (rply->cnid != CNID_INVALID) {
+ trycnid = ntohl(rply->cnid);
+ rply->cnid = CNID_INVALID;
+ } else {
+ if (++id == CNID_INVALID)
+ id = CNID_START;
+ trycnid = id;
+ }
+ tmp = htonl(trycnid);
+ key.data = &tmp;
+ key.size = sizeof(cnid_t);
+ rc = dbif_get(dbd, DBIF_CNID, &key, &data, 0);
+ if (rc == 0) {
+ break;
+ } else if (rc == -1) {
+ rply->result = CNID_DBD_RES_ERR_DB;
+ return -1;
+ }
}
- rootinfo_data.data = buf;
- rootinfo_data.size = ROOTINFO_DATALEN;
- hint = htonl(id);
- memcpy(buf + CNID_TYPE_OFS, &hint, sizeof(hint));
+ if (trycnid == id) {
+ rootinfo_data.data = buf;
+ rootinfo_data.size = ROOTINFO_DATALEN;
+ hint = htonl(id);
+ memcpy(buf + CNID_TYPE_OFS, &hint, sizeof(hint));
- if (dbif_put(dbd, DBIF_CNID, &rootinfo_key, &rootinfo_data, 0) < 0) {
- rply->result = CNID_DBD_RES_ERR_DB;
- return -1;
+ if (dbif_put(dbd, DBIF_CNID, &rootinfo_key, &rootinfo_data, 0) < 0) {
+ rply->result = CNID_DBD_RES_ERR_DB;
+ return -1;
+ }
}
- rply->cnid = hint;
+
+ rply->cnid = htonl(trycnid);
return 0;
}
/* ------------------------ */
/* We need a nolookup version for `dbd` */
-int dbd_add(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply, int nolookup)
+int dbd_add(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
{
rply->namelen = 0;
ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
/* See if we have an entry already and return it if yes */
- if (! nolookup) {
- if (dbd_lookup(dbd, rqst, rply, 0) < 0) {
- LOG(log_debug, logtype_cnid, "dbd_add(did:%u, '%s', dev/ino:0x%llx/0x%llx): error in dbd_lookup",
- ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
- return -1;
- }
+ if (dbd_lookup(dbd, rqst, rply) < 0) {
+ LOG(log_debug, logtype_cnid, "dbd_add(did:%u, '%s', dev/ino:0x%llx/0x%llx): error in dbd_lookup",
+ ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
+ return -1;
+ }
- if (rply->result == CNID_DBD_RES_OK) {
- /* Found it. rply->cnid is the correct CNID now. */
- LOG(log_debug, logtype_cnid, "dbd_add: dbd_lookup success --> CNID: %u", ntohl(rply->cnid));
- return 1;
- }
+ if (rply->result == CNID_DBD_RES_OK) {
+ /* Found it. rply->cnid is the correct CNID now. */
+ LOG(log_debug, logtype_cnid, "dbd_add: dbd_lookup success --> CNID: %u", ntohl(rply->cnid));
+ return 1;
}
LOG(log_debug, logtype_cnid, "dbd_add(did:%u, '%s', dev/ino:0x%llx/0x%llx): {adding to database ...}",
ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
-
+ if (rqst->cnid) {
+ /* rqst->cnid is the cnid "hint"/backup from the adouble file */
+ rply->cnid = rqst->cnid;
+ }
if (get_cnid(dbd, rply) < 0) {
if (rply->result == CNID_DBD_RES_ERR_MAX) {
LOG(log_error, logtype_cnid, "dbd_add: FATAL: CNID database has reached its limit.");
/*
- * $Id: dbd_dbcheck.c,v 1.4 2009-05-06 11:54:24 franklahm Exp $
*
* Copyright (C) Joerg Lenneis 2003
* All Rights Reserved. See COPYING.
/*
- * $Id: dbd_delete.c,v 1.5 2009-07-12 09:21:34 franklahm Exp $
*
* Copyright (C) Joerg Lenneis 2003
* All Rights Reserved. See COPYING.
/*
- * $Id: dbd_get.c,v 1.4 2009-05-06 11:54:24 franklahm Exp $
*
* Copyright (C) Joerg Lenneis 2003
* All Rights Reserved. See COPYING.
/*
- * $Id: dbd_getstamp.c,v 1.4 2009-05-06 11:54:24 franklahm Exp $
*
* Copyright (C) Joerg Lenneis 2003
* All Rights Reserved. See COPYING.
/*
- * $Id: dbd_lookup.c,v 1.18 2010-01-19 14:57:11 franklahm Exp $
*
* Copyright (C) Joerg Lenneis 2003
* Copyright (C) Frank Lahm 2009
#include <atalk/logger.h>
#include <atalk/cnid_dbd_private.h>
+#include <atalk/cnid.h>
#include "pack.h"
#include "dbif.h"
* up the database if there's a problem.
*/
-int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply, int roflag)
+int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
{
unsigned char *buf;
DBT key, devdata, diddata;
LOG(log_debug, logtype_cnid, "dbd_lookup(name:'%s', did:%u, dev/ino:0x%llx/0x%llx): type mismatch for devino",
rqst->name, ntohl(rqst->did), (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
- if (! roflag) {
- rqst->cnid = id_devino;
- rc = dbd_delete(dbd, rqst, rply, DBIF_CNID);
- rc += dbd_delete(dbd, rqst, rply, DBIF_IDX_DEVINO);
- rc += dbd_delete(dbd, rqst, rply, DBIF_IDX_DIDNAME);
- if (rc < 0) {
- LOG(log_error, logtype_cnid, "dbd_lookup(name:'%s', did:%u, dev/ino:0x%llx/0x%llx): error deleting type mismatch for devino",
- rqst->name, ntohl(rqst->did), (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
- return -1;
- }
+ rqst->cnid = id_devino;
+ rc = dbd_delete(dbd, rqst, rply, DBIF_CNID);
+ rc += dbd_delete(dbd, rqst, rply, DBIF_IDX_DEVINO);
+ rc += dbd_delete(dbd, rqst, rply, DBIF_IDX_DIDNAME);
+ if (rc < 0) {
+ LOG(log_error, logtype_cnid, "dbd_lookup(name:'%s', did:%u, dev/ino:0x%llx/0x%llx): error deleting type mismatch for devino",
+ rqst->name, ntohl(rqst->did), (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
+ return -1;
}
}
LOG(log_debug, logtype_cnid, "dbd_lookup(name:'%s', did:%u, dev/ino:0x%llx/0x%llx): type mismatch for didname",
rqst->name, ntohl(rqst->did), (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
- if (! roflag) {
- rqst->cnid = id_didname;
- rc = dbd_delete(dbd, rqst, rply, DBIF_CNID);
- rc += dbd_delete(dbd, rqst, rply, DBIF_IDX_DEVINO);
- rc += dbd_delete(dbd, rqst, rply, DBIF_IDX_DIDNAME);
- if (rc < 0) {
- LOG(log_error, logtype_cnid, "dbd_lookup(name:'%s', did:%u, dev/ino:0x%llx/0x%llx): error deleting type mismatch for didname",
- rqst->name, ntohl(rqst->did), (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
- return -1;
- }
+ rqst->cnid = id_didname;
+ rc = dbd_delete(dbd, rqst, rply, DBIF_CNID);
+ rc += dbd_delete(dbd, rqst, rply, DBIF_IDX_DEVINO);
+ rc += dbd_delete(dbd, rqst, rply, DBIF_IDX_DIDNAME);
+ if (rc < 0) {
+ LOG(log_error, logtype_cnid, "dbd_lookup(name:'%s', did:%u, dev/ino:0x%llx/0x%llx): error deleting type mismatch for didname",
+ rqst->name, ntohl(rqst->did), (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
+ return -1;
}
}
ntohl(rqst->did), rqst->name, ntohl(id_didname),
(unsigned long long)rqst->dev, (unsigned long long)rqst->ino, ntohl(id_devino));
- if (! roflag) {
- rqst->cnid = id_devino;
- if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
- return -1;
+ rqst->cnid = id_devino;
+ if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
+ return -1;
+
+ rqst->cnid = id_didname;
+ if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
+ return -1;
- rqst->cnid = id_didname;
- if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
- return -1;
- }
rply->result = CNID_DBD_RES_NOTFOUND;
return 1;
}
LOG(log_debug, logtype_cnid, "dbd_lookup: server side mv (with resource fork)");
update = 1;
} else {
- if ( ! roflag) {
- rqst->cnid = id_devino;
- if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
- return -1;
- }
+ rqst->cnid = id_devino;
+ if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
+ return -1;
rply->result = CNID_DBD_RES_NOTFOUND;
+ rqst->cnid = CNID_INVALID; /* invalidate CNID hint */
return 1;
}
}
if ( ! devino) {
LOG(log_debug, logtype_cnid, "dbd_lookup(DID:%u/'%s',0x%llx/0x%llx): CNID resolve problem: changed dev/ino",
ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
- if ( ! roflag) {
- rqst->cnid = id_didname;
- if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
- return -1;
- }
+ rqst->cnid = id_didname;
+ if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
+ return -1;
rply->result = CNID_DBD_RES_NOTFOUND;
+ rqst->cnid = CNID_INVALID; /* invalidate CNID hint */
return 1;
}
/* This is also a catch all if we've forgot to catch some possibility with the preceding ifs*/
- if (!update || roflag) {
+ if (!update) {
rply->result = CNID_DBD_RES_NOTFOUND;
return 1;
}
/*
- * $Id: dbd_rebuild_add.c,v 1.4 2009-12-23 10:18:48 franklahm Exp $
*
* Copyright (C) Joerg Lenneis 2005
* All Rights Reserved. See COPYING.
/*
- * $Id: dbd_resolve.c,v 1.4 2009-05-06 11:54:24 franklahm Exp $
*
* Copyright (C) Joerg Lenneis 2003
* All Rights Reserved. See COPYING.
#include <atalk/logger.h>
#include <atalk/util.h>
#include <atalk/errchk.h>
+#include <atalk/cnid.h>
#include "db_param.h"
#include "dbif.h"
static int dbif_init_rootinfo(DBD *dbd, int version)
{
DBT key, data;
- uint32_t v;
+ uint32_t uint32;
char buf[ROOTINFO_DATALEN];
LOG(log_debug, logtype_cnid, "Setting CNID database version to %u", version);
- v = version;
- v = htonl(v);
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
data.size = ROOTINFO_DATALEN;
memcpy(buf, ROOTINFO_DATA, ROOTINFO_DATALEN);
- memcpy(buf + CNID_DID_OFS, &v, sizeof(v));
+
+ uint32 = htonl(CNID_START - 1);
+ memcpy(buf + CNID_TYPE_OFS, &uint32, sizeof(uint32));
+
+ uint32 = htonl(version);
+ memcpy(buf + CNID_DID_OFS, &uint32, sizeof(uint32));
+
if (dbif_stamp(dbd, buf + CNID_DEV_OFS, CNID_DEV_LEN) < 0)
return -1;
return ret;
}
-/*!
- * Get lock on db lock file
- *
- * @args cmd (r) lock command:
- * LOCK_FREE: close lockfd
- * LOCK_UNLOCK: unlock lockm keep lockfd open
- * LOCK_EXCL: F_WRLCK on lockfd
- * LOCK_SHRD: F_RDLCK on lockfd
- * @args dbpath (r) path to lockfile, only used on first call,
- * later the stored fd is used
- * @returns LOCK_FREE/LOCK_UNLOCK return 0 on success, -1 on error
- * LOCK_EXCL/LOCK_SHRD return LOCK_EXCL or LOCK_SHRD respectively on
- * success, 0 if the lock couldn't be acquired, -1 on other errors
- */
-int get_lock(int cmd, const char *dbpath)
-{
- static int lockfd = -1;
- int ret;
- char lockpath[PATH_MAX];
- struct stat st;
-
- LOG(log_debug, logtype_cnid, "get_lock(%s, \"%s\")",
- cmd == LOCK_EXCL ? "LOCK_EXCL" :
- cmd == LOCK_SHRD ? "LOCK_SHRD" :
- cmd == LOCK_FREE ? "LOCK_FREE" :
- cmd == LOCK_UNLOCK ? "LOCK_UNLOCK" : "UNKNOWN" , dbpath ? dbpath : "");
-
- switch (cmd) {
- case LOCK_FREE:
- if (lockfd == -1)
- return -1;
- close(lockfd);
- lockfd = -1;
- return 0;
-
- case LOCK_UNLOCK:
- if (lockfd == -1)
- return -1;
- return unlock(lockfd, 0, SEEK_SET, 0);
-
- case LOCK_EXCL:
- case LOCK_SHRD:
- if (lockfd == -1) {
- if ( (strlen(dbpath) + strlen(LOCKFILENAME+1)) > (PATH_MAX - 1) ) {
- LOG(log_error, logtype_cnid, ".AppleDB pathname too long");
- return -1;
- }
- strncpy(lockpath, dbpath, PATH_MAX - 1);
- strcat(lockpath, "/");
- strcat(lockpath, LOCKFILENAME);
-
- if ((lockfd = open(lockpath, O_RDWR | O_CREAT, 0644)) < 0) {
- LOG(log_error, logtype_cnid, "Error opening lockfile: %s", strerror(errno));
- return -1;
- }
-
- if ((stat(dbpath, &st)) != 0) {
- LOG(log_error, logtype_cnid, "Error statting lockfile: %s", strerror(errno));
- return -1;
- }
-
- if ((chown(lockpath, st.st_uid, st.st_gid)) != 0) {
- LOG(log_error, logtype_cnid, "Error inheriting lockfile permissions: %s",
- strerror(errno));
- return -1;
- }
- }
-
- if (cmd == LOCK_EXCL)
- ret = write_lock(lockfd, 0, SEEK_SET, 0);
- else
- ret = read_lock(lockfd, 0, SEEK_SET, 0);
-
- if (ret != 0) {
- if (cmd == LOCK_SHRD)
- LOG(log_error, logtype_cnid, "Volume CNID db is locked, try again...");
- return 0;
- }
-
- LOG(log_debug, logtype_cnid, "get_lock: got %s lock",
- cmd == LOCK_EXCL ? "LOCK_EXCL" : "LOCK_SHRD");
- return cmd;
-
- default:
- return -1;
- } /* switch(cmd) */
-
- /* deadc0de, never get here */
- return -1;
-}
-
/* --------------- */
DBD *dbif_init(const char *envhome, const char *filename)
{
LOG(log_debug, logtype_cnid, "Trying to remove BerkeleyDB environment");
- if (get_lock(LOCK_EXCL, path) != LOCK_EXCL) {
- LOG(log_debug, logtype_cnid, "CNID db \"%s\" in use, not removing BerkeleyDB environment", path);
- return 0;
- }
-
if (NULL == (dbd = dbif_init(path, "cnid2.db")))
return -1;
#define DBIF_IDX_DIDNAME 2
#define DBIF_IDX_NAME 3
-/* get_lock cmd and return value */
#define LOCKFILENAME "lock"
#define LOCK_FREE 0
#define LOCK_UNLOCK 1
db_table db_table[DBIF_DB_CNT];
} DBD;
-/* Functions */
-extern int get_lock(int cmd, const char *dbpath);
-
extern DBD *dbif_init(const char *envhome, const char *dbname);
extern int dbif_env_open(DBD *dbd, struct db_param *dbp, uint32_t dbenv_oflags);
extern int dbif_open(DBD *dbd, struct db_param *dbp, int reindex);
#include <atalk/logger.h>
#include <atalk/errchk.h>
#include <atalk/bstrlib.h>
+#include <atalk/bstradd.h>
#include <atalk/netatalk_conf.h>
+#include <atalk/util.h>
#include "db_param.h"
#include "dbif.h"
static DBD *dbd;
static int exit_sig = 0;
static int db_locked;
+static bstring dbpath;
+static struct db_param *dbp;
+static struct vol *vol;
static void sig_exit(int signo)
{
of the cnid_dbd_rply structure contains further details.
*/
-#ifndef min
-#define min(a,b) ((a)<(b)?(a):(b))
-#endif
+
+/*!
+ * Get lock on db lock file
+ *
+ * @args cmd (r) lock command:
+ * LOCK_FREE: close lockfd
+ * LOCK_UNLOCK: unlock lockm keep lockfd open
+ * LOCK_EXCL: F_WRLCK on lockfd
+ * LOCK_SHRD: F_RDLCK on lockfd
+ * @args dbpath (r) path to lockfile, only used on first call,
+ * later the stored fd is used
+ * @returns LOCK_FREE/LOCK_UNLOCK return 0 on success, -1 on error
+ * LOCK_EXCL/LOCK_SHRD return LOCK_EXCL or LOCK_SHRD respectively on
+ * success, 0 if the lock couldn't be acquired, -1 on other errors
+ */
+static int get_lock(int cmd, const char *dbpath)
+{
+ static int lockfd = -1;
+ int ret;
+ char lockpath[PATH_MAX];
+ struct stat st;
+
+ LOG(log_debug, logtype_cnid, "get_lock(%s, \"%s\")",
+ cmd == LOCK_EXCL ? "LOCK_EXCL" :
+ cmd == LOCK_SHRD ? "LOCK_SHRD" :
+ cmd == LOCK_FREE ? "LOCK_FREE" :
+ cmd == LOCK_UNLOCK ? "LOCK_UNLOCK" : "UNKNOWN",
+ dbpath ? dbpath : "");
+
+ switch (cmd) {
+ case LOCK_FREE:
+ if (lockfd == -1)
+ return -1;
+ close(lockfd);
+ lockfd = -1;
+ return 0;
+
+ case LOCK_UNLOCK:
+ if (lockfd == -1)
+ return -1;
+ return unlock(lockfd, 0, SEEK_SET, 0);
+
+ case LOCK_EXCL:
+ case LOCK_SHRD:
+ if (lockfd == -1) {
+ if ( (strlen(dbpath) + strlen(LOCKFILENAME+1)) > (PATH_MAX - 1) ) {
+ LOG(log_error, logtype_cnid, ".AppleDB pathname too long");
+ return -1;
+ }
+ strncpy(lockpath, dbpath, PATH_MAX - 1);
+ strcat(lockpath, "/");
+ strcat(lockpath, LOCKFILENAME);
+
+ if ((lockfd = open(lockpath, O_RDWR | O_CREAT, 0644)) < 0) {
+ LOG(log_error, logtype_cnid, "Error opening lockfile: %s", strerror(errno));
+ return -1;
+ }
+
+ if ((stat(dbpath, &st)) != 0) {
+ LOG(log_error, logtype_cnid, "Error statting lockfile: %s", strerror(errno));
+ return -1;
+ }
+
+ if ((chown(lockpath, st.st_uid, st.st_gid)) != 0) {
+ LOG(log_error, logtype_cnid, "Error inheriting lockfile permissions: %s",
+ strerror(errno));
+ return -1;
+ }
+ }
+
+ if (cmd == LOCK_EXCL)
+ ret = write_lock(lockfd, 0, SEEK_SET, 0);
+ else
+ ret = read_lock(lockfd, 0, SEEK_SET, 0);
+
+ if (ret != 0) {
+ if (cmd == LOCK_SHRD)
+ LOG(log_error, logtype_cnid, "Volume CNID db is locked, try again...");
+ return 0;
+ }
+
+ LOG(log_debug, logtype_cnid, "get_lock: got %s lock",
+ cmd == LOCK_EXCL ? "LOCK_EXCL" : "LOCK_SHRD");
+ return cmd;
+
+ default:
+ return -1;
+ } /* switch(cmd) */
+
+ /* deadc0de, never get here */
+ return -1;
+}
+
+static int open_db(void)
+{
+ EC_INIT;
+
+ /* Get db lock */
+ if ((db_locked = get_lock(LOCK_EXCL, bdata(dbpath))) != LOCK_EXCL) {
+ LOG(log_error, logtype_cnid, "main: fatal db lock error");
+ EC_FAIL;
+ }
+
+ if (NULL == (dbd = dbif_init(bdata(dbpath), "cnid2.db")))
+ EC_FAIL;
+
+ /* Only recover if we got the lock */
+ if (dbif_env_open(dbd, dbp, DBOPTIONS | DB_RECOVER) < 0)
+ EC_FAIL;
+
+ LOG(log_debug, logtype_cnid, "Finished initializing BerkeleyDB environment");
+
+ if (dbif_open(dbd, dbp, 0) < 0)
+ EC_FAIL;
+
+ LOG(log_debug, logtype_cnid, "Finished opening BerkeleyDB databases");
+
+EC_CLEANUP:
+ if (ret != 0) {
+ if (dbd) {
+ (void)dbif_close(dbd);
+ dbd = NULL;
+ }
+ }
+
+ EC_EXIT;
+}
+
+static int delete_db(void)
+{
+ EC_INIT;
+ int cwd = -1;
+
+ EC_ZERO( get_lock(LOCK_FREE, bdata(dbpath)) );
+ EC_NEG1( cwd = open(".", O_RDONLY) );
+ chdir(cfrombstr(dbpath));
+ system("rm -f cnid2.db lock log.* __db.*");
+
+ if ((db_locked = get_lock(LOCK_EXCL, bdata(dbpath))) != LOCK_EXCL) {
+ LOG(log_error, logtype_cnid, "main: fatal db lock error");
+ EC_FAIL;
+ }
+
+ LOG(log_warning, logtype_cnid, "Recreated CNID BerkeleyDB databases of volume \"%s\"", vol->v_localname);
+
+EC_CLEANUP:
+ if (cwd != -1)
+ fchdir(cwd);
+ EC_EXIT;
+}
+
+
+/**
+ * Close dbd if open, delete it, reopen
+ *
+ * Also tries to copy the rootinfo key, that would allow for keeping the db stamp
+ * and last used CNID
+ **/
+static int reinit_db(void)
+{
+ EC_INIT;
+ DBT key, data;
+ bool copyRootInfo = false;
+
+ if (dbd) {
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+
+ key.data = ROOTINFO_KEY;
+ key.size = ROOTINFO_KEYLEN;
+
+ if (dbif_get(dbd, DBIF_CNID, &key, &data, 0) <= 0) {
+ LOG(log_error, logtype_cnid, "dbif_copy_rootinfokey: Error getting rootinfo record");
+ copyRootInfo = false;
+ } else {
+ copyRootInfo = true;
+ }
+ (void)dbif_close(dbd);
+ }
+
+ EC_ZERO_LOG( delete_db() );
+ EC_ZERO_LOG( open_db() );
+
+ if (copyRootInfo == true) {
+ memset(&key, 0, sizeof(key));
+ key.data = ROOTINFO_KEY;
+ key.size = ROOTINFO_KEYLEN;
+
+ if (dbif_put(dbd, DBIF_CNID, &key, &data, 0) != 0) {
+ LOG(log_error, logtype_cnid, "dbif_copy_rootinfokey: Error writing rootinfo key");
+ EC_FAIL;
+ }
+ }
+
+EC_CLEANUP:
+ EC_EXIT;
+}
static int loop(struct db_param *dbp)
{
dbp->flush_interval, timebuf);
while (1) {
- timeout = min(time_next_flush, time_last_rqst +dbp->idle_timeout);
+ timeout = MIN(time_next_flush, time_last_rqst + dbp->idle_timeout);
if (timeout > now)
timeout -= now;
else
ret = 1;
break;
case CNID_DBD_OP_ADD:
- ret = dbd_add(dbd, &rqst, &rply, 0);
+ ret = dbd_add(dbd, &rqst, &rply);
break;
case CNID_DBD_OP_GET:
ret = dbd_get(dbd, &rqst, &rply);
ret = dbd_resolve(dbd, &rqst, &rply);
break;
case CNID_DBD_OP_LOOKUP:
- ret = dbd_lookup(dbd, &rqst, &rply, 0);
+ ret = dbd_lookup(dbd, &rqst, &rply);
break;
case CNID_DBD_OP_UPDATE:
ret = dbd_update(dbd, &rqst, &rply);
case CNID_DBD_OP_SEARCH:
ret = dbd_search(dbd, &rqst, &rply);
break;
+ case CNID_DBD_OP_WIPE:
+ ret = reinit_db();
+ break;
default:
LOG(log_error, logtype_cnid, "loop: unknown op %d", rqst.op);
ret = -1;
int main(int argc, char *argv[])
{
EC_INIT;
- struct db_param *dbp;
int delete_bdb = 0;
int ctrlfd = -1, clntfd = -1;
- char *logconfig;
AFPObj obj = { 0 };
- struct vol *vol;
char *volpath = NULL;
- bstring dbpath;
while (( ret = getopt( argc, argv, "dF:l:p:t:vV")) != -1 ) {
switch (ret) {
case 'd':
+ /* this is now just ignored, as we do it automatically anyway */
delete_bdb = 1;
break;
case 'F':
EC_ZERO( afp_config_parse(&obj, "cnid_dbd") );
- EC_ZERO( load_volumes(&obj, NULL) );
+ EC_ZERO( load_volumes(&obj) );
EC_NULL( vol = getvolbypath(&obj, volpath) );
EC_ZERO( load_charset(vol) );
pack_setvol(vol);
switch_to_user(bdata(dbpath));
- /* Get db lock */
- if ((db_locked = get_lock(LOCK_EXCL, bdata(dbpath))) == -1) {
- LOG(log_error, logtype_cnid, "main: fatal db lock error");
- EC_FAIL;
- }
- if (db_locked != LOCK_EXCL) {
- /* Couldn't get exclusive lock, try shared lock */
- if ((db_locked = get_lock(LOCK_SHRD, NULL)) != LOCK_SHRD) {
- LOG(log_error, logtype_cnid, "main: fatal db lock error");
- EC_FAIL;
- }
- }
-
- if (delete_bdb && (db_locked == LOCK_EXCL)) {
- LOG(log_warning, logtype_cnid, "main: too many CNID db opening attempts, wiping the slate clean");
- chdir(bdata(dbpath));
- system("rm -f cnid2.db lock log.* __db.*");
- if ((db_locked = get_lock(LOCK_EXCL, bdata(dbpath))) != LOCK_EXCL) {
- LOG(log_error, logtype_cnid, "main: fatal db lock error");
- EC_FAIL;
- }
- }
-
set_signal();
/* SIGINT and SIGTERM are always off, unless we are in pselect */
EC_FAIL;
LOG(log_maxdebug, logtype_cnid, "Finished parsing db_param config file");
- if (NULL == (dbd = dbif_init(bdata(dbpath), "cnid2.db")))
- EC_FAIL;
-
- /* Only recover if we got the lock */
- if (dbif_env_open(dbd,
- dbp,
- (db_locked == LOCK_EXCL) ? DBOPTIONS | DB_RECOVER : DBOPTIONS) < 0)
- EC_FAIL;
- LOG(log_debug, logtype_cnid, "Finished initializing BerkeleyDB environment");
-
- if (dbif_open(dbd, dbp, 0) < 0) {
- ret = -1;
- goto close_db;
- }
-
- LOG(log_debug, logtype_cnid, "Finished opening BerkeleyDB databases");
-
- /* Downgrade db lock */
- if (db_locked == LOCK_EXCL) {
- if (get_lock(LOCK_UNLOCK, NULL) != 0) {
- ret = -1;
- goto close_db;
- }
-
- if (get_lock(LOCK_SHRD, NULL) != LOCK_SHRD) {
- ret = -1;
- goto close_db;
- }
+ if (open_db() != 0) {
+ LOG(log_error, logtype_cnid, "Failed to open CNID database for volume \"%s\"", vol->v_localname);
+ EC_ZERO_LOG( reinit_db() );
}
-
if (comm_init(dbp, ctrlfd, clntfd) < 0) {
ret = -1;
goto close_db;
/*
- * $Id: usockfd.h,v 1.5 2009-11-05 14:38:07 franklahm Exp $
*
* Copyright (C) Joerg Lenneis 2003
* All Rights Reserved. See COPYING.
-/*
- * Copyright (c) 1990,1993 Regents of The University of Michigan.
- * All Rights Reserved. See COPYRIGHT.
- */
-
+/*
+ Copyright (c) 2012 Frank Lahm <franklahm@gmail.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
/* static variables */
static AFPObj obj;
-static sig_atomic_t got_chldsig;
static pid_t afpd_pid = -1, cnid_metad_pid = -1;
static uint afpd_restarts, cnid_metad_restarts;
static struct event_base *base;
kill_childs(SIGQUIT, &afpd_pid, &cnid_metad_pid, NULL);
}
+/* SIGQUIT callback */
+static void sighup_cb(evutil_socket_t fd, short what, void *arg)
+{
+ LOG(log_note, logtype_afpd, "Received SIGHUP, sending all processes signal to reload config");
+ kill_childs(SIGHUP, &afpd_pid, &cnid_metad_pid, NULL);
+}
+
/* SIGCHLD callback */
static void sigchld_cb(evutil_socket_t fd, short what, void *arg)
{
- int status, i;
+ int status;
pid_t pid;
LOG(log_debug, logtype_afpd, "Got SIGCHLD event");
if (pid == afpd_pid)
afpd_pid = -1;
- else if (pid = cnid_metad_pid)
+ else if (pid == cnid_metad_pid)
cnid_metad_pid = -1;
else
LOG(log_error, logtype_afpd, "Bad pid: %d", pid);
/* timer callback */
static void timer_cb(evutil_socket_t fd, short what, void *arg)
{
- static int i = 0;
-
if (in_shutdown)
return;
int main(int argc, char **argv)
{
- const char *configfile = NULL;
int c, ret, debug = 0;
sigset_t blocksigs;
struct timeval tv;
sigterm_ev = event_new(base, SIGTERM, EV_SIGNAL, sigterm_cb, NULL);
sigquit_ev = event_new(base, SIGQUIT, EV_SIGNAL | EV_PERSIST, sigquit_cb, NULL);
+ sigquit_ev = event_new(base, SIGHUP, EV_SIGNAL | EV_PERSIST, sighup_cb, NULL);
sigchld_ev = event_new(base, SIGCHLD, EV_SIGNAL | EV_PERSIST, sigchld_cb, NULL);
timer_ev = event_new(base, -1, EV_PERSIST, timer_cb, NULL);
sigdelset(&blocksigs, SIGTERM);
sigdelset(&blocksigs, SIGQUIT);
sigdelset(&blocksigs, SIGCHLD);
+ sigdelset(&blocksigs, SIGHUP);
sigprocmask(SIG_SETMASK, &blocksigs, NULL);
/* run the event loop */
* echo off means password.
*/
static int PAM_conv (int num_msg,
+#ifdef LINUX
const struct pam_message **msg,
+#else
+ struct pam_message **msg,
+#endif
struct pam_response **resp,
void *appdata_ptr _U_) {
int count = 0;
if (uam_register(UAM_SERVER_CHANGEPW, path, "DHX2", dhx2_changepw) < 0)
return -1;
- p = gcry_mpi_new(0);
- g = gcry_mpi_new(0);
-
LOG(log_debug, logtype_uams, "DHX2: generating mersenne primes");
/* Generate p and g for DH */
if (dh_params_generate(PRIMEBITS) != 0) {
uam_unregister(UAM_SERVER_LOGIN, "DHX2");
uam_unregister(UAM_SERVER_CHANGEPW, "DHX2");
+ LOG(log_debug, logtype_uams, "DHX2: uam_cleanup");
+
gcry_mpi_release(p);
gcry_mpi_release(g);
}
/*
- * $Id: uams_dhx2_passwd.c,v 1.8 2010-03-30 10:25:49 franklahm Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* Copyright (c) 1999 Adrian Sun (asun@u.washington.edu)
/*
- * $Id: uams_dhx_pam.c,v 1.33 2010-03-30 10:25:49 franklahm Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* Copyright (c) 1999 Adrian Sun (asun@u.washington.edu)
* echo off means password.
*/
static int PAM_conv (int num_msg,
+#ifdef LINUX
const struct pam_message **msg,
+#else
+ struct pam_message **msg,
+#endif
struct pam_response **resp,
void *appdata_ptr _U_) {
int count = 0;
DH *dh;
/* get the client's public key */
- if (!(bn = BN_bin2bn(ibuf, KEYSIZE, NULL))) {
+ if (!(bn = BN_bin2bn((unsigned char *)ibuf, KEYSIZE, NULL))) {
/* Log Entry */
LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM No Public Key -- %s",
strerror(errno));
}
/* figure out the key. store the key in rbuf for now. */
- i = DH_compute_key(rbuf, bn, dh);
+ i = DH_compute_key((unsigned char *)rbuf, bn, dh);
/* set the key */
- CAST_set_key(&castkey, i, rbuf);
+ CAST_set_key(&castkey, i, (unsigned char *)rbuf);
/* session id. it's just a hashed version of the object pointer. */
sessid = dhxhash(obj);
*rbuflen += sizeof(sessid);
/* public key */
- BN_bn2bin(dh->pub_key, rbuf);
+ BN_bn2bin(dh->pub_key, (unsigned char *)rbuf);
rbuf += KEYSIZE;
*rbuflen += KEYSIZE;
#endif /* 0 */
/* encrypt using cast */
- CAST_cbc_encrypt(rbuf, rbuf, CRYPTBUFLEN, &castkey, msg2_iv,
+ CAST_cbc_encrypt((unsigned char *)rbuf, (unsigned char *)rbuf, CRYPTBUFLEN, &castkey, msg2_iv,
CAST_ENCRYPT);
*rbuflen += CRYPTBUFLEN;
BN_free(bn);
hostname = NULL;
}
- CAST_cbc_encrypt(ibuf, rbuf, CRYPT2BUFLEN, &castkey,
+ CAST_cbc_encrypt((unsigned char *)ibuf, (unsigned char *)rbuf, CRYPT2BUFLEN, &castkey,
msg3_iv, CAST_DECRYPT);
memset(&castkey, 0, sizeof(castkey));
/* check to make sure that the random number is the same. we
* get sent back an incremented random number. */
- if (!(bn1 = BN_bin2bn(rbuf, KEYSIZE, NULL)))
+ if (!(bn1 = BN_bin2bn((unsigned char *)rbuf, KEYSIZE, NULL)))
return AFPERR_PARAM;
if (!(bn2 = BN_bin2bn(randbuf, sizeof(randbuf), NULL))) {
}
/* grab the client's nonce, old password, and new password. */
- CAST_cbc_encrypt(ibuf, ibuf, CHANGEPWBUFLEN, &castkey,
+ CAST_cbc_encrypt((unsigned char *)ibuf, (unsigned char *)ibuf, CHANGEPWBUFLEN, &castkey,
msg3_iv, CAST_DECRYPT);
memset(&castkey, 0, sizeof(castkey));
/* check to make sure that the random number is the same. we
* get sent back an incremented random number. */
- if (!(bn1 = BN_bin2bn(ibuf, KEYSIZE, NULL))) {
+ if (!(bn1 = BN_bin2bn((unsigned char *)ibuf, KEYSIZE, NULL))) {
/* Log Entry */
LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM: Random Number Not the same or not incremented-- %s",
strerror(errno));
cleanup_client_name:
gss_release_name(&status, &client_name);
-
-cleanup_context:
gss_release_buffer(&status, &authenticator_buff);
gss_delete_sec_context(&status, &context, NULL);
/*
- * $Id: uams_guest.c,v 1.18 2009-11-08 01:07:17 didg Exp $
*
* (c) 2001 (see COPYING)
*/
/*
- * $Id: uams_pam.c,v 1.24 2010-03-30 10:25:49 franklahm Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* Copyright (c) 1999 Adrian Sun (asun@u.washington.edu)
* echo off means password.
*/
static int PAM_conv (int num_msg,
+#ifdef LINUX
const struct pam_message **msg,
+#else
+ struct pam_message **msg,
+#endif
struct pam_response **resp,
void *appdata_ptr _U_)
{
/*
- * $Id: uams_pgp.c,v 1.12 2009-10-15 11:39:48 didg Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* Copyright (c) 1999 Adrian Sun (asun@u.washington.edu)
/*
- * $Id: uams_randnum.c,v 1.21 2010-03-30 10:25:49 franklahm Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* Copyright (c) 1999 Adrian Sun (asun@u.washington.edu)
#ifdef HAVE_ACLS
+#define O_NETATALK_ACL (O_NOFOLLOW << 1)
+
#ifdef HAVE_SOLARIS_ACLS
#include <sys/acl.h>
#else /* HAVE_ACLS=no */
+#define O_NETATALK_ACL 0
#define chmod_acl chmod
#endif /* HAVE_ACLS */
#define ADVOL_NODEV (1 << 0)
#define ADVOL_UNIXPRIV (1 << 2) /* adouble unix priv */
#define ADVOL_INVDOTS (1 << 3) /* dot files (.DS_Store) are invisible) */
+#define ADVOL_FOLLO_SYML (1 << 4)
/* lock flags */
#define ADLOCK_CLR (0)
#define ad_ref(ad) (ad)->ad_refcount++
#define ad_unref(ad) --((ad)->ad_refcount)
+#define ad_get_syml_opt(ad) (((ad)->ad_options & ADVOL_FOLLO_SYML) ? 0 : O_NOFOLLOW)
+
/* ad_flush.c */
extern int ad_rebuild_adouble_header_v2(struct adouble *);
extern int ad_rebuild_adouble_header_ea(struct adouble *);
const char *, size_t, cnid_t);
int (*cnid_find) (struct _cnid_db *cdb, const char *name, size_t namelen,
void *buffer, size_t buflen);
+ int (*cnid_wipe) (struct _cnid_db *cdb);
};
typedef struct _cnid_db cnid_db;
char *name, const size_t len, cnid_t hint);
int cnid_find (struct _cnid_db *cdb, const char *name, size_t namelen,
void *buffer, size_t buflen);
+int cnid_wipe (struct _cnid_db *cdb);
void cnid_close (struct _cnid_db *db);
#endif
#define CNID_DBD_OP_GETSTAMP 0x0b
#define CNID_DBD_OP_REBUILD_ADD 0x0c
#define CNID_DBD_OP_SEARCH 0x0d
+#define CNID_DBD_OP_WIPE 0x0e
#define CNID_DBD_RES_OK 0x00
#define CNID_DBD_RES_NOTFOUND 0x01
@file dictionary.h
@author N. Devillard
@date Sep 2007
- @version $Revision: 1.12 $
@brief Implements a dictionary for string variables.
This module implements a simple dictionary object, i.e. a list
/*--------------------------------------------------------------------------*/
/*
- $Id: dictionary.h,v 1.12 2007-11-23 21:37:00 ndevilla Exp $
$Author: ndevilla $
$Date: 2007-11-23 21:37:00 $
- $Revision: 1.12 $
*/
#ifndef _DICTIONARY_H_
extern DSI *dsi_init(AFPObj *obj, const char *hostname, const char *address, const char *port);
extern void dsi_setstatus (DSI *, char *, const size_t);
extern int dsi_tcp_init(DSI *dsi, const char *hostname, const char *address, const char *port);
+extern void dsi_free(DSI *dsi);
/* in dsi_getsess.c */
extern int dsi_getsession (DSI *, server_child *, const int, afp_child_t **);
#define EC_INIT int ret = 0
#define EC_STATUS(a) ret = (a)
+#define EC_EXIT_STATUS(a) do { ret = (a); goto cleanup; } while (0)
#define EC_FAIL do { ret = -1; goto cleanup; } while (0)
#define EC_FAIL_LOG(a, ...) \
do { \
#define FCE_DIR_DELETE 3
#define FCE_FILE_CREATE 4
#define FCE_DIR_CREATE 5
-#define FCE_TM_SIZE 6
#define FCE_CONN_START 42
#define FCE_CONN_BROKEN 99
+#define FCE_FIRST_EVENT FCE_FILE_MODIFY /* keep in sync with last file event above */
+#define FCE_LAST_EVENT FCE_DIR_CREATE /* keep in sync with last file event above */
/* fce_packet.fce_magic */
#define FCE_PACKET_MAGIC "at_fcapi"
* Format is network byte order.
*/
#define FCE_PACKET_HEADER_SIZE 8+1+1+4+2
+
struct fce_packet
{
char magic[8];
char data[MAXPATHLEN];
};
+typedef uint32_t fce_ev_t;
+typedef enum { fce_file, fce_dir } fce_obj_t;
+
struct path;
struct ofork;
void fce_pending_events(AFPObj *obj);
-
-int fce_register_delete_file( struct path *path );
-int fce_register_delete_dir( char *name );
-int fce_register_new_dir( struct path *path );
-int fce_register_new_file( struct path *path );
-int fce_register_file_modification( struct ofork *ofork );
-int fce_register_tm_size(const char *vol, size_t used);
-
+int fce_register(fce_ev_t event, const char *path, const char *oldpath, fce_obj_t type);
int fce_add_udp_socket(const char *target ); // IP or IP:Port
int fce_set_coalesce(const char *coalesce_opt ); // all|delete|create
-int fce_set_events(const char *events); /* fmod,fdel,ddel,fcre,dcre,tmsz (default is all except tmsz) */
+int fce_set_events(const char *events); /* fmod,fdel,ddel,fcre,dcre */
#define FCE_DEFAULT_PORT 12250
#define FCE_DEFAULT_PORT_STRING "12250"
char *uampath, *fqdn;
char *sigconffile;
char *uuidconf;
- char *guest, *loginmesg, *keyfile, *passwdfile;
+ char *guest, *loginmesg, *keyfile, *passwdfile, *extmapfile;
char *uamlist;
char *signatureopt;
unsigned char signature[16];
gid_t admingid;
int volnamelen;
/* default value for winbind authentication */
- char *ntdomain, *ntseparator;
+ char *ntdomain, *ntseparator, *addomain;
char *logconfig;
char *logfile;
char *mimicmodel;
extern int get_afp_errno (const int param);
extern void afp_options_init (struct afp_options *);
extern void afp_options_parse_cmdline(AFPObj *obj, int ac, char **av);
-extern void afp_options_free(struct afp_options *);
extern void setmessage (const char *);
extern void readmessage (AFPObj *);
-/* gettok.c */
-extern void initline (int, char *);
-extern int parseline (int, char *);
-
/* afp_util.c */
extern const char *AfpNum2name (int );
extern const char *AfpErr2name(int err);
* into proprietary software; there is no requirement for such software to
* contain a copyright notice related to this source.
*
- * $Id: hash.h,v 1.2 2009-11-19 10:37:44 franklahm Exp $
* $Name: $
*/
/*--------------------------------------------------------------------------*/
/*
- $Id: iniparser.h,v 1.26 2011-03-02 20:15:13 ndevilla Exp $
- $Revision: 1.26 $
*/
#ifndef _INIPARSER_H_
/* One function does the whole job */
extern int acl_ldap_readconfig(dictionary *iniconfig);
+extern void acl_ldap_freeconfig(void);
/* These are the prefvalues */
extern char *ldap_server;
int strorint; /* string to just store in char * or convert to int ? */
int intfromarray; /* convert to int, but use string to int mapping array pref_array[] */
int valid; /* -1 = mandatory, 0 = omittable/valid */
+ int valid_save; /* copy of 'valid', used when resettting config */
};
struct pref_array {
logtype_cnid,
logtype_afpd,
logtype_dsi,
- logtype_atalkd,
- logtype_papd,
logtype_uams,
+ logtype_fce,
+ logtype_ad,
logtype_end_of_list_marker /* don't put any logtypes after this */
};
#include <atalk/volume.h>
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, void (*delvol_fn)(const AFPObj *obj, struct vol *));
+extern int load_volumes(AFPObj *obj);
extern void unload_volumes(AFPObj *obj);
extern struct vol *getvolumes(void);
extern struct vol *getvolbyvid(const uint16_t);
extern struct vol *getvolbyname(const char *name);
extern void volume_free(struct vol *vol);
extern void volume_unlink(struct vol *volume);
+
+/* Extension type/creator mapping */
+struct extmap *getdefextmap(void);
+struct extmap *getextmap(const char *path);
+
#endif
#define CONV_DECOMPOSE (1<<7) /* precompose */
#define CONV_FORCE (1<<8) /* force convertion */
#define CONV__EILSEQ (1<<9) /* ignore EILSEQ, replace with IGNORE_CHAR (try USC2) */
-#define CONV_ALLOW_COLON (1<<10) /* Allow ':' in name. Needed for Extended Attributes */
-#define CONV_ALLOW_SLASH (1<<11) /* Allow '/' in name. Needed for volume name */
/* conversion return flags */
#define CONV_REQMANGLE (1<<14) /* mangling of returned name is required */
/* from charcnv.c */
extern int set_charset_name(charset_t, const char *);
+extern void free_charset_names(void);
extern void init_iconv (void);
extern size_t convert_string (charset_t, charset_t, void const *, size_t, void *, size_t);
extern size_t convert_string_allocate (charset_t, charset_t, void const *, size_t, char **);
#define NETATALK_DIOSZ_STACK 65536
#define NETATALK_DIOSZ_HEAP (1024*1024)
+struct vol;
+
/* vfs/unix.c */
extern int netatalk_unlink(const char *name);
extern int netatalk_unlinkat(int dirfd, const char *name);
extern int statat(int dirfd, const char *path, struct stat *st);
-extern int lstatat(int dirfd, const char *path, struct stat *st);
extern DIR *opendirat(int dirfd, const char *path);
/* rmdir ENOENT not an error */
extern int netatalk_rmdir(int dirfd, const char *name);
extern int netatalk_rmdir_all_errors(int dirfd, const char *name);
-extern int setfilmode(const char *, mode_t, struct stat *, mode_t);
+extern int setfilmode(const struct vol *vol, const char *name, mode_t mode, struct stat *st);
extern int dir_rx_set(mode_t mode);
extern int unix_rename(int sfd, const char *oldpath, int dfd, const char *newpath);
extern int copy_file(int sfd, const char *src, const char *dst, mode_t mode);
#include <sys/socket.h>
#include <unistd.h>
#include <poll.h>
+#include <sys/stat.h>
#include <atalk/unicode.h>
#include <atalk/bstrlib.h>
extern const char *getcwdpath(void);
extern const char *fullpathname(const char *);
extern char *stripped_slashes_basename(char *p);
-extern int lchdir(const char *dir);
extern void randombytes(void *buf, int n);
extern int daemonize(int nochdir, int noclose);
extern int run_cmd(const char *cmd, char **cmd_argv);
+extern char *realpath_safe(const char *path);
+extern const char *basename_safe(const char *path);
+extern char *strtok_quote (char *s, const char *delim);
+
+extern int ochdir(const char *dir, int options);
+extern int ostat(const char *path, struct stat *buf, int options);
+extern int ostatat(int dirfd, const char *path, struct stat *st, int options);
+extern int ochown(const char *path, uid_t owner, gid_t group, int options);
+extern int ochmod(char *path, mode_t mode, const struct stat *st, int options);
/******************************************************************
* cnid.c
extern bstring rel_path_in_vol(const char *path, const char *volpath);
+/******************************************************************
+ * cnid.c
+ *****************************************************************/
+
+extern void initline (int, char *);
+extern int parseline (int, char *);
+
#endif /* _ATALK_UTIL_H */
typedef uint64_t VolSpace;
+/* This should belong in a file.h */
+struct extmap {
+ char *em_ext;
+ char em_creator[4];
+ char em_type[4];
+};
+
struct vol {
struct vol *v_next;
AFPObj *v_obj;
#define AFPVOL_ACLS (1 << 24) /* Volume supports ACLS */
#define AFPVOL_SEARCHDB (1 << 25) /* Use fast CNID db search instead of filesystem */
#define AFPVOL_NONETIDS (1 << 26) /* signal the client it shall do privelege mapping */
+#define AFPVOL_FOLLOWSYM (1 << 27) /* follow symlinks on the server, default is not to */
/* Extended Attributes vfs indirection */
#define AFPVOL_EA_NONE 0 /* No EAs */
#define vol_nodev(vol) (((vol)->v_flags & AFPVOL_NODEV) ? 1 : 0)
#define vol_unix_priv(vol) ((vol)->v_obj->afp_version >= 30 && ((vol)->v_flags & AFPVOL_UNIX_PRIV))
#define vol_inv_dots(vol) (((vol)->v_flags & AFPVOL_INV_DOTS) ? 1 : 0)
-
+#define vol_syml_opt(vol) (((vol)->v_flags & AFPVOL_FOLLOWSYM) ? 0 : O_NOFOLLOW)
#endif
# current+1:0:0
#
-VERSION_INFO = 2:0:0
+VERSION_INFO = 3:0:0
# History: VERSION_INFO
#
# 3.0.0-beta2 1:0:0
# 3.0 1:0:0
# 3.0.1 2:0:0
+# 3.0.2 3:0:0
SUBDIRS = acl adouble bstring compat cnid dsi iniparser tdb util unicode vfs
libatalk_la_SOURCES = dummy.c
+libatalk_la_CFLAGS = \
+ @PTHREAD_CFLAGS@
+
libatalk_la_LIBADD = \
- @WRAP_LIBS@ @ACL_LIBS@ \
+ @WRAP_LIBS@ @ACL_LIBS@ @PTHREAD_LIBS@ \
acl/libacl.la \
adouble/libadouble.la \
bstring/libbstring.la \
EXTRA_DIST = \
libatalk-3.0beta1.abi \
libatalk-3.0beta2.abi \
+ libatalk-3.0.abi \
libatalk-3.0.1.abi \
- libatalk-3.0.abi
+ libatalk-3.0.2.abi
libacl_la_SOURCES = cache.c unix.c uuid.c
libacl_la_CFLAGS =
libacl_la_LDFLAGS =
-libacl_la_LIBADD =
+libacl_la_LIBADD = @ACL_LIBS@
if HAVE_LDAP
libacl_la_SOURCES += ldap.c ldap_config.c
void uuidcache_dump(void) {
int i;
- int ret = 0;
cacheduser_t *entry;
char timestr[200];
struct tm *tmp = NULL;
char *name = NULL;
unsigned char *uuid = NULL;
cacheduser_t *cacheduser = NULL;
- cacheduser_t *entry;
unsigned char hash;
/* allocate mem and copy values */
/*
- $Id: cache.h,v 1.1 2009-02-02 11:55:01 franklahm Exp $
Copyright (c) 2008,2009 Frank Lahm <franklahm@gmail.com>
This program is free software; you can redistribute it and/or modify
#include <sys/time.h>
#include <string.h>
#include <errno.h>
+#include <ctype.h>
#define LDAP_DEPRECATED 1
#include <ldap.h>
int ldap_uuid_encoding;
struct ldap_pref ldap_prefs[] = {
- {&ldap_server, "ldap server", 0, 0, -1},
- {&ldap_auth_method,"ldap auth method", 1, 1, -1},
- {&ldap_auth_dn, "ldap auth dn", 0, 0, 0},
- {&ldap_auth_pw, "ldap auth pw", 0, 0, 0},
- {&ldap_userbase, "ldap userbase", 0, 0, -1},
- {&ldap_userscope, "ldap userscope", 1 ,1, -1},
- {&ldap_groupbase, "ldap groupbase", 0, 0, -1},
- {&ldap_groupscope, "ldap groupscope", 1 ,1, -1},
- {&ldap_uuid_attr, "ldap uuid attr", 0, 0, -1},
- {&ldap_uuid_string,"ldap uuid string", 0, 0, 0},
- {&ldap_name_attr, "ldap name attr", 0, 0, -1},
- {&ldap_group_attr, "ldap group attr", 0, 0, -1},
- {&ldap_uid_attr, "ldap uid attr", 0, 0, 0},
- {&ldap_uuid_encoding,"ldap uuid encoding", 1, 1, 0},
- {NULL, NULL, 0, 0, -1}
+ /* pointer to pref, prefname, strorint, intfromarray, valid, valid_save */
+ {&ldap_server, "ldap server", 0, 0, -1, -1},
+ {&ldap_auth_method, "ldap auth method", 1, 1, -1, -1},
+ {&ldap_auth_dn, "ldap auth dn", 0, 0, 0, 0},
+ {&ldap_auth_pw, "ldap auth pw", 0, 0, 0, 0},
+ {&ldap_userbase, "ldap userbase", 0, 0, -1, -1},
+ {&ldap_userscope, "ldap userscope", 1 ,1, -1, -1},
+ {&ldap_groupbase, "ldap groupbase", 0, 0, -1, -1},
+ {&ldap_groupscope, "ldap groupscope", 1 ,1, -1, -1},
+ {&ldap_uuid_attr, "ldap uuid attr", 0, 0, -1, -1},
+ {&ldap_uuid_string, "ldap uuid string", 0, 0, 0, 0},
+ {&ldap_name_attr, "ldap name attr", 0, 0, -1, -1},
+ {&ldap_group_attr, "ldap group attr", 0, 0, -1, -1},
+ {&ldap_uid_attr, "ldap uid attr", 0, 0, 0, 0},
+ {&ldap_uuid_encoding, "ldap uuid encoding", 1, 1, 0, 0},
+ {NULL, NULL, 0, 0, 0, 0}
};
struct pref_array prefs_array[] = {
int i = 0;
int s = 0;
char c;
- while(c = uuidstr[i]) {
+ while ((c = uuidstr[i])) {
if((c >='a' && c <= 'f')
|| (c >= 'A' && c <= 'F')
|| (c >= '0' && c <= '9')) {
#include <atalk/logger.h>
#include <atalk/iniparser.h>
+void acl_ldap_freeconfig(void)
+{
+ for (int i = 0; ldap_prefs[i].name != NULL; i++) {
+ if (ldap_prefs[i].intfromarray == 0 && ldap_prefs[i].strorint == 0) {
+ free(*((char **)(ldap_prefs[i].pref)));
+ *((char **)(ldap_prefs[i].pref)) = NULL;
+ }
+ ldap_prefs[i].valid = ldap_prefs[i].valid_save;
+ }
+}
+
int acl_ldap_readconfig(dictionary *iniconfig)
{
int i, j;
add_cachebyname(name, uuid, mytype, 0);
}
-cleanup:
#ifdef HAVE_LDAP
if (uuid_string) free(uuid_string);
#endif
}
/* ----------------------------- */
-uint32_t ad_getid (struct adouble *adp, const dev_t st_dev, const ino_t st_ino , const cnid_t did, const void *stamp)
+uint32_t ad_getid (struct adouble *adp, const dev_t st_dev, const ino_t st_ino , const cnid_t did, const void *stamp _U_)
{
uint32_t aint = 0;
dev_t dev;
ino_t ino;
cnid_t a_did;
- char temp[ADEDLEN_PRIVSYN];
if (adp) {
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) ) {
+ && (!did || a_did == did) ) {
memcpy(&aint, ad_entry(adp, ADEID_PRIVID), sizeof(aint));
if (adp->ad_vers == AD_VERSION2)
return aint;
EC_INIT;
struct adouble adv2;
struct adouble adea;
- const char *adpath;
int adflags;
uint32_t ctime, mtime, afpinfo = 0;
char *emptyad;
- LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): BEGIN", fullpathname(path));
+ LOG(log_debug, logtype_ad,"ad_conv_v22ea_hf(\"%s\"): BEGIN", fullpathname(path));
+
+ switch (S_IFMT & sp->st_mode) {
+ case S_IFREG:
+ break;
+ default:
+ return 0;
+ }
ad_init(&adea, vol);
ad_init_old(&adv2, AD_VERSION2, adea.ad_options);
+
adflags = S_ISDIR(sp->st_mode) ? ADFLAGS_DIR : 0;
/* Open and lock adouble:v2 file */
goto copy;
}
- LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): default adouble", fullpathname(path), ret);
+ LOG(log_debug, logtype_ad,"ad_conv_v22ea_hf(\"%s\"): default adouble", fullpathname(path), ret);
goto EC_CLEANUP;
copy:
/* Create a adouble:ea meta EA */
- LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): copying adouble", fullpathname(path), ret);
+ LOG(log_debug, logtype_ad,"ad_conv_v22ea_hf(\"%s\"): copying adouble", fullpathname(path), ret);
EC_ZERO_LOGSTR( ad_open(&adea, path, adflags | ADFLAGS_HF | ADFLAGS_RDWR | ADFLAGS_CREATE),
"ad_conv_v22ea_hf(\"%s\"): error creating metadata EA: %s",
fullpathname(path), strerror(errno));
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);
+ LOG(log_debug, logtype_ad,"ad_conv_v22ea_hf(\"%s\"): END: %d", fullpathname(path), ret);
EC_EXIT;
}
struct adouble adv2;
struct adouble adea;
- LOG(log_debug, logtype_default,"ad_conv_v22ea_rf(\"%s\"): BEGIN", fullpathname(path));
+ LOG(log_debug, logtype_ad,"ad_conv_v22ea_rf(\"%s\"): BEGIN", fullpathname(path));
+
+ switch (S_IFMT & sp->st_mode) {
+ case S_IFREG:
+ break;
+ default:
+ return 0;
+ }
if (S_ISDIR(sp->st_mode))
return 0;
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);
+ LOG(log_debug, logtype_ad,"ad_conv_v22ea_rf(\"%s\"): END: %d", fullpathname(path), ret);
EC_EXIT;
}
become_root();
- EC_ZERO( ad_conv_v22ea_hf(path, sp, vol) );
- EC_ZERO( ad_conv_v22ea_rf(path, sp, vol) );
+ if (ad_conv_v22ea_hf(path, sp, vol) != 0)
+ goto delete;
+ if (ad_conv_v22ea_rf(path, sp, vol) != 0)
+ goto delete;
+delete:
EC_NULL( adpath = ad_path(path, adflags) );
- LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): deleting adouble:v2 file: \"%s\"",
+ LOG(log_debug, logtype_ad,"ad_conv_v22ea_hf(\"%s\"): deleting adouble:v2 file: \"%s\"",
path, fullpathname(adpath));
unlink(adpath);
{
EC_INIT;
static char buf[MAXPATHLEN];
- const char *adpath, *p;
+ const char *p;
int adflags = S_ISDIR(sp->st_mode) ? ADFLAGS_DIR : 0;
bstring newpath = NULL;
- LOG(log_debug, logtype_default,"ad_conv_dehex(\"%s\"): BEGIN", fullpathname(path));
+ LOG(log_debug, logtype_ad,"ad_conv_dehex(\"%s\"): BEGIN", fullpathname(path));
*newpathp = NULL;
EC_INIT;
const char *p;
- LOG(log_debug, logtype_default,"ad_convert(\"%s\"): BEGIN", fullpathname(path));
+ LOG(log_debug, logtype_ad,"ad_convert(\"%s\"): BEGIN", fullpathname(path));
if (newpath)
*newpath = NULL;
}
EC_CLEANUP:
- LOG(log_debug, logtype_default,"ad_convert(\"%s\"): END: %d", fullpathname(path), ret);
+ LOG(log_debug, logtype_ad,"ad_convert(\"%s\"): END: %d", fullpathname(path), ret);
EC_EXIT;
}
uint32_t temp;
uint16_t nent;
char *buf, *nentp;
- int len;
- LOG(log_debug, logtype_default, "ad_rebuild_adouble_header_v2");
+ LOG(log_debug, logtype_ad, "ad_rebuild_adouble_header_v2");
buf = ad->ad_data;
uint32_t temp;
uint16_t nent;
char *buf, *nentp;
- int len;
- LOG(log_debug, logtype_default, "ad_rebuild_adouble_header_ea");
+ LOG(log_debug, logtype_ad, "ad_rebuild_adouble_header_ea");
buf = ad->ad_data;
uint32_t temp;
uint16_t nent;
char *buf;
- int len;
- LOG(log_debug, logtype_default, "ad_rebuild_adouble_header_osx");
+ LOG(log_debug, logtype_ad, "ad_rebuild_adouble_header_osx");
buf = &adbuf[0];
memcpy(buf, &temp, sizeof( temp ));
buf += sizeof( temp );
- memset(buf, 0, sizeof(ad->ad_filler));
+ memcpy(buf, "Netatalk ", 16);
buf += sizeof( ad->ad_filler );
nent = htons(ADEID_NUM_OSX);
}
add->ad_rlen = ads->ad_rlen;
- if ((ads->ad_vers == AD_VERSION2) && (add->ad_vers = AD_VERSION_EA)
- || (ads->ad_vers == AD_VERSION_EA) && (add->ad_vers = AD_VERSION2)) {
+ if (((ads->ad_vers == AD_VERSION2) && (add->ad_vers == AD_VERSION_EA))
+ || ((ads->ad_vers == AD_VERSION_EA) && (add->ad_vers == AD_VERSION2))) {
cnid_t id;
memcpy(&id, ad_entry(add, ADEID_PRIVID), sizeof(cnid_t));
id = htonl(id);
int len;
int cwd = -1;
- LOG(log_debug, logtype_default, "ad_flush_hf(%s)", adflags2logstr(ad->ad_adflags));
+ LOG(log_debug, logtype_ad, "ad_flush_hf(%s)", adflags2logstr(ad->ad_adflags));
struct ad_fd *adf;
adf = &ad->ad_data_fork;
break;
default:
- LOG(log_error, logtype_afpd, "ad_flush: unexpected adouble version");
+ LOG(log_error, logtype_ad, "ad_flush: unexpected adouble version");
return -1;
}
if (ad->ad_adflags & ADFLAGS_DIR) {
EC_NEG1_LOG( cwd = open(".", O_RDONLY) );
EC_NEG1_LOG( fchdir(ad_data_fileno(ad)) );
- EC_ZERO_LOG( sys_lsetxattr(".", AD_EA_META, ad->ad_data, AD_DATASZ_EA, 0) );
+ EC_ZERO_LOGSTR( sys_lsetxattr(".", AD_EA_META, ad->ad_data, AD_DATASZ_EA, 0),
+ "sys_lsetxattr(\"%s\"): %s", fullpathname(".") ,strerror(errno));
EC_NEG1_LOG( fchdir(cwd) );
EC_NEG1_LOG( close(cwd) );
cwd = -1;
}
break;
default:
- LOG(log_error, logtype_afpd, "ad_flush: unexpected adouble version");
+ LOG(log_error, logtype_ad, "ad_flush: unexpected adouble version");
return -1;
}
}
if (ad->ad_vers != AD_VERSION_EA)
return 0;
- LOG(log_debug, logtype_default, "ad_flush_rf(%s)", adflags2logstr(ad->ad_adflags));
+ LOG(log_debug, logtype_ad, "ad_flush_rf(%s)", adflags2logstr(ad->ad_adflags));
if ((ad->ad_rfp->adf_flags & O_RDWR)) {
if (ad_getentryoff(ad, ADEID_RFORK)) {
{
EC_INIT;
- LOG(log_debug, logtype_default, "ad_flush(%s)", adflags2logstr(ad->ad_adflags));
+ LOG(log_debug, logtype_ad, "ad_flush(%s)", adflags2logstr(ad->ad_adflags));
if (AD_META_OPEN(ad)) {
EC_ZERO( ad_flush_hf(ad) );
return err;
- LOG(log_debug, logtype_default,
+ LOG(log_debug, logtype_ad,
"ad_close(%s): BEGIN: {d: %d, m: %d, r: %d} "
"[dfd: %d (ref: %d), mfd: %d (ref: %d), rfd: %d (ref: %d)]",
adflags2logstr(adflags),
if ((adflags & ADFLAGS_DF) && (ad_data_fileno(ad) >= 0 || ad_data_fileno(ad) == AD_SYMLINK)) {
if (ad->ad_data_refcount)
- ad->ad_data_refcount--;
+ if (--ad->ad_data_refcount == 0)
+ adf_lock_free(&ad->ad_data_fork);
if (--ad->ad_data_fork.adf_refcount == 0) {
if (ad_data_closefd(ad) < 0)
err = -1;
- adf_lock_free(&ad->ad_data_fork);
}
}
if (close( ad_meta_fileno(ad)) < 0)
err = -1;
ad_meta_fileno(ad) = -1;
- if (ad->ad_vers == AD_VERSION2)
- adf_lock_free(ad->ad_mdp);
}
}
if (adflags & ADFLAGS_RF) {
if (ad->ad_reso_refcount)
- ad->ad_reso_refcount--;
+ if (--ad->ad_reso_refcount == 0)
+ adf_lock_free(ad->ad_rfp);
if (ad->ad_vers == AD_VERSION_EA) {
if ((ad_reso_fileno(ad) != -1)
&& !(--ad->ad_rfp->adf_refcount)) {
err = -1;
ad->ad_rlen = 0;
ad_reso_fileno(ad) = -1;
- adf_lock_free(ad->ad_rfp);
}
}
}
- LOG(log_debug, logtype_default,
+ LOG(log_debug, logtype_ad,
"ad_close(%s): END: %d {d: %d, m: %d, r: %d} "
"[dfd: %d (ref: %d), mfd: %d (ref: %d), rfd: %d (ref: %d)]",
adflags2logstr(adflags), err,
{
EC_INIT;
- LOG(log_debug, logtype_default, "set_lock(fd: %d, %s, %s, off: %jd (%s), len: %jd): BEGIN",
+ LOG(log_debug, logtype_ad, "set_lock(fd: %d, %s, %s, off: %jd (%s), len: %jd): BEGIN",
fd, cmd == F_SETLK ? "F_SETLK" : "F_GETLK",
lock->l_type == F_RDLCK ? "F_RDLCK" : lock->l_type == F_WRLCK ? "F_WRLCK" : "F_UNLCK",
(intmax_t)lock->l_start,
int type;
int ret = 0, fcntl_lock_err = 0;
- LOG(log_debug, logtype_default, "ad_lock(%s, %s, off: %jd (%s), len: %jd): BEGIN",
+ LOG(log_debug, logtype_ad, "ad_lock(%s, %s, off: %jd (%s), len: %jd): BEGIN",
eid == ADEID_DFORK ? "data" : "reso",
locktypetostr(locktype),
(intmax_t)off,
set_lock(adf->adf_fd, F_SETLK, &lock);
}
}
- LOG(log_debug, logtype_default, "ad_lock: END: %d", ret);
+ LOG(log_debug, logtype_ad, "ad_lock: END: %d", ret);
return ret;
}
int err;
int type;
- LOG(log_debug, logtype_default, "ad_tmplock(%s, %s, off: %jd (%s), len: %jd): BEGIN",
+ LOG(log_debug, logtype_ad, "ad_tmplock(%s, %s, off: %jd (%s), len: %jd): BEGIN",
eid == ADEID_DFORK ? "data" : "reso",
locktypetostr(locktype),
(intmax_t)off,
adf_relockrange(adf, adf->adf_fd, lock.l_start, len);
exit:
- LOG(log_debug, logtype_default, "ad_tmplock: END: %d", err);
+ LOG(log_debug, logtype_ad, "ad_tmplock: END: %d", err);
return err;
}
/* --------------------- */
void ad_unlock(struct adouble *ad, const int fork, int unlckbrl)
{
- LOG(log_debug, logtype_default, "ad_unlock(unlckbrl: %d): BEGIN", unlckbrl);
+ LOG(log_debug, logtype_ad, "ad_unlock(unlckbrl: %d): BEGIN", unlckbrl);
if (ad_data_fileno(ad) != -1) {
adf_unlock(ad, &ad->ad_data_fork, fork, unlckbrl);
adf_unlock(ad, &ad->ad_resource_fork, fork, unlckbrl);
}
- LOG(log_debug, logtype_default, "ad_unlock: END");
+ LOG(log_debug, logtype_ad, "ad_unlock: END");
}
/*!
int ret = 0;
off_t lock_offset;
- LOG(log_debug, logtype_default, "ad_testlock(%s, off: %jd (%s): BEGIN",
+ LOG(log_debug, logtype_ad, "ad_testlock(%s, off: %jd (%s): BEGIN",
eid == ADEID_DFORK ? "data" : "reso",
(intmax_t)off,
shmdstrfromoff(off));
ret = testlock(&ad->ad_data_fork, lock_offset, 1);
- LOG(log_debug, logtype_default, "ad_testlock: END: %d", ret);
+ LOG(log_debug, logtype_ad, "ad_testlock: END: %d", ret);
return ret;
}
uint16_t ad_openforks(struct adouble *ad, uint16_t attrbits)
{
uint16_t ret = 0;
- struct ad_fd *adf;
off_t off;
off_t len;
static int ad_header_read(const char *path, struct adouble *ad, const struct stat *hst);
static int ad_header_upgrade(struct adouble *ad, const char *name);
+#ifdef HAVE_EAFD
static int ad_mkrf_ea(const char *path);
+#endif
static int ad_header_read_ea(const char *path, struct adouble *ad, const struct stat *hst);
static int ad_header_upgrade_ea(struct adouble *ad, const char *name);
static int ad_reso_size(const char *path, int adflags, struct adouble *ad);
uint16_t ashort;
struct stat st;
- LOG(log_debug, logtype_default, "new_ad_header(\"%s\")", path);
+ LOG(log_debug, logtype_ad, "new_ad_header(\"%s\")", path);
if (ad->ad_magic == AD_MAGIC) {
- LOG(log_debug, logtype_default, "new_ad_header(\"%s\"): already initialized", path);
+ LOG(log_debug, logtype_ad, "new_ad_header(\"%s\"): already initialized", path);
return 0;
}
ad->ad_eid[ eid ].ade_len = len;
} else if (!warning) {
warning = 1;
- LOG(log_warning, logtype_default, "parse_entries: bogus eid: %d", eid);
+ LOG(log_warning, logtype_ad, "parse_entries: bogus eid: %d", eid);
}
}
}
ad->ad_version = ntohl( ad->ad_version );
if ((ad->ad_magic != AD_MAGIC) || (ad->ad_version != AD_VERSION2)) {
- LOG(log_error, logtype_default, "ad_open: can't parse AppleDouble header.");
+ LOG(log_error, logtype_ad, "ad_open: can't parse AppleDouble header.");
errno = EIO;
return -1;
}
buf += AD_HEADER_LEN;
if (len > header_len - AD_HEADER_LEN) {
- LOG(log_error, logtype_default, "ad_header_read: can't read entry info.");
+ LOG(log_error, logtype_ad, "ad_header_read: can't read entry info.");
errno = EIO;
return -1;
}
if (!ad_getentryoff(ad, ADEID_RFORK)
|| (ad_getentryoff(ad, ADEID_RFORK) > sizeof(ad->ad_data))
) {
- LOG(log_error, logtype_default, "ad_header_read: problem with rfork entry offset.");
+ LOG(log_error, logtype_ad, "ad_header_read: problem with rfork entry offset.");
errno = EIO;
return -1;
}
if (ad_getentryoff(ad, ADEID_RFORK) > header_len) {
- LOG(log_error, logtype_default, "ad_header_read: can't read in entries.");
+ LOG(log_error, logtype_ad, "ad_header_read: can't read in entries.");
errno = EIO;
return -1;
}
char *buf = &adosx.ad_data[0];
ssize_t header_len;
- LOG(log_debug, logtype_afpd, "ad_valid_header_osx(\"%s\"): BEGIN", fullpathname(path));
+ LOG(log_debug, logtype_ad, "ad_valid_header_osx(\"%s\"): BEGIN", fullpathname(path));
EC_NEG1( fd = open(path, O_RDONLY) );
adosx.ad_version = ntohl(adosx.ad_version);
if ((adosx.ad_magic != AD_MAGIC) || (adosx.ad_version != AD_VERSION2)) {
- LOG(log_error, logtype_afpd, "ad_valid_header_osx: not an adouble:ox file");
+ LOG(log_warning, logtype_ad, "ad_valid_header_osx: not an adouble:osx file");
EC_FAIL;
}
+ if (strncmp(buf + ADEDOFF_FILLER, "Mac OS X", strlen("Mac OS X")) == 0)
+ /*
+ * It's a split fork created by OS X, it's not our "own" ._ file
+ * and thus not a valid header in this context.
+ * We allow enumeration and access.
+ */
+ EC_FAIL;
+
EC_CLEANUP:
- LOG(log_debug, logtype_afpd, "ad_valid_header_osx(\"%s\"): END: %d", fullpathname(path), ret);
+ LOG(log_debug, logtype_ad, "ad_valid_header_osx(\"%s\"): END: %d", fullpathname(path), ret);
if (fd != -1)
close(fd);
if (ret != 0)
adosx.ad_version = ntohl(adosx.ad_version);
if ((adosx.ad_magic != AD_MAGIC) || (adosx.ad_version != AD_VERSION2)) {
- LOG(log_error, logtype_afpd, "ad_header_read_osx: can't parse AppleDouble header");
+ LOG(log_error, logtype_ad, "ad_header_read_osx: can't parse AppleDouble header");
errno = EIO;
return -1;
}
buf += AD_HEADER_LEN;
if (len > header_len - AD_HEADER_LEN) {
- LOG(log_error, logtype_afpd, "ad_header_read_osx: can't read entry info.");
+ LOG(log_error, logtype_ad, "ad_header_read_osx: can't read entry info.");
errno = EIO;
return -1;
}
|| ad_getentryoff(&adosx, ADEID_RFORK) > sizeof(ad->ad_data)
|| ad_getentryoff(&adosx, ADEID_RFORK) > header_len
) {
- LOG(log_error, logtype_afpd, "ad_header_read_osx: problem with rfork entry offset.");
+ LOG(log_error, logtype_ad, "ad_header_read_osx: problem with rfork entry offset.");
errno = EIO;
return -1;
}
else
header_len = sys_lgetxattr(path, AD_EA_META, ad->ad_data, AD_DATASZ_EA);
if (header_len < 1) {
- LOG(log_debug, logtype_default, "ad_header_read_ea: %s", strerror(errno));
+ LOG(log_debug, logtype_ad, "ad_header_read_ea: %s", strerror(errno));
return -1;
}
if (header_len < AD_HEADER_LEN) {
- LOG(log_error, logtype_default, "ad_header_read_ea: bogus AppleDouble header.");
+ LOG(log_error, logtype_ad, "ad_header_read_ea: bogus AppleDouble header.");
errno = EIO;
return -1;
}
ad->ad_version = ntohl( ad->ad_version );
if ((ad->ad_magic != AD_MAGIC) || (ad->ad_version != AD_VERSION2)) {
- LOG(log_error, logtype_default, "ad_header_read_ea: wrong magic or version");
+ LOG(log_error, logtype_ad, "ad_header_read_ea: wrong magic or version");
errno = EIO;
return -1;
}
if (len + AD_HEADER_LEN > sizeof(ad->ad_data))
len = sizeof(ad->ad_data) - AD_HEADER_LEN;
if (len > header_len - AD_HEADER_LEN) {
- LOG(log_error, logtype_default, "ad_header_read_ea: can't read entry info.");
+ LOG(log_error, logtype_ad, "ad_header_read_ea: can't read entry info.");
errno = EIO;
return -1;
}
return 0;
}
+#ifdef HAVE_EAFD
static int ad_mkrf_ea(const char *path _U_)
{
AFP_PANIC("ad_mkrf_ea: dont use");
return 0;
}
+#endif
static int ad_mkrf_osx(const char *path _U_)
{
if (adflags & ADFLAGS_TRUNC)
oflags |= O_TRUNC;
+ if (!(ad->ad_options & ADVOL_FOLLO_SYML))
+ oflags |= O_NOFOLLOW;
+
return oflags;
}
int st_invalid = -1;
ssize_t lsz;
- LOG(log_debug, logtype_default,
+ LOG(log_debug, logtype_ad,
"ad_open_df(\"%s\", %s): BEGIN [dfd: %d (ref: %d), mfd: %d (ref: %d), rfd: %d (ref: %d)]",
fullpathname(path), adflags2logstr(adflags),
ad_data_fileno(ad), ad->ad_data_fork.adf_refcount,
goto EC_CLEANUP;
}
- oflags = O_NOFOLLOW | ad2openflags(ad, ADFLAGS_DF, adflags);
+ oflags = ad2openflags(ad, ADFLAGS_DF, adflags);
admode = mode;
if ((adflags & ADFLAGS_CREATE)) {
ad->ad_data_fork.adf_refcount++;
EC_CLEANUP:
- LOG(log_debug, logtype_default,
+ LOG(log_debug, logtype_ad,
"ad_open_df(\"%s\", %s): END: %d [dfd: %d (ref: %d), mfd: %d (ref: %d), rfd: %d (ref: %d)]",
fullpathname(path), adflags2logstr(adflags), ret,
ad_data_fileno(ad), ad->ad_data_fork.adf_refcount,
mode_t admode;
int st_invalid = -1;
- LOG(log_debug, logtype_default,
+ LOG(log_debug, logtype_ad,
"ad_open_hf_v2(\"%s\", %s): BEGIN [dfd: %d (ref: %d), mfd: %d (ref: %d), rfd: %d (ref: %d)]",
fullpathname(path), adflags2logstr(adflags),
ad_data_fileno(ad), ad->ad_data_fork.adf_refcount,
}
ad_p = ad->ad_ops->ad_path(path, adflags);
- oflags = O_NOFOLLOW | ad2openflags(ad, ADFLAGS_HF, adflags);
- LOG(log_debug, logtype_default,"ad_open_hf_v2(\"%s\"): open flags: %s",
+ oflags = ad2openflags(ad, ADFLAGS_HF, adflags);
+ LOG(log_debug, logtype_ad,"ad_open_hf_v2(\"%s\"): open flags: %s",
fullpathname(path), openflags2logstr(oflags));
nocreatflags = oflags & ~(O_CREAT | O_EXCL);
/*
* We're expecting to create a new adouble header file here
*/
- LOG(log_debug, logtype_default, "ad_open(\"%s\"): creating adouble file",
+ LOG(log_debug, logtype_ad, "ad_open(\"%s\"): creating adouble file",
fullpathname(path));
admode = mode;
errno = 0;
ad_meta_fileno(ad) = -1;
ad->ad_mdp->adf_refcount = 0;
}
- LOG(log_debug, logtype_default,
+ LOG(log_debug, logtype_ad,
"ad_open_hf_v2(\"%s\", %s): END: %d [dfd: %d (ref: %d), mfd: %d (ref: %d), rfd: %d (ref: %d)]",
fullpathname(path), adflags2logstr(adflags), ret,
ad_data_fileno(ad), ad->ad_data_fork.adf_refcount,
static int ad_open_hf_ea(const char *path, int adflags, int mode, struct adouble *ad)
{
EC_INIT;
- ssize_t rforklen;
int oflags;
int opened = 0;
- LOG(log_debug, logtype_default,
+ LOG(log_debug, logtype_ad,
"ad_open_hf_ea(\"%s\", %s): BEGIN [dfd: %d (ref: %d), mfd: %d (ref: %d), rfd: %d (ref: %d)]",
fullpathname(path), adflags2logstr(adflags),
ad_data_fileno(ad), ad->ad_data_fork.adf_refcount,
ad_meta_fileno(ad), ad->ad_mdp->adf_refcount,
ad_reso_fileno(ad), ad->ad_rfp->adf_refcount);
- oflags = O_NOFOLLOW | (ad2openflags(ad, ADFLAGS_DF, adflags) & ~(O_CREAT | O_TRUNC));
+ oflags = ad2openflags(ad, ADFLAGS_DF, adflags) & ~(O_CREAT | O_TRUNC);
if (ad_meta_fileno(ad) == AD_SYMLINK)
goto EC_CLEANUP;
if ((oflags & O_RDWR) &&
/* and it was already denied: */
(ad->ad_mdp->adf_flags & O_RDONLY)) {
- LOG(log_error, logtype_default, "ad_open_hf_ea(%s): rw request for ro file: %s",
+ LOG(log_error, logtype_ad, "ad_open_hf_ea(%s): rw request for ro file: %s",
fullpathname(path), strerror(errno));
errno = EACCES;
EC_FAIL;
if (adflags & ADFLAGS_DIR)
/* For directories we open the directory RDONYL so we can later fchdir() */
oflags = (oflags & ~O_RDWR) | O_RDONLY;
- LOG(log_debug, logtype_default, "ad_open_hf_ea(\"%s\"): opening base file for meta adouble EA", path);
+ LOG(log_debug, logtype_ad, "ad_open_hf_ea(\"%s\"): opening base file for meta adouble EA", path);
EC_NEG1(ad_meta_fileno(ad) = open(path, oflags));
opened = 1;
ad->ad_mdp->adf_flags = oflags;
/* Read the adouble header in and parse it.*/
if (ad->ad_ops->ad_header_read(path, ad, NULL) != 0) {
if (!(adflags & ADFLAGS_CREATE)) {
- LOG(log_debug, logtype_default, "ad_open_hf_ea(\"%s\"): can't read metadata EA", path);
+ LOG(log_debug, logtype_ad, "ad_open_hf_ea(\"%s\"): can't read metadata EA", path);
errno = ENOENT;
EC_FAIL;
}
- LOG(log_debug, logtype_default, "ad_open_hf_ea(\"%s\"): creating metadata EA", path);
+ LOG(log_debug, logtype_ad, "ad_open_hf_ea(\"%s\"): creating metadata EA", path);
/* It doesnt exist, EPERM or another error */
if (!(errno == ENOATTR || errno == ENOENT)) {
- LOG(log_error, logtype_default, "ad_open_hf_ea: unexpected: %s", strerror(errno));
+ LOG(log_error, logtype_ad, "ad_open_hf_ea: unexpected: %s", strerror(errno));
EC_FAIL;
}
EC_NEG1_LOG(new_ad_header(ad, path, NULL, adflags));
ad->ad_mdp->adf_flags |= O_CREAT; /* mark as just created */
ad_flush(ad);
- LOG(log_debug, logtype_default, "ad_open_hf_ea(\"%s\"): created metadata EA", path);
+ LOG(log_debug, logtype_ad, "ad_open_hf_ea(\"%s\"): created metadata EA", path);
}
if (ad_meta_fileno(ad) != -1)
ad_meta_fileno(ad) = -1;
ad->ad_mdp->adf_refcount = 0;
}
- LOG(log_debug, logtype_default,
+ LOG(log_debug, logtype_ad,
"ad_open_hf_ea(\"%s\", %s): END: %d [dfd: %d (ref: %d), mfd: %d (ref: %d), rfd: %d (ref: %d)]",
fullpathname(path), adflags2logstr(adflags), ret,
ad_data_fileno(ad), ad->ad_data_fork.adf_refcount,
break;
}
- if (ret != 0)
+ if (ret == 0)
+ ad->ad_meta_refcount++;
+ else
ret = ad_error(ad, adflags);
return ret;
goto EC_CLEANUP;
}
- LOG(log_debug, logtype_default, "ad_reso_size(\"%s\"): BEGIN", path);
+ LOG(log_debug, logtype_ad, "ad_reso_size(\"%s\"): BEGIN", path);
#ifdef HAVE_EAFD
ssize_t easz;
ad->ad_rlen = 0;
#endif
- LOG(log_debug, logtype_default, "ad_reso_size(\"%s\"): size: %zd", path, ad->ad_rlen);
+ LOG(log_debug, logtype_ad, "ad_reso_size(\"%s\"): size: %zd", path, ad->ad_rlen);
EC_CLEANUP:
if (ret != 0)
static int ad_open_rf_v2(const char *path, int adflags, int mode, struct adouble *ad)
{
+ EC_INIT;
+
/*
* ad_open_hf_v2() does the work, but if it failed and adflags are ADFLAGS_NOHF | ADFLAGS_RF
* ad_open_hf_v2() didn't give an error, but we're supposed to return a reso fork fd
*/
- if (!AD_RSRC_OPEN(ad) && !(adflags & ADFLAGS_NORF))
- return -1;
- return 0;
+
+ LOG(log_debug, logtype_ad, "ad_open_rf_v2(\"%s\"): BEGIN", fullpathname(path));
+
+ if (!AD_META_OPEN(ad) && !(adflags & ADFLAGS_NORF))
+ EC_FAIL;
+ if (AD_META_OPEN(ad))
+ ad->ad_reso_refcount++;
+
+EC_CLEANUP:
+ LOG(log_debug, logtype_ad, "ad_open_rf_v2(\"%s\"): END: %d", fullpathname(path), ret);
+ EC_EXIT;
}
static int ad_open_rf_ea(const char *path, int adflags, int mode, struct adouble *ad)
int oflags;
int opened = 0;
int closeflags = adflags & (ADFLAGS_DF | ADFLAGS_HF);
- ssize_t rlen;
#ifndef HAVE_EAFD
const char *rfpath;
struct stat st;
#endif
- LOG(log_debug, logtype_default, "ad_open_rf(\"%s\"): BEGIN", fullpathname(path));
+ LOG(log_debug, logtype_ad, "ad_open_rf(\"%s\"): BEGIN", fullpathname(path));
- oflags = O_NOFOLLOW | (ad2openflags(ad, ADFLAGS_RF, adflags) & ~O_CREAT);
+ oflags = ad2openflags(ad, ADFLAGS_RF, adflags) & ~O_CREAT;
if (ad_reso_fileno(ad) != -1) {
/* the file is already open, but we want write access: */
EC_FAIL;
oflags |= O_CREAT;
EC_NEG1_LOG( ad_reso_fileno(ad) = open(rfpath, oflags, mode) );
- LOG(log_debug, logtype_default, "ad_open_rf(\"%s\"): created adouble rfork: \"%s\"",
+ LOG(log_debug, logtype_ad, "ad_open_rf(\"%s\"): created adouble rfork: \"%s\"",
path, rfpath);
}
#endif
opened = 1;
ad->ad_rfp->adf_refcount = 1;
ad->ad_rfp->adf_flags = oflags;
+ ad->ad_reso_refcount++;
#ifndef HAVE_EAFD
EC_ZERO_LOG( fstat(ad_reso_fileno(ad), &st) );
if (ad->ad_rfp->adf_flags & O_CREAT) {
/* This is a new adouble header file, create it */
- LOG(log_debug, logtype_default, "ad_open_rf(\"%s\"): created adouble rfork, initializing: \"%s\"",
+ LOG(log_debug, logtype_ad, "ad_open_rf(\"%s\"): created adouble rfork, initializing: \"%s\"",
path, rfpath);
EC_NEG1_LOG( new_ad_header(ad, path, NULL, adflags) );
- LOG(log_debug, logtype_default, "ad_open_rf(\"%s\"): created adouble rfork, flushing: \"%s\"",
+ LOG(log_debug, logtype_ad, "ad_open_rf(\"%s\"): created adouble rfork, flushing: \"%s\"",
path, rfpath);
ad_flush(ad);
} else {
/* Read the adouble header */
- LOG(log_debug, logtype_default, "ad_open_rf(\"%s\"): reading adouble rfork: \"%s\"",
+ LOG(log_debug, logtype_ad, "ad_open_rf(\"%s\"): reading adouble rfork: \"%s\"",
path, rfpath);
EC_NEG1_LOG( ad_header_read_osx(NULL, ad, &st) );
}
if (opened && (ad_reso_fileno(ad) != -1)) {
close(ad_reso_fileno(ad));
ad_reso_fileno(ad) = -1;
+ ad->ad_reso_refcount--;
ad->ad_rfp->adf_refcount = 0;
}
if (adflags & ADFLAGS_NORF) {
ad->ad_rlen = 0;
}
- LOG(log_debug, logtype_default, "ad_open_rf(\"%s\"): END: %d", fullpathname(path), ret);
+ LOG(log_debug, logtype_ad, "ad_open_rf(\"%s\"): END: %d", fullpathname(path), ret);
EC_EXIT;
}
p = ad_dir(path);
if (!p)
return -1;
- return lstat( p, stbuf );
+ return stat( p, stbuf );
}
/* ----------------
int st_invalid;
struct stat stbuf;
- LOG(log_debug, logtype_default, "ad_mkdir(\"%s\", %04o) {cwd: \"%s\"}",
+ LOG(log_debug, logtype_ad, "ad_mkdir(\"%s\", %04o) {cwd: \"%s\"}",
path, mode, getcwdpath());
st_invalid = ad_mode_st(path, &mode, &stbuf);
va_list args;
mode_t mode = 0;
- LOG(log_debug, logtype_default,
+ LOG(log_debug, logtype_ad,
"ad_open(\"%s\", %s): BEGIN {d: %d, m: %d, r: %d}"
"[dfd: %d (ref: %d), mfd: %d (ref: %d), rfd: %d (ref: %d)]",
fullpathname(path), adflags2logstr(adflags),
}
if (adflags & ADFLAGS_HF) {
- ad->ad_meta_refcount++;
if (ad_open_hf(path, adflags, mode, ad) != 0) {
- ad->ad_meta_refcount--;
EC_FAIL;
}
}
if (adflags & ADFLAGS_RF) {
- ad->ad_reso_refcount++;
if (ad_open_rf(path, adflags, mode, ad) != 0) {
- ad->ad_reso_refcount--;
EC_FAIL;
}
}
}
EC_CLEANUP:
- LOG(log_debug, logtype_default,
+ LOG(log_debug, logtype_ad,
"ad_open(\"%s\"): END: %d {d: %d, m: %d, r: %d}"
"[dfd: %d (ref: %d), mfd: %d (ref: %d), rfd: %d (ref: %d)]",
fullpathname(path), ret,
if (dirfd != -1) {
if (fchdir(cwdfd) != 0) {
- LOG(log_error, logtype_afpd, "ad_openat: cant chdir back, exiting");
+ LOG(log_error, logtype_ad, "ad_openat: cant chdir back, exiting");
exit(EXITERR_SYS);
}
}
ssize_t ad_read( struct adouble *ad, const uint32_t eid, off_t off, char *buf, const size_t buflen)
{
ssize_t cc;
- ssize_t rlen;
off_t r_off = 0;
/* We're either reading the data fork (and thus the data file)
/*
- * $Id: ad_size.c,v 1.8 2010-02-26 14:13:16 didg Exp $
*
* Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
* All rights reserved. See COPYRIGHT.
EC_INIT;
struct stat st;
ssize_t cc;
- size_t roundup;
off_t r_off;
if (ad_data_fileno(ad) == AD_SYMLINK) {
return -1;
}
- LOG(log_debug, logtype_default, "ad_write: off: %ju, size: %zu, eabuflen: %zu",
+ LOG(log_debug, logtype_ad, "ad_write: off: %ju, size: %zu, eabuflen: %zu",
(uintmax_t)off, buflen, ad->ad_rlen);
if ( eid == ADEID_DFORK ) {
return -1; /* we don't know how to write if it's not a ressource or data fork */
}
-EC_CLEANUP:
if (ret != 0)
return ret;
return( cc );
if (ret == 0)
ad->ad_rlen = size;
else
- LOG(log_error, logtype_default, "ad_rtruncate(\"%s\"): %s",
+ LOG(log_error, logtype_ad, "ad_rtruncate(\"%s\"): %s",
fullpathname(ad->ad_name), strerror(errno));
EC_EXIT;
}
int ad_dtruncate(struct adouble *ad, const off_t size)
{
if (sys_ftruncate(ad_data_fileno(ad), size) < 0) {
- LOG(log_error, logtype_default, "sys_ftruncate(fd: %d): %s",
+ LOG(log_error, logtype_ad, "sys_ftruncate(fd: %d): %s",
ad_data_fileno(ad), strerror(errno));
return -1;
}
/*
- $Id: bstradd.c,v 1.1.2.1 2010-02-01 10:56:08 franklahm Exp $
Copyright (c) 2010 Frank Lahm <franklahm@gmail.com>
This program is free software; you can redistribute it and/or modify
*/
bstring brefcstr (char *str) {
bstring b;
- int i;
size_t j;
if (str == NULL)
b->slen = (int) j;
b->mlen = -1;
- b->data = str;
+ b->data = (unsigned char *)str;
return b;
}
/*
- * $Id: cnid_cdb_close.c,v 1.2 2005-04-28 20:49:59 bfernhomberg Exp $
*/
#ifdef HAVE_CONFIG_H
/*
- * $Id: cnid_cdb_delete.c,v 1.4 2009-10-29 13:38:16 didg Exp $
*
* Copyright (c) 1999. Adrian Sun (asun@zoology.washington.edu)
* All Rights Reserved. See COPYRIGHT.
/*
- * $Id: cnid_cdb_meta.c,v 1.2 2005-04-28 20:49:59 bfernhomberg Exp $
*
* Copyright (c) 1999. Adrian Sun (asun@zoology.washington.edu)
* All Rights Reserved. See COPYRIGHT.
/*
- * $Id: cnid_cdb_meta.h,v 1.2 2005-04-28 20:49:59 bfernhomberg Exp $
*/
#define CNID_META_CNID_LEN 4
/*
- * $Id: cnid_cdb_nextid.c,v 1.2 2005-04-28 20:49:59 bfernhomberg Exp $
*/
#ifdef HAVE_CONFIG_H
cdb->cnid_close = cnid_cdb_close;
cdb->cnid_getstamp = cnid_cdb_getstamp;
cdb->cnid_rebuild_add = cnid_cdb_rebuild_add;
-
+ cdb->cnid_wipe = NULL;
return cdb;
}
/*
- * $Id: cnid_cdb_rebuild_add.c,v 1.6 2009-11-20 17:22:11 didg Exp $
*
* All Rights Reserved. See COPYRIGHT.
*
/*
- * $Id: cnid_cdb_resolve.c,v 1.5 2009-10-29 13:38:16 didg Exp $
*/
#ifdef HAVE_CONFIG_H
unblock_signal(cdb->flags);
return ret;
}
+
+/* --------------- */
+int cnid_wipe(struct _cnid_db *cdb)
+{
+ int ret = 0;
+
+ block_signal(cdb->flags);
+ if (cdb->cnid_wipe)
+ ret = cdb->cnid_wipe(cdb);
+ unblock_signal(cdb->flags);
+ return ret;
+}
/*
- * $Id: cnid_init.c,v 1.3 2009-10-13 22:55:37 didg Exp $
*
* Copyright (c) 2003 the Netatalk Team
* Copyright (c) 2003 Rafal Lewczuk <rlewczuk@pronet.pl>
time_t orig, t;
int clean = 1; /* no errors so far - to prevent sleep on first try */
- if (db->changed) {
- /* volume and db don't have the same timestamp
- */
- return -1;
- }
while (1) {
if (db->fd == -1) {
- struct cnid_dbd_rqst rqst_stamp;
- struct cnid_dbd_rply rply_stamp;
- char stamp[ADEDLEN_PRIVSYN];
-
LOG(log_maxdebug, logtype_cnid, "transmit: connecting to cnid_dbd ...");
if ((db->fd = init_tsock(db)) < 0) {
goto transmit_fail;
}
- dbd_initstamp(&rqst_stamp);
- memset(stamp, 0, ADEDLEN_PRIVSYN);
- rply_stamp.name = stamp;
- rply_stamp.namelen = ADEDLEN_PRIVSYN;
-
- if (dbd_rpc(db, &rqst_stamp, &rply_stamp) < 0)
- goto transmit_fail;
- if (dbd_reply_stamp(&rply_stamp ) < 0)
- goto transmit_fail;
-
if (db->notfirst) {
- LOG(log_debug7, logtype_cnid, "transmit: reconnected to cnid_dbd, comparing database stamps...");
- if (memcmp(stamp, db->stamp, ADEDLEN_PRIVSYN)) {
- LOG(log_error, logtype_cnid, "transmit: ... not the same db!");
- db->changed = 1;
- return -1;
- }
- LOG(log_debug7, logtype_cnid, "transmit: ... OK.");
+ LOG(log_debug7, logtype_cnid, "transmit: reconnected to cnid_dbd");
} else { /* db->notfirst == 0 */
db->notfirst = 1;
- if (db->client_stamp)
- memcpy(db->client_stamp, stamp, ADEDLEN_PRIVSYN);
- memcpy(db->stamp, stamp, ADEDLEN_PRIVSYN);
}
- LOG(log_debug, logtype_cnid, "transmit: attached to '%s', stamp: '%08lx'.",
- db->db_dir, *(uint64_t *)stamp);
+ LOG(log_debug, logtype_cnid, "transmit: attached to '%s'", db->db_dir);
}
if (!dbd_rpc(db, rqst, rply)) {
LOG(log_maxdebug, logtype_cnid, "transmit: {done}");
cdb->cnid_update = cnid_dbd_update;
cdb->cnid_rebuild_add = cnid_dbd_rebuild_add;
cdb->cnid_close = cnid_dbd_close;
-
+ cdb->cnid_wipe = cnid_dbd_wipe;
return cdb;
}
return;
}
+/**
+ * Get the db stamp
+ **/
+static int cnid_dbd_stamp(CNID_private *db)
+{
+ struct cnid_dbd_rqst rqst_stamp;
+ struct cnid_dbd_rply rply_stamp;
+ char stamp[ADEDLEN_PRIVSYN];
+
+ dbd_initstamp(&rqst_stamp);
+ memset(stamp, 0, ADEDLEN_PRIVSYN);
+ rply_stamp.name = stamp;
+ rply_stamp.namelen = ADEDLEN_PRIVSYN;
+
+ if (transmit(db, &rqst_stamp, &rply_stamp) < 0)
+ return -1;
+ if (dbd_reply_stamp(&rply_stamp ) < 0)
+ return -1;
+
+ if (db->client_stamp)
+ memcpy(db->client_stamp, stamp, ADEDLEN_PRIVSYN);
+ memcpy(db->stamp, stamp, ADEDLEN_PRIVSYN);
+
+ return 0;
+}
+
/* ---------------------- */
cnid_t cnid_dbd_add(struct _cnid_db *cdb, const struct stat *st,
cnid_t did, const char *name, size_t len, cnid_t hint)
rqst.name = name;
rqst.namelen = len;
- LOG(log_debug, logtype_cnid, "cnid_dbd_add: CNID: %u, name: '%s', inode: 0x%llx, type: %d (0=file, 1=dir)",
- ntohl(did), name, (long long)st->st_ino, rqst.type);
+ LOG(log_debug, logtype_cnid, "cnid_dbd_add: CNID: %u, name: '%s', dev: 0x%llx, inode: 0x%llx, type: %s",
+ ntohl(did), name, (long long)rqst.dev, (long long)st->st_ino, rqst.type ? "dir" : "file");
rply.namelen = 0;
if (transmit(db, &rqst, &rply) < 0) {
return name;
}
-/* ---------------------- */
+/**
+ * Caller passes buffer where we will store the db stamp
+ **/
int cnid_dbd_getstamp(struct _cnid_db *cdb, void *buffer, const size_t len)
{
CNID_private *db;
}
db->client_stamp = buffer;
db->stamp_size = len;
- memset(buffer,0, len);
- return 0;
+
+ return cnid_dbd_stamp(db);
}
/* ---------------------- */
}
}
+int cnid_dbd_wipe(struct _cnid_db *cdb)
+{
+ CNID_private *db;
+ struct cnid_dbd_rqst rqst;
+ struct cnid_dbd_rply rply;
+
+ if (!cdb || !(db = cdb->_private)) {
+ LOG(log_error, logtype_cnid, "cnid_wipe: Parameter error");
+ errno = CNID_ERR_PARAM;
+ return -1;
+ }
+
+ LOG(log_debug, logtype_cnid, "cnid_dbd_wipe");
+
+ RQST_RESET(&rqst);
+ rqst.op = CNID_DBD_OP_WIPE;
+ rqst.cnid = 0;
+
+ rply.namelen = 0;
+ if (transmit(db, &rqst, &rply) < 0) {
+ errno = CNID_ERR_DB;
+ return -1;
+ }
+
+ if (rply.result != CNID_DBD_RES_OK) {
+ errno = CNID_ERR_DB;
+ return -1;
+ }
+ LOG(log_debug, logtype_cnid, "cnid_dbd_wipe: ok");
+
+ return cnid_dbd_stamp(db);
+}
+
struct _cnid_module cnid_dbd_module = {
"dbd",
extern int cnid_dbd_delete (struct _cnid_db *, const cnid_t);
extern cnid_t cnid_dbd_rebuild_add(struct _cnid_db *, const struct stat *,
cnid_t, const char *, size_t, cnid_t);
-
+extern int cnid_dbd_wipe (struct _cnid_db *cdb);
/* FIXME: These functions could be static in cnid_dbd.c */
#endif /* include/atalk/cnid_dbd.h */
/*
- * $Id: cnid_last.c,v 1.5 2010-03-31 09:47:32 franklahm Exp $
*
* Copyright (c) 1999. Adrian Sun (asun@zoology.washington.edu)
* All Rights Reserved. See COPYRIGHT.
cdb->cnid_resolve = cnid_last_resolve;
cdb->cnid_update = cnid_last_update;
cdb->cnid_close = cnid_last_close;
-
+ cdb->cnid_wipe = NULL;
+
return cdb;
}
}
/* did/name database */
- altkey.dptr = (char *) data->dptr +CNID_DID_OFS;
+ altkey.dptr = data->dptr +CNID_DID_OFS;
altkey.dsize = data->dsize -CNID_DID_OFS;
if (tdb_store(db->tdb_didname, altkey, altdata, TDB_REPLACE)) {
goto abort;
memset(&rootinfo_key, 0, sizeof(rootinfo_key));
memset(&data, 0, sizeof(data));
- rootinfo_key.dptr = ROOTINFO_KEY;
+ rootinfo_key.dptr = (unsigned char *)ROOTINFO_KEY;
rootinfo_key.dsize = ROOTINFO_KEYLEN;
tdb_chainlock(db->tdb_didname, rootinfo_key);
}
memset(&data, 0, sizeof(data));
- data.dptr = (char *)&hint;
+ data.dptr = (unsigned char *)&hint;
data.dsize = sizeof(hint);
if (tdb_store(db->tdb_didname, rootinfo_key, data, TDB_REPLACE)) {
goto cleanup;
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
- key.dptr = (char *)&hint;
+ key.dptr = (unsigned char *)&hint;
key.dsize = sizeof(cnid_t);
if ((data.dptr = make_tdb_data(cdb->flags, lstp, did, name, len)) == NULL) {
LOG(log_error, logtype_default, "tdb_add: Path name is too long");
/*
- * $Id: cnid_tdb_close.c,v 1.3 2009-11-21 13:38:11 didg Exp $
*/
#ifdef HAVE_CONFIG_H
/*
- * $Id: cnid_tdb_delete.c,v 1.4 2009-11-20 19:25:05 didg Exp $
*
* Copyright (c) 1999. Adrian Sun (asun@zoology.washington.edu)
* All Rights Reserved. See COPYRIGHT.
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
- key.dptr = (char *)&id;
+ key.dptr = (unsigned char *)&id;
key.dsize = sizeof(cnid_t);
data = tdb_fetch(db->tdb_cnid, key);
if (!data.dptr)
key.dsize = CNID_DEVINO_LEN;
tdb_delete(db->tdb_devino, key);
- key.dptr = (char *)data.dptr +CNID_DID_OFS;
+ key.dptr = data.dptr +CNID_DID_OFS;
key.dsize = data.dsize -CNID_DID_OFS;
tdb_delete(db->tdb_didname, key);
buf += sizeof(did);
memcpy(buf, name, len);
*(buf + len) = '\0'; /* Make it a C-string. */
- key.dptr = start;
+ key.dptr = (unsigned char *)start;
key.dsize = CNID_DID_LEN + len + 1;
data = tdb_fetch(db->tdb_didname, key);
if (!data.dptr)
return 0;
}
- if ((buf = make_tdb_data(cdb->flags, st, did, name, len)) == NULL) {
+ if ((buf = (char *)make_tdb_data(cdb->flags, st, did, name, len)) == NULL) {
LOG(log_error, logtype_default, "tdb_lookup: Pathname is too long");
return 0;
}
memcpy(dev, buf + CNID_DEV_OFS, CNID_DEV_LEN);
memcpy(ino, buf + CNID_INO_OFS, CNID_INO_LEN);
- key.dptr = buf +CNID_DEVINO_OFS;
+ key.dptr = (unsigned char *)buf + CNID_DEVINO_OFS;
key.dsize = CNID_DEVINO_LEN;
cniddata = tdb_fetch(db->tdb_devino, key);
if (!cniddata.dptr) {
}
/* did/name now */
- key.dptr = buf + CNID_DID_OFS;
+ key.dptr = (unsigned char *)buf + CNID_DID_OFS;
key.dsize = CNID_DID_LEN + len + 1;
cniddata = tdb_fetch(db->tdb_didname, key);
if (!cniddata.dptr) {
/*
- * $Id: cnid_tdb_nextid.c,v 1.2 2005-04-28 20:50:02 bfernhomberg Exp $
*/
#ifdef HAVE_CONFIG_H
cdb->cnid_resolve = cnid_tdb_resolve;
cdb->cnid_update = cnid_tdb_update;
cdb->cnid_close = cnid_tdb_close;
-
+ cdb->cnid_wipe = NULL;
+
return cdb;
}
* to change the format in any way. */
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
- key.dptr = DBVERSION_KEY;
+ key.dptr = (unsigned char *)DBVERSION_KEY;
key.dsize = DBVERSION_KEYLEN;
data = tdb_fetch(db->tdb_didname, key);
if (!data.dptr) {
uint32_t version = htonl(DBVERSION);
- data.dptr = (char *)&version;
+ data.dptr = (unsigned char *)&version;
data.dsize = sizeof(version);
if (tdb_store(db->tdb_didname, key, data, TDB_REPLACE)) {
LOG(log_error, logtype_default, "tdb_open: Error putting new version");
/*
- * $Id: cnid_tdb_resolve.c,v 1.4 2009-11-22 14:14:05 franklahm Exp $
*/
#ifdef HAVE_CONFIG_H
if (!cdb || !(db = cdb->_private) || !id || !(*id)) {
return NULL;
}
- key.dptr = (char *)id;
+ key.dptr = (unsigned char *)id;
key.dsize = sizeof(cnid_t);
data = tdb_fetch(db->tdb_cnid, key);
if (data.dptr)
free(altdata.dptr);
if (data.dptr) {
- key.dptr = (char *)data.dptr +CNID_DID_OFS;
+ key.dptr = (unsigned char *)data.dptr +CNID_DID_OFS;
key.dsize = data.dsize - CNID_DID_OFS;
tdb_delete(db->tdb_didname, key);
/* search by did/name */
data.dptr = make_tdb_data(cdb->flags, st, did, name, len);
data.dsize = CNID_HEADER_LEN + len + 1;
- key.dptr = (char *)data.dptr +CNID_DID_OFS;
+ key.dptr = (unsigned char *)data.dptr +CNID_DID_OFS;
key.dsize = data.dsize - CNID_DID_OFS;
altdata = tdb_fetch(db->tdb_didname, key);
if (altdata.dptr) {
memcpy(data.dptr, &id, sizeof(id));
/* Update the old CNID with the new info. */
- key.dptr = (char *) &id;
+ key.dptr = (unsigned char *) &id;
key.dsize = sizeof(id);
if (tdb_store(db->tdb_cnid, key, data, TDB_REPLACE)) {
goto update_err;
/* Put in a new dev/ino mapping. */
key.dptr = data.dptr +CNID_DEVINO_OFS;
key.dsize = CNID_DEVINO_LEN;
- altdata.dptr = (char *) &id;
+ altdata.dptr = (unsigned char *) &id;
altdata.dsize = sizeof(id);
if (tdb_store(db->tdb_devino, key, altdata, TDB_REPLACE)) {
goto update_err;
}
/* put in a new did/name mapping. */
- key.dptr = (char *) data.dptr +CNID_DID_OFS;
+ key.dptr = (unsigned char *) data.dptr +CNID_DID_OFS;
key.dsize = data.dsize -CNID_DID_OFS;
if (tdb_store(db->tdb_didname, key, altdata, TDB_REPLACE)) {
/*
- * $Id: getusershell.c,v 1.4 2003-02-17 01:51:08 srittau Exp $
*
* Copyright (c) 1985 Regents of the University of California.
* All rights reserved.
/*
- * $Id: mktemp.c,v 1.4 2003-02-17 01:51:08 srittau Exp $
*
* Copyright (c) 1987 Regents of the University of California.
* All rights reserved.
/*
- * $Id: rquota_xdr.c,v 1.4 2003-02-17 01:51:08 srittau Exp $
*
* taken from the quota-1.55 used on linux. here's the bsd copyright:
*
/*
- * $Id: dsi_attn.c,v 1.8 2009-10-25 06:13:11 didg Exp $
*
* Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
* All rights reserved. See COPYRIGHT.
/*
- * $Id: dsi_close.c,v 1.4 2003-03-12 15:07:06 didg Exp $
*
* Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
* All rights reserved. See COPYRIGHT.
/*
- * $Id: dsi_getsess.c,v 1.7 2005-04-28 20:50:02 bfernhomberg Exp $
*
* Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
* All rights reserved. See COPYRIGHT.
int dsi_getsession(DSI *dsi, server_child *serv_children, int tickleval, afp_child_t **childp)
{
pid_t pid;
- unsigned int ipc_fds[2];
+ int ipc_fds[2];
afp_child_t *child;
if (socketpair(PF_UNIX, SOCK_STREAM, 0, ipc_fds) < 0) {
/* set up the tickle timer */
dsi->timer.it_interval.tv_sec = dsi->timer.it_value.tv_sec = tickleval;
dsi->timer.it_interval.tv_usec = dsi->timer.it_value.tv_usec = 0;
- signal(SIGPIPE, SIG_IGN); /* we catch these ourselves */
dsi_opensession(dsi);
*childp = NULL;
return 0;
/*
- * $Id: dsi_getstat.c,v 1.4 2005-09-07 15:27:29 didg Exp $
*
* Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
* All rights reserved. See COPYRIGHT.
dsi->end = dsi->buffer + (dsi->dsireadbuf * dsi->server_quantum);
}
+/*!
+ * Free any allocated ressources of the master afpd DSI objects and close server socket
+ */
+void dsi_free(DSI *dsi)
+{
+ close(dsi->serversock);
+ dsi->serversock = -1;
+
+ free(dsi->commands);
+ dsi->commands = NULL;
+
+ free(dsi->buffer);
+ dsi->buffer = NULL;
+
+#ifdef USE_ZEROCONF
+ free(dsi->bonjourname);
+ dsi->bonjourname = NULL;
+#endif
+}
+
static struct itimerval itimer;
/* accept the socket and do a little sanity checking */
-static int dsi_tcp_open(DSI *dsi)
+static pid_t dsi_tcp_open(DSI *dsi)
{
pid_t pid;
SOCKLEN_T len;
/*
- * $Id: dsi_tickle.c,v 1.8 2009-10-25 06:13:11 didg Exp $
*
* Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
* All rights reserved. See COPYRIGHT.
/*
- * $Id: dsi_write.c,v 1.5 2009-10-20 04:31:41 didg Exp $
*
* Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
* All rights reserved. See COPYRIGHT.
@file dictionary.c
@author N. Devillard
@date Sep 2007
- @version $Revision: 1.27 $
@brief Implements a dictionary for string variables.
This module implements a simple dictionary object, i.e. a list
/*--------------------------------------------------------------------------*/
/*
- $Id: dictionary.c,v 1.27 2007-11-23 21:39:18 ndevilla Exp $
- $Revision: 1.27 $
*/
/*---------------------------------------------------------------------------
Includes
---------------------------------------------------------------------------*/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
#include <atalk/dictionary.h>
#include <atalk/compat.h>
*/
/*---------------------------- Includes ------------------------------------*/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
#include <ctype.h>
#include <atalk/iniparser.h>
strcpy(section, strstrip(section));
strcpy(section, section);
sta = LINE_SECTION ;
- } else if (sscanf (line, "%[^=] = \"%[^\"]\"", key, value) == 2
- || sscanf (line, "%[^=] = '%[^\']'", key, value) == 2
+ } else if (sscanf (line, "%[^=] = '%[^\']'", key, value) == 2
|| sscanf (line, "%[^=] = %[^;#]", key, value) == 2) {
/* Usual key=value, with or without comments */
strcpy(key, strstrip(key));
char line [ASCIILINESZ+1] ;
char section [ASCIILINESZ+1] ;
char key [ASCIILINESZ+1] ;
- char tmp [ASCIILINESZ+1] ;
char val [ASCIILINESZ+1] ;
int last=0 ;
len = (int)strlen(line)-1;
if (len==0)
continue;
- /* Safety check against buffer overflows */
- if (line[len]!='\n') {
- LOG(log_error, logtype_default, "iniparser: input line too long in \"%s\" (lineno: %d)",
- ininame, lineno);
- dictionary_del(dict);
- fclose(in);
- return NULL ;
- }
/* Get rid of \n and spaces at end of line */
while ((len>=0) &&
((line[len]=='\n') || (isspace(line[len])))) {
--- /dev/null
+acl_ldap_readconfig: int (dictionary *)
+ad_close: int (struct adouble *, int)
+ad_convert: int (const char *, const struct stat *, const struct vol *, const char **)
+ad_copy_header: int (struct adouble *, struct adouble *)
+add_cachebyname: int (const char *, const uuidp_t, const uuidtype_t, const long unsigned int)
+add_cachebyuuid: int (uuidp_t, const char *, uuidtype_t, const long unsigned int)
+add_charset: charset_t (const char *)
+ad_dir: char *(const char *)
+ad_dtruncate: int (struct adouble *, const off_t)
+adflags2logstr: const char *(int)
+ad_flush: int (struct adouble *)
+ad_forcegetid: uint32_t (struct adouble *)
+adf_pread: ssize_t (struct ad_fd *, void *, size_t, off_t)
+adf_pwrite: ssize_t (struct ad_fd *, const void *, size_t, off_t)
+ad_getattr: int (const struct adouble *, uint16_t *)
+ad_getdate: int (const struct adouble *, unsigned int, uint32_t *)
+ad_getentryoff: off_t (const struct adouble *, int)
+ad_getfuid: uid_t (void)
+ad_getid: uint32_t (struct adouble *, const dev_t, const ino_t, const cnid_t, const void *)
+ad_hf_mode: mode_t (mode_t)
+ad_init: void (struct adouble *, const struct vol *)
+ad_init_old: void (struct adouble *, int, int)
+ad_lock: int (struct adouble *, uint32_t, int, off_t, off_t, int)
+ad_metadata: int (const char *, int, struct adouble *)
+ad_metadataat: int (int, const char *, int, struct adouble *)
+ad_mkdir: int (const char *, mode_t)
+ad_mode: int (const char *, mode_t)
+ad_open: int (struct adouble *, const char *, int, ...)
+ad_openat: int (struct adouble *, int, const char *, int, ...)
+ad_openforks: uint16_t (struct adouble *, uint16_t)
+ad_path: const char *(const char *, int)
+ad_path_ea: const char *(const char *, int)
+ad_path_osx: const char *(const char *, int)
+ad_read: ssize_t (struct adouble *, const uint32_t, off_t, char *, const size_t)
+ad_readfile_init: int (const struct adouble *, const int, off_t *, const int)
+ad_rebuild_adouble_header_ea: int (struct adouble *)
+ad_rebuild_adouble_header_v2: int (struct adouble *)
+ad_refresh: int (const char *, struct adouble *)
+ad_rtruncate: int (struct adouble *, const off_t)
+ad_setattr: int (const struct adouble *, const uint16_t)
+ad_setdate: int (struct adouble *, unsigned int, uint32_t)
+ad_setfuid: int (const uid_t)
+ad_setid: int (struct adouble *, const dev_t, const ino_t, const uint32_t, const cnid_t, const void *)
+ad_setname: int (struct adouble *, const char *)
+ad_size: off_t (const struct adouble *, const uint32_t)
+ad_stat: int (const char *, struct stat *)
+ad_testlock: int (struct adouble *, int, const off_t)
+ad_tmplock: int (struct adouble *, uint32_t, int, off_t, off_t, int)
+ad_unlock: void (struct adouble *, const int, int)
+ad_valid_header_osx: int (const char *)
+ad_write: ssize_t (struct adouble *, uint32_t, off_t, int, const char *, size_t)
+afp_config_parse: int (AFPObj *, char *)
+allow_severity: 5
+apply_ip_mask: void (struct sockaddr *, int)
+atalk_iconv: size_t (atalk_iconv_t, const char **, size_t *, char **, size_t *)
+atalk_iconv_close: int (atalk_iconv_t)
+atalk_iconv_open: atalk_iconv_t (const char *, const char *)
+atalk_register_charset: int (struct charset_functions *)
+balloc: int (bstring, int)
+ballocmin: int (bstring, int)
+bassign: int (bstring, const_bstring)
+bassignblk: int (bstring, const void *, int)
+bassigncstr: int (bstring, const char *)
+bassignformat: int (bstring, const char *, ...)
+bassigngets: int (bstring, bNgetc, void *, char)
+bassignmidstr: int (bstring, const_bstring, int, int)
+bcatblk: int (bstring, const void *, int)
+bcatcstr: int (bstring, const char *)
+bconcat: int (bstring, const_bstring)
+bconchar: int (bstring, char)
+bcstrfree: int (char *)
+bdelete: int (bstring, int, int)
+bdestroy: int (bstring)
+become_root: void (void)
+bfindreplace: int (bstring, const_bstring, const_bstring, int)
+bfindreplacecaseless: int (bstring, const_bstring, const_bstring, int)
+bformat: bstring (const char *, ...)
+bformata: int (bstring, const char *, ...)
+bfromcstr: bstring (const char *)
+bfromcstralloc: bstring (int, const char *)
+bgetsa: int (bstring, bNgetc, void *, char)
+bgetstream: bstring (bNgetc, void *, char)
+binchr: int (const_bstring, int, const_bstring)
+binchrr: int (const_bstring, int, const_bstring)
+binsert: int (bstring, int, const_bstring, unsigned char)
+binsertch: int (bstring, int, int, unsigned char)
+binstr: int (const_bstring, int, const_bstring)
+binstrcaseless: int (const_bstring, int, const_bstring)
+binstrr: int (const_bstring, int, const_bstring)
+binstrrcaseless: int (const_bstring, int, const_bstring)
+biseq: int (const_bstring, const_bstring)
+biseqcaseless: int (const_bstring, const_bstring)
+biseqcstr: int (const_bstring, const char *)
+biseqcstrcaseless: int (const_bstring, const char *)
+bisstemeqblk: int (const_bstring, const void *, int)
+bisstemeqcaselessblk: int (const_bstring, const void *, int)
+bjoin: bstring (const struct bstrList *, const_bstring)
+bjoinInv: bstring (const struct bstrList *, const_bstring)
+blk2bstr: bstring (const void *, int)
+bltrimws: int (bstring)
+bmidstr: bstring (const_bstring, int, int)
+bninchr: int (const_bstring, int, const_bstring)
+bninchrr: int (const_bstring, int, const_bstring)
+bpattern: int (bstring, int)
+bread: bstring (bNread, void *)
+breada: int (bstring, bNread, void *)
+brefcstr: bstring (char *)
+breplace: int (bstring, int, int, const_bstring, unsigned char)
+brtrimws: int (bstring)
+bsbufflength: int (struct bStream *, int)
+bsclose: void *(struct bStream *)
+bseof: int (const struct bStream *)
+bsetstr: int (bstring, int, const_bstring, unsigned char)
+bsopen: struct bStream *(bNread, void *)
+bspeek: int (bstring, const struct bStream *)
+bsplit: struct bstrList *(const_bstring, unsigned char)
+bsplitcb: int (const_bstring, unsigned char, int, int (*)(void *, int, int), void *)
+bsplits: struct bstrList *(const_bstring, const_bstring)
+bsplitscb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *)
+bsplitstr: struct bstrList *(const_bstring, const_bstring)
+bsplitstrcb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *)
+bsread: int (bstring, struct bStream *, int)
+bsreada: int (bstring, struct bStream *, int)
+bsreadln: int (bstring, struct bStream *, char)
+bsreadlna: int (bstring, struct bStream *, char)
+bsreadlns: int (bstring, struct bStream *, const_bstring)
+bsreadlnsa: int (bstring, struct bStream *, const_bstring)
+bssplitscb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *)
+bssplitstrcb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *)
+bstr2cstr: char *(const_bstring, char)
+bstrchrp: int (const_bstring, int, int)
+bstrcmp: int (const_bstring, const_bstring)
+bstrcpy: bstring (const_bstring)
+bstricmp: int (const_bstring, const_bstring)
+bstrListAlloc: int (struct bstrList *, int)
+bstrListAllocMin: int (struct bstrList *, int)
+bstrListCreate: struct bstrList *(void)
+bstrListCreateMin: struct bstrList *(int)
+bstrListDestroy: int (struct bstrList *)
+bstrListPop: bstring (struct bstrList *)
+bstrListPush: int (struct bstrList *, bstring)
+bstrncmp: int (const_bstring, const_bstring, int)
+bstrnicmp: int (const_bstring, const_bstring, int)
+bstrrchrp: int (const_bstring, int, int)
+bsunread: int (struct bStream *, const_bstring)
+btolower: int (bstring)
+btoupper: int (bstring)
+btrimws: int (bstring)
+btrunc: int (bstring, int)
+bunrefcstr: int (bstring)
+bvcformata: int (bstring, int, const char *, struct __va_list_tag *)
+charset_decompose: size_t (charset_t, char *, size_t, char *, size_t)
+charset_mac_centraleurope: {name = "MAC_CENTRALEUROPE", kTextEncoding = 29, pull = <mac_centraleurope_pull>, push = <mac_centraleurope_push>, flags = 17, iname = 0x0, prev = 0x0, next = 0x0}
+charset_mac_chinese_simp: {name = "MAC_CHINESE_SIMP", kTextEncoding = 25, pull = <mac_chinese_simp_pull>, push = <mac_chinese_simp_push>, flags = 85, iname = "EUC-CN", prev = 0x0, next = 0x0}
+charset_mac_chinese_trad: {name = "MAC_CHINESE_TRAD", kTextEncoding = 2, pull = <mac_chinese_trad_pull>, push = <mac_chinese_trad_push>, flags = 85, iname = "BIG-5", prev = 0x0, next = 0x0}
+charset_mac_cyrillic: {name = "MAC_CYRILLIC", kTextEncoding = 7, pull = <mac_cyrillic_pull>, push = <mac_cyrillic_push>, flags = 17, iname = 0x0, prev = 0x0, next = 0x0}
+charset_mac_greek: {name = "MAC_GREEK", kTextEncoding = 6, pull = <mac_greek_pull>, push = <mac_greek_push>, flags = 17, iname = 0x0, prev = 0x0, next = 0x0}
+charset_mac_hebrew: {name = "MAC_HEBREW", kTextEncoding = 5, pull = <mac_hebrew_pull>, push = <mac_hebrew_push>, flags = 17, iname = 0x0, prev = 0x0, next = 0x0}
+charset_mac_japanese: {name = "MAC_JAPANESE", kTextEncoding = 1, pull = <mac_japanese_pull>, push = <mac_japanese_push>, flags = 85, iname = "SHIFT_JIS", prev = 0x0, next = 0x0}
+charset_mac_korean: {name = "MAC_KOREAN", kTextEncoding = 3, pull = <mac_korean_pull>, push = <mac_korean_push>, flags = 85, iname = "EUC-KR", prev = 0x0, next = 0x0}
+charset_mac_roman: {name = "MAC_ROMAN", kTextEncoding = 0, pull = <mac_roman_pull>, push = <mac_roman_push>, flags = 21, iname = 0x0, prev = 0x0, next = 0x0}
+charset_mac_turkish: {name = "MAC_TURKISH", kTextEncoding = 35, pull = <mac_turkish_pull>, push = <mac_turkish_push>, flags = 17, iname = 0x0, prev = 0x0, next = 0x0}
+charset_precompose: size_t (charset_t, char *, size_t, char *, size_t)
+charset_strlower: size_t (charset_t, const char *, size_t, char *, size_t)
+charset_strupper: size_t (charset_t, const char *, size_t, char *, size_t)
+charset_to_ucs2_allocate: size_t (charset_t, uint16_t **, const char *)
+charset_to_utf8_allocate: size_t (charset_t, char **, const char *)
+charset_utf8: {name = "UTF8", kTextEncoding = 134217987, pull = <utf8_pull>, push = <utf8_push>, flags = 22, iname = 0x0, prev = 0x0, next = 0x0}
+charset_utf8_mac: {name = "UTF8-MAC", kTextEncoding = 134217987, pull = <utf8_pull>, push = <utf8_push>, flags = 27, iname = 0x0, prev = 0x0, next = 0x0}
+check_lockfile: int (const char *, const char *)
+cjk_char_pull: size_t (uint16_t, uint16_t *, const uint32_t *)
+cjk_char_push: size_t (uint16_t, uint8_t *)
+cjk_compose: uint16_t (uint16_t, uint16_t, const uint32_t *, size_t)
+cjk_compose_seq: uint16_t (const uint16_t *, size_t *, const uint32_t *, size_t)
+cjk_generic_pull: size_t (size_t (*)(uint16_t *, const uint8_t *, size_t *), void *, char **, size_t *, char **, size_t *)
+cjk_generic_push: size_t (size_t (*)(uint8_t *, const uint16_t *, size_t *), void *, char **, size_t *, char **, size_t *)
+cjk_lookup: uint16_t (uint16_t, const cjk_index_t *, const uint16_t *)
+cnid_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, const char *, const size_t, cnid_t)
+cnid_close: void (struct _cnid_db *)
+cnid_dbd_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t)
+cnid_dbd_close: void (struct _cnid_db *)
+cnid_dbd_delete: int (struct _cnid_db *, const cnid_t)
+cnid_dbd_find: int (struct _cnid_db *, const char *, size_t, void *, size_t)
+cnid_dbd_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t)
+cnid_dbd_getstamp: int (struct _cnid_db *, void *, const size_t)
+cnid_dbd_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t)
+cnid_dbd_module: {name = "dbd", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 0}
+cnid_dbd_open: struct _cnid_db *(struct cnid_open_args *)
+cnid_dbd_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t)
+cnid_dbd_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t)
+cnid_dbd_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t)
+cnid_delete: int (struct _cnid_db *, cnid_t)
+cnid_find: int (struct _cnid_db *, const char *, size_t, void *, size_t)
+cnid_get: cnid_t (struct _cnid_db *, const cnid_t, char *, const size_t)
+cnid_getstamp: int (struct _cnid_db *, void *, const size_t)
+cnid_init: void (void)
+cnid_last_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t)
+cnid_last_close: void (struct _cnid_db *)
+cnid_last_delete: int (struct _cnid_db *, const cnid_t)
+cnid_last_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t)
+cnid_last_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t)
+cnid_last_module: {name = "last", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 0}
+cnid_last_open: struct _cnid_db *(struct cnid_open_args *)
+cnid_last_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t)
+cnid_last_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t)
+cnid_lookup: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t)
+cnid_open: struct _cnid_db *(const char *, mode_t, char *, int, const char *, const char *)
+cnid_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t, cnid_t)
+cnid_register: void (struct _cnid_module *)
+cnid_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t)
+cnid_tdb_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t)
+cnid_tdb_close: void (struct _cnid_db *)
+cnid_tdb_delete: int (struct _cnid_db *, const cnid_t)
+cnid_tdb_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t)
+cnid_tdb_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t)
+cnid_tdb_module: {name = "tdb", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 12}
+cnid_tdb_open: struct _cnid_db *(struct cnid_open_args *)
+cnid_tdb_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t)
+cnid_tdb_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t)
+cnid_update: int (struct _cnid_db *, const cnid_t, const struct stat *, const cnid_t, char *, const size_t)
+compare_ip: int (const struct sockaddr *, const struct sockaddr *)
+convert_charset: size_t (charset_t, charset_t, charset_t, const char *, size_t, char *, size_t, uint16_t *)
+convert_string: size_t (charset_t, charset_t, const void *, size_t, void *, size_t)
+convert_string_allocate: size_t (charset_t, charset_t, const void *, size_t, char **)
+copy_ea: int (const char *, int, const char *, const char *, mode_t)
+copy_file: int (int, const char *, const char *, mode_t)
+copy_file_fd: int (int, int)
+copy_fork: int (int, struct adouble *, struct adouble *)
+create_lockfile: int (const char *, const char *)
+daemonize: int (int, int)
+decompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *)
+deny_severity: 3
+dequeue: void *(q_t *)
+_diacasemap: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 231, 203, 229, 128, 204, 129, 130, 131, 233, 230, 232, 234, 237, 235, 236, 132, 238, 241, 239, 133, 205, 242, 244, 243, 134, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 198, 183, 184, 184, 186, 187, 188, 189, 174, 175, 192, 193, 194, 195, 196, 197, 198, 199...}
+_dialowermap: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 138, 140, 141, 142, 150, 154, 159, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 132, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 190, 191, 176, 177, 178, 179, 180, 181, 198, 183, 185, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199...}
+dictionary_del: void (dictionary *)
+dictionary_dump: void (dictionary *, FILE *)
+dictionary_get: const char *(const dictionary *, const char *, const char *, const char *)
+dictionary_hash: unsigned int (char *)
+dictionary_new: dictionary *(int)
+dictionary_set: int (dictionary *, char *, char *, char *)
+dictionary_unset: void (dictionary *, char *, char *)
+dir_rx_set: int (mode_t)
+dsi_attention: int (DSI *, AFPUserBytes)
+dsi_close: void (DSI *)
+dsi_cmdreply: int (DSI *, const int)
+dsi_disconnect: int (DSI *)
+dsi_getsession: int (DSI *, server_child *, int, afp_child_t **)
+dsi_getstatus: void (DSI *)
+dsi_init: DSI *(AFPObj *, const char *, const char *, const char *)
+dsi_opensession: void (DSI *)
+dsi_read: ssize_t (DSI *, void *, const size_t)
+dsi_readdone: void (DSI *)
+dsi_readinit: ssize_t (DSI *, void *, const size_t, const size_t, const int)
+dsi_stream_read: size_t (DSI *, void *, const size_t)
+dsi_stream_read_file: ssize_t (DSI *, const int, off_t, const size_t, const int)
+dsi_stream_receive: int (DSI *)
+dsi_stream_send: int (DSI *, void *, size_t)
+dsi_stream_write: ssize_t (DSI *, void *, const size_t, int)
+dsi_tcp_init: int (DSI *, const char *, const char *, const char *)
+dsi_tickle: int (DSI *)
+dsi_write: size_t (DSI *, void *, const size_t)
+dsi_writeflush: void (DSI *)
+dsi_writeinit: size_t (DSI *, void *, const size_t)
+ea_chmod_dir: int (const struct vol *, const char *, mode_t, struct stat *)
+ea_chmod_file: int (const struct vol *, const char *, mode_t, struct stat *)
+ea_chown: int (const struct vol *, const char *, uid_t, gid_t)
+ea_close: int (struct ea *)
+ea_copyfile: int (const struct vol *, int, const char *, const char *)
+ea_deletefile: int (const struct vol *, int, const char *)
+ea_open: int (const struct vol *, const char *, eaflags_t, struct ea *)
+ea_openat: int (const struct vol *, int, const char *, eaflags_t, struct ea *)
+ea_path: char *(const struct ea *, const char *, int)
+ea_renamefile: int (const struct vol *, int, const char *, const char *)
+enqueue: qnode_t *(q_t *, void *)
+fault_setup: void (void (*)(void *))
+fdset_add_fd: void (int, struct pollfd **, struct polldata **, int *, int *, int, enum fdtype, void *)
+fdset_del_fd: void (struct pollfd **, struct polldata **, int *, int *, int)
+find_charset_functions: struct charset_functions *(const char *)
+_fini: <text variable, no debug info>
+freeifacelist: void (char **)
+fullpathname: const char *(const char *)
+getcwdpath: const char *(void)
+getdefextmap: struct extmap *(void)
+get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int)
+get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *)
+getextmap: struct extmap *(const char *)
+getifacelist: char **(void)
+getip_port: unsigned int (const struct sockaddr *)
+getip_string: const char *(const struct sockaddr *)
+getnamefromuuid: int (const uuidp_t, char **, uuidtype_t *)
+getuuidfromname: int (const char *, uuidtype_t, unsigned char *)
+getvolbyname: struct vol *(const char *)
+getvolbypath: struct vol *(AFPObj *, const char *)
+getvolbyvid: struct vol *(const uint16_t)
+getvolumes: struct vol *(void)
+gmem: int (gid_t, int, gid_t *)
+iniparser_dump: void (const dictionary *, FILE *)
+iniparser_dump_ini: void (const dictionary *, FILE *)
+iniparser_find_entry: int (const dictionary *, const char *)
+iniparser_freedict: void (dictionary *)
+iniparser_getboolean: int (const dictionary *, const char *, const char *, int)
+iniparser_getdouble: double (const dictionary *, const char *, const char *, double)
+iniparser_getint: int (const dictionary *, const char *, const char *, int)
+iniparser_getnsec: int (const dictionary *)
+iniparser_getsecname: const char *(const dictionary *, int)
+iniparser_getstrdup: char *(const dictionary *, const char *, const char *, const char *)
+iniparser_getstring: const char *(const dictionary *, const char *, const char *, const char *)
+iniparser_load: dictionary *(const char *)
+iniparser_set: int (dictionary *, char *, char *, char *)
+iniparser_unset: void (dictionary *, char *, char *)
+_init: <text variable, no debug info>
+init_iconv: void (void)
+initline: void (int, char *)
+initvol_vfs: void (struct vol *)
+ipc_child_write: int (int, uint16_t, int, void *)
+ipc_client_uds: int (const char *)
+ipc_server_read: int (server_child *, int)
+ipc_server_uds: int (const char *)
+islower_sp: int (uint32_t)
+islower_w: int (uint16_t)
+isupper_sp: int (uint32_t)
+isupper_w: int (uint16_t)
+lchdir: int (const char *)
+ldap_auth_dn: 0x0
+ldap_auth_method: 0
+ldap_auth_pw: 0x0
+ldap_config_valid: 0
+ldap_getnamefromuuid: int (const char *, char **, uuidtype_t *)
+ldap_getuuidfromname: int (const char *, uuidtype_t, char **)
+ldap_group_attr: 0x0
+ldap_groupbase: 0x0
+ldap_groupscope: 0
+ldap_name_attr: 0x0
+ldap_prefs: {{pref = 0x0, name = "ldap server", strorint = 0, intfromarray = 0, valid = -1}, {pref = 0x0, name = "ldap auth method", strorint = 1, intfromarray = 1, valid = -1}, {pref = 0x0, name = "ldap auth dn", strorint = 0, intfromarray = 0, valid = 0}, {pref = 0x0, name = "ldap auth pw", strorint = 0, intfromarray = 0, valid = 0}, {pref = 0x0, name = "ldap userbase", strorint = 0, intfromarray = 0, valid = -1}, {pref = 0x0, name = "ldap userscope", strorint = 1, intfromarray = 1, valid = -1}, {pref = 0x0, name = "ldap groupbase", strorint = 0, intfromarray = 0, valid = -1}, {pref = 0x0, name = "ldap groupscope", strorint = 1, intfromarray = 1, valid = -1}, {pref = 0x0, name = "ldap uuid attr", strorint = 0, intfromarray = 0, valid = -1}, {pref = 0x0, name = "ldap uuid string", strorint = 0, intfromarray = 0, valid = 0}, {pref = 0x0, name = "ldap name attr", strorint = 0, intfromarray = 0, valid = -1}, {pref = 0x0, name = "ldap group attr", strorint = 0, intfromarray = 0, valid = -1}, {pref = 0x0, name = "ldap uid attr", strorint = 0, intfromarray = 0, valid = 0}, {pref = 0x0, name = "ldap uuid encoding", strorint = 1, intfromarray = 1, valid = 0}, {pref = 0x0, name = 0x0, strorint = 0, intfromarray = 0, valid = -1}}
+ldap_server: 0x0
+ldap_uid_attr: 0x0
+ldap_userbase: 0x0
+ldap_userscope: 0
+ldap_uuid_attr: 0x0
+ldap_uuid_encoding: 0
+ldap_uuid_string: 0x0
+list_eas: int (const struct vol *, char *, size_t *, const char *, int)
+load_charset: int (struct vol *)
+load_volumes: int (AFPObj *, void (*)(const AFPObj *, struct vol *))
+localuuid_from_id: void (unsigned char *, uuidtype_t, unsigned int)
+lock_reg: int (int, int, int, off_t, int, off_t)
+log_config: {inited = false, syslog_opened = false, console = false, processname = '\0' <repeats 15 times>, syslog_facility = 0, syslog_display_options = 0}
+lstatat: int (int, const char *, struct stat *)
+make_log_entry: void (enum loglevels, enum logtypes, const char *, int, char *, ...)
+make_tdb_data: unsigned char *(uint32_t, const struct stat *, const cnid_t, const char *, const size_t)
+mb_generic_pull: size_t (int (*)(uint16_t *, const unsigned char *), void *, char **, size_t *, char **, size_t *)
+mb_generic_push: size_t (int (*)(unsigned char *, uint16_t), void *, char **, size_t *, char **, size_t *)
+netatalk_panic: void (const char *)
+netatalk_rmdir: int (int, const char *)
+netatalk_rmdir_all_errors: int (int, const char *)
+netatalk_unlink: int (const char *)
+netatalk_unlinkat: int (int, const char *)
+nftw: int (const char *, nftw_func_t, dir_notification_func_t, int, int)
+opendirat: DIR *(int, const char *)
+openflags2logstr: const char *(int)
+parseline: int (int, char *)
+posix_chmod: int (const char *, mode_t)
+posix_fchmod: int (int, mode_t)
+precompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *)
+prefs_array: {{pref = "ldap auth method", valuestring = "none", value = 0}, {pref = "ldap auth method", valuestring = "simple", value = 128}, {pref = "ldap auth method", valuestring = "sasl", value = 163}, {pref = "ldap userscope", valuestring = "base", value = 0}, {pref = "ldap userscope", valuestring = "one", value = 1}, {pref = "ldap userscope", valuestring = "sub", value = 2}, {pref = "ldap groupscope", valuestring = "base", value = 0}, {pref = "ldap groupscope", valuestring = "one", value = 1}, {pref = "ldap groupscope", valuestring = "sub", value = 2}, {pref = "ldap uuid encoding", valuestring = "ms-guid", value = 1}, {pref = "ldap uuid encoding", valuestring = "string", value = 0}, {pref = 0x0, valuestring = 0x0, value = 0}}
+prequeue: qnode_t *(q_t *, void *)
+queue_destroy: void (q_t *, void (*)(void *))
+queue_init: q_t *(void)
+randombytes: void (void *, int)
+readt: ssize_t (int, void *, const size_t, int, int)
+realpath_safe: char *(const char *)
+reconnect_ipc: int (AFPObj *)
+recv_fd: int (int, int)
+rel_path_in_vol: bstring (const char *, const char *)
+remove_acl_vfs: int (const char *)
+remove_ea: int (const struct vol *, const char *, const char *, int)
+run_cmd: int (const char *, char **)
+search_cachebyname: int (const char *, uuidtype_t *, unsigned char *)
+search_cachebyuuid: int (uuidp_t, char **, uuidtype_t *)
+send_fd: int (int, int)
+server_child_add: afp_child_t *(server_child *, int, pid_t, int)
+server_child_alloc: server_child *(const int, const int)
+server_child_free: void (server_child *)
+server_child_kill: void (server_child *, int, int)
+server_child_kill_one_by_id: void (server_child *, int, pid_t, uid_t, uint32_t, char *, uint32_t)
+server_child_remove: int (server_child *, const int, pid_t)
+server_child_setup: void (server_child *, const int, void (*)(const pid_t))
+server_child_transfer_session: int (server_child *, int, pid_t, uid_t, int, uint16_t)
+server_lock: pid_t (char *, char *, int)
+server_reset_signal: void (void)
+set_charset_name: int (charset_t, const char *)
+set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int)
+setfilmode: int (const char *, mode_t, struct stat *, mode_t)
+setnonblock: int (int, int)
+set_processname: void (const char *)
+setuplog: void (const char *, const char *)
+statat: int (int, const char *, struct stat *)
+strcasechr_sp: uint16_t *(const uint16_t *, uint32_t)
+strcasechr_w: uint16_t *(const uint16_t *, uint16_t)
+strcasecmp_w: int (const uint16_t *, const uint16_t *)
+strcasestr_w: uint16_t *(const uint16_t *, const uint16_t *)
+strcat_w: uint16_t *(uint16_t *, const uint16_t *)
+strchr_w: uint16_t *(const uint16_t *, uint16_t)
+strcmp_w: int (const uint16_t *, const uint16_t *)
+strdiacasecmp: int (const char *, const char *)
+strdup_w: uint16_t *(const uint16_t *)
+stripped_slashes_basename: char *(char *)
+strlcat: size_t (char *, const char *, size_t)
+strlcpy: size_t (char *, const char *, size_t)
+strlen_w: size_t (const uint16_t *)
+strlower_w: int (uint16_t *)
+strncasecmp_w: int (const uint16_t *, const uint16_t *, size_t)
+strncat_w: uint16_t *(uint16_t *, const uint16_t *, const size_t)
+strncmp_w: int (const uint16_t *, const uint16_t *, size_t)
+strncpy_w: uint16_t *(uint16_t *, const uint16_t *, const size_t)
+strndiacasecmp: int (const char *, const char *, size_t)
+strndup_w: uint16_t *(const uint16_t *, size_t)
+strnlen_w: size_t (const uint16_t *, size_t)
+strstr_w: uint16_t *(const uint16_t *, const uint16_t *)
+strupper_w: int (uint16_t *)
+sys_ea_copyfile: int (const struct vol *, int, const char *, const char *)
+sys_fgetxattr: ssize_t (int, const char *, void *, size_t)
+sys_fsetxattr: int (int, const char *, const void *, size_t, int)
+sys_ftruncate: int (int, off_t)
+sys_get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int)
+sys_get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *)
+sys_getxattr: ssize_t (const char *, const char *, void *, size_t)
+sys_getxattrfd: int (int, const char *, int, ...)
+sys_lgetxattr: ssize_t (const char *, const char *, void *, size_t)
+sys_list_eas: int (const struct vol *, char *, size_t *, const char *, int)
+sys_listxattr: ssize_t (const char *, char *, size_t)
+sys_llistxattr: ssize_t (const char *, char *, size_t)
+sys_lremovexattr: int (const char *, const char *)
+sys_lsetxattr: int (const char *, const char *, const void *, size_t, int)
+sys_remove_ea: int (const struct vol *, const char *, const char *, int)
+sys_removexattr: int (const char *, const char *)
+sys_sendfile: ssize_t (int, int, off_t *, size_t)
+sys_set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int)
+sys_setxattr: int (const char *, const char *, const void *, size_t, int)
+tdb_add_flags: void (struct tdb_context *, unsigned int)
+tdb_allocate: tdb_off_t (struct tdb_context *, tdb_len_t, struct tdb_record *)
+tdb_alloc_read: unsigned char *(struct tdb_context *, tdb_off_t, tdb_len_t)
+tdb_append: int (struct tdb_context *, TDB_DATA, TDB_DATA)
+tdb_brlock: int (struct tdb_context *, tdb_off_t, int, int, int, size_t)
+tdb_brlock_upgrade: int (struct tdb_context *, tdb_off_t, size_t)
+tdb_chainlock: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_mark: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_nonblock: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_read: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_unmark: int (struct tdb_context *, TDB_DATA)
+tdb_chainunlock: int (struct tdb_context *, TDB_DATA)
+tdb_chainunlock_read: int (struct tdb_context *, TDB_DATA)
+tdb_check: int (struct tdb_context *, int (*)(TDB_DATA, TDB_DATA, void *), void *)
+tdb_close: int (struct tdb_context *)
+tdb_convert: void *(void *, uint32_t)
+tdb_delete: int (struct tdb_context *, TDB_DATA)
+tdb_do_delete: int (struct tdb_context *, tdb_off_t, struct tdb_record *)
+tdb_dump_all: void (struct tdb_context *)
+tdb_enable_seqnum: void (struct tdb_context *)
+tdb_error: enum TDB_ERROR (struct tdb_context *)
+tdb_errorstr: const char *(struct tdb_context *)
+tdb_exists: int (struct tdb_context *, TDB_DATA)
+tdb_expand: int (struct tdb_context *, tdb_off_t)
+tdb_fd: int (struct tdb_context *)
+tdb_fetch: TDB_DATA (struct tdb_context *, TDB_DATA)
+tdb_find_lock_hash: tdb_off_t (struct tdb_context *, TDB_DATA, uint32_t, int, struct tdb_record *)
+tdb_firstkey: TDB_DATA (struct tdb_context *)
+tdb_free: int (struct tdb_context *, tdb_off_t, struct tdb_record *)
+tdb_freelist_size: int (struct tdb_context *)
+tdb_get_flags: int (struct tdb_context *)
+tdb_get_logging_private: void *(struct tdb_context *)
+tdb_get_seqnum: int (struct tdb_context *)
+tdb_hash_size: int (struct tdb_context *)
+tdb_increment_seqnum_nonblock: void (struct tdb_context *)
+tdb_io_init: void (struct tdb_context *)
+tdb_lock: int (struct tdb_context *, int, int)
+tdb_lockall: int (struct tdb_context *)
+tdb_lockall_mark: int (struct tdb_context *)
+tdb_lockall_nonblock: int (struct tdb_context *)
+tdb_lockall_read: int (struct tdb_context *)
+tdb_lockall_read_nonblock: int (struct tdb_context *)
+tdb_lockall_unmark: int (struct tdb_context *)
+tdb_lock_nonblock: int (struct tdb_context *, int, int)
+tdb_lock_record: int (struct tdb_context *, tdb_off_t)
+tdb_log_fn: tdb_log_func (struct tdb_context *)
+tdb_map_size: size_t (struct tdb_context *)
+tdb_mmap: void (struct tdb_context *)
+tdb_munmap: int (struct tdb_context *)
+tdb_name: const char *(struct tdb_context *)
+tdb_nextkey: TDB_DATA (struct tdb_context *, TDB_DATA)
+tdb_null: {dptr = 0x0, dsize = 0}
+tdb_ofs_read: int (struct tdb_context *, tdb_off_t, tdb_off_t *)
+tdb_ofs_write: int (struct tdb_context *, tdb_off_t, tdb_off_t *)
+tdb_open: struct tdb_context *(const char *, int, int, int, mode_t)
+tdb_open_ex: struct tdb_context *(const char *, int, int, int, mode_t, const struct tdb_logging_context *, tdb_hash_func)
+tdb_parse_data: int (struct tdb_context *, TDB_DATA, tdb_off_t, tdb_len_t, int (*)(TDB_DATA, TDB_DATA, void *), void *)
+tdb_parse_record: int (struct tdb_context *, TDB_DATA, int (*)(TDB_DATA, TDB_DATA, void *), void *)
+tdb_printfreelist: int (struct tdb_context *)
+tdb_rec_free_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *)
+tdb_rec_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *)
+tdb_rec_write: int (struct tdb_context *, tdb_off_t, struct tdb_record *)
+tdb_remove_flags: void (struct tdb_context *, unsigned int)
+tdb_reopen: int (struct tdb_context *)
+tdb_reopen_all: int (int)
+tdb_repack: int (struct tdb_context *)
+tdb_setalarm_sigptr: void (struct tdb_context *, volatile sig_atomic_t *)
+tdb_set_logging_function: void (struct tdb_context *, const struct tdb_logging_context *)
+tdb_set_max_dead: void (struct tdb_context *, int)
+tdb_store: int (struct tdb_context *, TDB_DATA, TDB_DATA, int)
+_tdb_transaction_cancel: int (struct tdb_context *)
+tdb_transaction_cancel: int (struct tdb_context *)
+tdb_transaction_commit: int (struct tdb_context *)
+tdb_transaction_lock: int (struct tdb_context *, int)
+tdb_transaction_prepare_commit: int (struct tdb_context *)
+tdb_transaction_recover: int (struct tdb_context *)
+tdb_transaction_start: int (struct tdb_context *)
+tdb_transaction_unlock: int (struct tdb_context *)
+tdb_traverse: int (struct tdb_context *, tdb_traverse_func, void *)
+tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *)
+tdb_unlock: int (struct tdb_context *, int, int)
+tdb_unlockall: int (struct tdb_context *)
+tdb_unlockall_read: int (struct tdb_context *)
+tdb_unlock_record: int (struct tdb_context *, tdb_off_t)
+tdb_validate_freelist: int (struct tdb_context *, int *)
+tdb_wipe_all: int (struct tdb_context *)
+tdb_write_lock_record: int (struct tdb_context *, tdb_off_t)
+tdb_write_unlock_record: int (struct tdb_context *, tdb_off_t)
+tolower_sp: uint32_t (uint32_t)
+tolower_w: uint16_t (uint16_t)
+toupper_sp: uint32_t (uint32_t)
+toupper_w: uint16_t (uint16_t)
+type_configs: {{set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}}
+ucs2_to_charset: size_t (charset_t, const uint16_t *, char *, size_t)
+ucs2_to_charset_allocate: size_t (charset_t, char **, const uint16_t *)
+unbecome_root: void (void)
+unix_rename: int (int, const char *, int, const char *)
+unix_strlower: size_t (const char *, size_t, char *, size_t)
+unix_strupper: size_t (const char *, size_t, char *, size_t)
+unload_volumes: void (AFPObj *)
+utf8_charlen: size_t (char *)
+utf8_decompose: size_t (char *, size_t, char *, size_t)
+utf8_precompose: size_t (char *, size_t, char *, size_t)
+utf8_strlen_validate: size_t (char *)
+utf8_strlower: size_t (const char *, size_t, char *, size_t)
+utf8_strupper: size_t (const char *, size_t, char *, size_t)
+utf8_to_charset_allocate: size_t (charset_t, char **, const char *)
+uuid_bin2string: const char *(const unsigned char *)
+uuidcache_dump: void (void)
+uuid_string2bin: void (const char *, unsigned char *)
+uuidtype: {"", "USER", "GROUP", "LOCAL"}
+volume_free: void (struct vol *)
+volume_unlink: void (struct vol *)
+writet: ssize_t (int, void *, const size_t, int, int)
--- /dev/null
+acl_ldap_freeconfig: void (void)
+acl_ldap_readconfig: int (dictionary *)
+ad_close: int (struct adouble *, int)
+ad_convert: int (const char *, const struct stat *, const struct vol *, const char **)
+ad_copy_header: int (struct adouble *, struct adouble *)
+add_cachebyname: int (const char *, const uuidp_t, const uuidtype_t, const long unsigned int)
+add_cachebyuuid: int (uuidp_t, const char *, uuidtype_t, const long unsigned int)
+add_charset: charset_t (const char *)
+ad_dir: char *(const char *)
+ad_dtruncate: int (struct adouble *, const off_t)
+adflags2logstr: const char *(int)
+ad_flush: int (struct adouble *)
+ad_forcegetid: uint32_t (struct adouble *)
+adf_pread: ssize_t (struct ad_fd *, void *, size_t, off_t)
+adf_pwrite: ssize_t (struct ad_fd *, const void *, size_t, off_t)
+ad_getattr: int (const struct adouble *, uint16_t *)
+ad_getdate: int (const struct adouble *, unsigned int, uint32_t *)
+ad_getentryoff: off_t (const struct adouble *, int)
+ad_getfuid: uid_t (void)
+ad_getid: uint32_t (struct adouble *, const dev_t, const ino_t, const cnid_t, const void *)
+ad_hf_mode: mode_t (mode_t)
+ad_init: void (struct adouble *, const struct vol *)
+ad_init_old: void (struct adouble *, int, int)
+ad_lock: int (struct adouble *, uint32_t, int, off_t, off_t, int)
+ad_metadata: int (const char *, int, struct adouble *)
+ad_metadataat: int (int, const char *, int, struct adouble *)
+ad_mkdir: int (const char *, mode_t)
+ad_mode: int (const char *, mode_t)
+ad_open: int (struct adouble *, const char *, int, ...)
+ad_openat: int (struct adouble *, int, const char *, int, ...)
+ad_openforks: uint16_t (struct adouble *, uint16_t)
+ad_path: const char *(const char *, int)
+ad_path_ea: const char *(const char *, int)
+ad_path_osx: const char *(const char *, int)
+ad_read: ssize_t (struct adouble *, const uint32_t, off_t, char *, const size_t)
+ad_readfile_init: int (const struct adouble *, const int, off_t *, const int)
+ad_rebuild_adouble_header_ea: int (struct adouble *)
+ad_rebuild_adouble_header_v2: int (struct adouble *)
+ad_refresh: int (const char *, struct adouble *)
+ad_rtruncate: int (struct adouble *, const off_t)
+ad_setattr: int (const struct adouble *, const uint16_t)
+ad_setdate: int (struct adouble *, unsigned int, uint32_t)
+ad_setfuid: int (const uid_t)
+ad_setid: int (struct adouble *, const dev_t, const ino_t, const uint32_t, const cnid_t, const void *)
+ad_setname: int (struct adouble *, const char *)
+ad_size: off_t (const struct adouble *, const uint32_t)
+ad_stat: int (const char *, struct stat *)
+ad_testlock: int (struct adouble *, int, const off_t)
+ad_tmplock: int (struct adouble *, uint32_t, int, off_t, off_t, int)
+ad_unlock: void (struct adouble *, const int, int)
+ad_valid_header_osx: int (const char *)
+ad_write: ssize_t (struct adouble *, uint32_t, off_t, int, const char *, size_t)
+afp_config_free: void (AFPObj *)
+afp_config_parse: int (AFPObj *, char *)
+allow_severity: 5
+apply_ip_mask: void (struct sockaddr *, int)
+atalk_iconv: size_t (atalk_iconv_t, const char **, size_t *, char **, size_t *)
+atalk_iconv_close: int (atalk_iconv_t)
+atalk_iconv_open: atalk_iconv_t (const char *, const char *)
+atalk_register_charset: int (struct charset_functions *)
+balloc: int (bstring, int)
+ballocmin: int (bstring, int)
+basename_safe: const char *(const char *)
+bassign: int (bstring, const_bstring)
+bassignblk: int (bstring, const void *, int)
+bassigncstr: int (bstring, const char *)
+bassignformat: int (bstring, const char *, ...)
+bassigngets: int (bstring, bNgetc, void *, char)
+bassignmidstr: int (bstring, const_bstring, int, int)
+bcatblk: int (bstring, const void *, int)
+bcatcstr: int (bstring, const char *)
+bconcat: int (bstring, const_bstring)
+bconchar: int (bstring, char)
+bcstrfree: int (char *)
+bdelete: int (bstring, int, int)
+bdestroy: int (bstring)
+become_root: void (void)
+bfindreplace: int (bstring, const_bstring, const_bstring, int)
+bfindreplacecaseless: int (bstring, const_bstring, const_bstring, int)
+bformat: bstring (const char *, ...)
+bformata: int (bstring, const char *, ...)
+bfromcstr: bstring (const char *)
+bfromcstralloc: bstring (int, const char *)
+bgetsa: int (bstring, bNgetc, void *, char)
+bgetstream: bstring (bNgetc, void *, char)
+binchr: int (const_bstring, int, const_bstring)
+binchrr: int (const_bstring, int, const_bstring)
+binsert: int (bstring, int, const_bstring, unsigned char)
+binsertch: int (bstring, int, int, unsigned char)
+binstr: int (const_bstring, int, const_bstring)
+binstrcaseless: int (const_bstring, int, const_bstring)
+binstrr: int (const_bstring, int, const_bstring)
+binstrrcaseless: int (const_bstring, int, const_bstring)
+biseq: int (const_bstring, const_bstring)
+biseqcaseless: int (const_bstring, const_bstring)
+biseqcstr: int (const_bstring, const char *)
+biseqcstrcaseless: int (const_bstring, const char *)
+bisstemeqblk: int (const_bstring, const void *, int)
+bisstemeqcaselessblk: int (const_bstring, const void *, int)
+bjoin: bstring (const struct bstrList *, const_bstring)
+bjoinInv: bstring (const struct bstrList *, const_bstring)
+blk2bstr: bstring (const void *, int)
+bltrimws: int (bstring)
+bmidstr: bstring (const_bstring, int, int)
+bninchr: int (const_bstring, int, const_bstring)
+bninchrr: int (const_bstring, int, const_bstring)
+bpattern: int (bstring, int)
+bread: bstring (bNread, void *)
+breada: int (bstring, bNread, void *)
+brefcstr: bstring (char *)
+breplace: int (bstring, int, int, const_bstring, unsigned char)
+brtrimws: int (bstring)
+bsbufflength: int (struct bStream *, int)
+bsclose: void *(struct bStream *)
+bseof: int (const struct bStream *)
+bsetstr: int (bstring, int, const_bstring, unsigned char)
+bsopen: struct bStream *(bNread, void *)
+bspeek: int (bstring, const struct bStream *)
+bsplit: struct bstrList *(const_bstring, unsigned char)
+bsplitcb: int (const_bstring, unsigned char, int, int (*)(void *, int, int), void *)
+bsplits: struct bstrList *(const_bstring, const_bstring)
+bsplitscb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *)
+bsplitstr: struct bstrList *(const_bstring, const_bstring)
+bsplitstrcb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *)
+bsread: int (bstring, struct bStream *, int)
+bsreada: int (bstring, struct bStream *, int)
+bsreadln: int (bstring, struct bStream *, char)
+bsreadlna: int (bstring, struct bStream *, char)
+bsreadlns: int (bstring, struct bStream *, const_bstring)
+bsreadlnsa: int (bstring, struct bStream *, const_bstring)
+bssplitscb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *)
+bssplitstrcb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *)
+bstr2cstr: char *(const_bstring, char)
+bstrchrp: int (const_bstring, int, int)
+bstrcmp: int (const_bstring, const_bstring)
+bstrcpy: bstring (const_bstring)
+bstricmp: int (const_bstring, const_bstring)
+bstrListAlloc: int (struct bstrList *, int)
+bstrListAllocMin: int (struct bstrList *, int)
+bstrListCreate: struct bstrList *(void)
+bstrListCreateMin: struct bstrList *(int)
+bstrListDestroy: int (struct bstrList *)
+bstrListPop: bstring (struct bstrList *)
+bstrListPush: int (struct bstrList *, bstring)
+bstrncmp: int (const_bstring, const_bstring, int)
+bstrnicmp: int (const_bstring, const_bstring, int)
+bstrrchrp: int (const_bstring, int, int)
+bsunread: int (struct bStream *, const_bstring)
+btolower: int (bstring)
+btoupper: int (bstring)
+btrimws: int (bstring)
+btrunc: int (bstring, int)
+bunrefcstr: int (bstring)
+bvcformata: int (bstring, int, const char *, struct __va_list_tag *)
+charset_decompose: size_t (charset_t, char *, size_t, char *, size_t)
+charset_mac_centraleurope: {name = "MAC_CENTRALEUROPE", kTextEncoding = 29, pull = <mac_centraleurope_pull>, push = <mac_centraleurope_push>, flags = 17, iname = 0x0, prev = 0x0, next = 0x0}
+charset_mac_chinese_simp: {name = "MAC_CHINESE_SIMP", kTextEncoding = 25, pull = <mac_chinese_simp_pull>, push = <mac_chinese_simp_push>, flags = 85, iname = "EUC-CN", prev = 0x0, next = 0x0}
+charset_mac_chinese_trad: {name = "MAC_CHINESE_TRAD", kTextEncoding = 2, pull = <mac_chinese_trad_pull>, push = <mac_chinese_trad_push>, flags = 85, iname = "BIG-5", prev = 0x0, next = 0x0}
+charset_mac_cyrillic: {name = "MAC_CYRILLIC", kTextEncoding = 7, pull = <mac_cyrillic_pull>, push = <mac_cyrillic_push>, flags = 17, iname = 0x0, prev = 0x0, next = 0x0}
+charset_mac_greek: {name = "MAC_GREEK", kTextEncoding = 6, pull = <mac_greek_pull>, push = <mac_greek_push>, flags = 17, iname = 0x0, prev = 0x0, next = 0x0}
+charset_mac_hebrew: {name = "MAC_HEBREW", kTextEncoding = 5, pull = <mac_hebrew_pull>, push = <mac_hebrew_push>, flags = 17, iname = 0x0, prev = 0x0, next = 0x0}
+charset_mac_japanese: {name = "MAC_JAPANESE", kTextEncoding = 1, pull = <mac_japanese_pull>, push = <mac_japanese_push>, flags = 85, iname = "SHIFT_JIS", prev = 0x0, next = 0x0}
+charset_mac_korean: {name = "MAC_KOREAN", kTextEncoding = 3, pull = <mac_korean_pull>, push = <mac_korean_push>, flags = 85, iname = "EUC-KR", prev = 0x0, next = 0x0}
+charset_mac_roman: {name = "MAC_ROMAN", kTextEncoding = 0, pull = <mac_roman_pull>, push = <mac_roman_push>, flags = 21, iname = 0x0, prev = 0x0, next = 0x0}
+charset_mac_turkish: {name = "MAC_TURKISH", kTextEncoding = 35, pull = <mac_turkish_pull>, push = <mac_turkish_push>, flags = 17, iname = 0x0, prev = 0x0, next = 0x0}
+charset_precompose: size_t (charset_t, char *, size_t, char *, size_t)
+charset_strlower: size_t (charset_t, const char *, size_t, char *, size_t)
+charset_strupper: size_t (charset_t, const char *, size_t, char *, size_t)
+charset_to_ucs2_allocate: size_t (charset_t, uint16_t **, const char *)
+charset_to_utf8_allocate: size_t (charset_t, char **, const char *)
+charset_utf8: {name = "UTF8", kTextEncoding = 134217987, pull = <utf8_pull>, push = <utf8_push>, flags = 22, iname = 0x0, prev = 0x0, next = 0x0}
+charset_utf8_mac: {name = "UTF8-MAC", kTextEncoding = 134217987, pull = <utf8_pull>, push = <utf8_push>, flags = 27, iname = 0x0, prev = 0x0, next = 0x0}
+check_lockfile: int (const char *, const char *)
+cjk_char_pull: size_t (uint16_t, uint16_t *, const uint32_t *)
+cjk_char_push: size_t (uint16_t, uint8_t *)
+cjk_compose: uint16_t (uint16_t, uint16_t, const uint32_t *, size_t)
+cjk_compose_seq: uint16_t (const uint16_t *, size_t *, const uint32_t *, size_t)
+cjk_generic_pull: size_t (size_t (*)(uint16_t *, const uint8_t *, size_t *), void *, char **, size_t *, char **, size_t *)
+cjk_generic_push: size_t (size_t (*)(uint8_t *, const uint16_t *, size_t *), void *, char **, size_t *, char **, size_t *)
+cjk_lookup: uint16_t (uint16_t, const cjk_index_t *, const uint16_t *)
+cnid_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, const char *, const size_t, cnid_t)
+cnid_close: void (struct _cnid_db *)
+cnid_dbd_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t)
+cnid_dbd_close: void (struct _cnid_db *)
+cnid_dbd_delete: int (struct _cnid_db *, const cnid_t)
+cnid_dbd_find: int (struct _cnid_db *, const char *, size_t, void *, size_t)
+cnid_dbd_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t)
+cnid_dbd_getstamp: int (struct _cnid_db *, void *, const size_t)
+cnid_dbd_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t)
+cnid_dbd_module: {name = "dbd", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 0}
+cnid_dbd_open: struct _cnid_db *(struct cnid_open_args *)
+cnid_dbd_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t)
+cnid_dbd_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t)
+cnid_dbd_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t)
+cnid_dbd_wipe: int (struct _cnid_db *)
+cnid_delete: int (struct _cnid_db *, cnid_t)
+cnid_find: int (struct _cnid_db *, const char *, size_t, void *, size_t)
+cnid_get: cnid_t (struct _cnid_db *, const cnid_t, char *, const size_t)
+cnid_getstamp: int (struct _cnid_db *, void *, const size_t)
+cnid_init: void (void)
+cnid_last_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t)
+cnid_last_close: void (struct _cnid_db *)
+cnid_last_delete: int (struct _cnid_db *, const cnid_t)
+cnid_last_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t)
+cnid_last_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t)
+cnid_last_module: {name = "last", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 0}
+cnid_last_open: struct _cnid_db *(struct cnid_open_args *)
+cnid_last_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t)
+cnid_last_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t)
+cnid_lookup: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t)
+cnid_open: struct _cnid_db *(const char *, mode_t, char *, int, const char *, const char *)
+cnid_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t, cnid_t)
+cnid_register: void (struct _cnid_module *)
+cnid_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t)
+cnid_tdb_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t)
+cnid_tdb_close: void (struct _cnid_db *)
+cnid_tdb_delete: int (struct _cnid_db *, const cnid_t)
+cnid_tdb_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t)
+cnid_tdb_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t)
+cnid_tdb_module: {name = "tdb", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 12}
+cnid_tdb_open: struct _cnid_db *(struct cnid_open_args *)
+cnid_tdb_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t)
+cnid_tdb_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t)
+cnid_update: int (struct _cnid_db *, const cnid_t, const struct stat *, const cnid_t, char *, const size_t)
+cnid_wipe: int (struct _cnid_db *)
+compare_ip: int (const struct sockaddr *, const struct sockaddr *)
+convert_charset: size_t (charset_t, charset_t, charset_t, const char *, size_t, char *, size_t, uint16_t *)
+convert_string: size_t (charset_t, charset_t, const void *, size_t, void *, size_t)
+convert_string_allocate: size_t (charset_t, charset_t, const void *, size_t, char **)
+copy_ea: int (const char *, int, const char *, const char *, mode_t)
+copy_file: int (int, const char *, const char *, mode_t)
+copy_file_fd: int (int, int)
+copy_fork: int (int, struct adouble *, struct adouble *)
+create_lockfile: int (const char *, const char *)
+daemonize: int (int, int)
+decompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *)
+deny_severity: 3
+dequeue: void *(q_t *)
+_diacasemap: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 231, 203, 229, 128, 204, 129, 130, 131, 233, 230, 232, 234, 237, 235, 236, 132, 238, 241, 239, 133, 205, 242, 244, 243, 134, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 198, 183, 184, 184, 186, 187, 188, 189, 174, 175, 192, 193, 194, 195, 196, 197, 198, 199...}
+_dialowermap: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 138, 140, 141, 142, 150, 154, 159, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 132, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 190, 191, 176, 177, 178, 179, 180, 181, 198, 183, 185, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199...}
+dictionary_del: void (dictionary *)
+dictionary_dump: void (dictionary *, FILE *)
+dictionary_get: const char *(const dictionary *, const char *, const char *, const char *)
+dictionary_hash: unsigned int (char *)
+dictionary_new: dictionary *(int)
+dictionary_set: int (dictionary *, char *, char *, char *)
+dictionary_unset: void (dictionary *, char *, char *)
+dir_rx_set: int (mode_t)
+dsi_attention: int (DSI *, AFPUserBytes)
+dsi_close: void (DSI *)
+dsi_cmdreply: int (DSI *, const int)
+dsi_disconnect: int (DSI *)
+dsi_free: void (DSI *)
+dsi_getsession: int (DSI *, server_child *, int, afp_child_t **)
+dsi_getstatus: void (DSI *)
+dsi_init: DSI *(AFPObj *, const char *, const char *, const char *)
+dsi_opensession: void (DSI *)
+dsi_read: ssize_t (DSI *, void *, const size_t)
+dsi_readdone: void (DSI *)
+dsi_readinit: ssize_t (DSI *, void *, const size_t, const size_t, const int)
+dsi_stream_read: size_t (DSI *, void *, const size_t)
+dsi_stream_read_file: ssize_t (DSI *, const int, off_t, const size_t, const int)
+dsi_stream_receive: int (DSI *)
+dsi_stream_send: int (DSI *, void *, size_t)
+dsi_stream_write: ssize_t (DSI *, void *, const size_t, int)
+dsi_tcp_init: int (DSI *, const char *, const char *, const char *)
+dsi_tickle: int (DSI *)
+dsi_write: size_t (DSI *, void *, const size_t)
+dsi_writeflush: void (DSI *)
+dsi_writeinit: size_t (DSI *, void *, const size_t)
+ea_chmod_dir: int (const struct vol *, const char *, mode_t, struct stat *)
+ea_chmod_file: int (const struct vol *, const char *, mode_t, struct stat *)
+ea_chown: int (const struct vol *, const char *, uid_t, gid_t)
+ea_close: int (struct ea *)
+ea_copyfile: int (const struct vol *, int, const char *, const char *)
+ea_deletefile: int (const struct vol *, int, const char *)
+ea_open: int (const struct vol *, const char *, eaflags_t, struct ea *)
+ea_openat: int (const struct vol *, int, const char *, eaflags_t, struct ea *)
+ea_path: char *(const struct ea *, const char *, int)
+ea_renamefile: int (const struct vol *, int, const char *, const char *)
+enqueue: qnode_t *(q_t *, void *)
+fault_setup: void (void (*)(void *))
+fdset_add_fd: void (int, struct pollfd **, struct polldata **, int *, int *, int, enum fdtype, void *)
+fdset_del_fd: void (struct pollfd **, struct polldata **, int *, int *, int)
+find_charset_functions: struct charset_functions *(const char *)
+_fini: <text variable, no debug info>
+free_charset_names: void (void)
+freeifacelist: void (char **)
+fullpathname: const char *(const char *)
+getcwdpath: const char *(void)
+getdefextmap: struct extmap *(void)
+get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int)
+get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *)
+getextmap: struct extmap *(const char *)
+getifacelist: char **(void)
+getip_port: unsigned int (const struct sockaddr *)
+getip_string: const char *(const struct sockaddr *)
+getnamefromuuid: int (const uuidp_t, char **, uuidtype_t *)
+getuuidfromname: int (const char *, uuidtype_t, unsigned char *)
+getvolbyname: struct vol *(const char *)
+getvolbypath: struct vol *(AFPObj *, const char *)
+getvolbyvid: struct vol *(const uint16_t)
+getvolumes: struct vol *(void)
+gmem: int (gid_t, int, gid_t *)
+iniparser_dump: void (const dictionary *, FILE *)
+iniparser_dump_ini: void (const dictionary *, FILE *)
+iniparser_find_entry: int (const dictionary *, const char *)
+iniparser_freedict: void (dictionary *)
+iniparser_getboolean: int (const dictionary *, const char *, const char *, int)
+iniparser_getdouble: double (const dictionary *, const char *, const char *, double)
+iniparser_getint: int (const dictionary *, const char *, const char *, int)
+iniparser_getnsec: int (const dictionary *)
+iniparser_getsecname: const char *(const dictionary *, int)
+iniparser_getstrdup: char *(const dictionary *, const char *, const char *, const char *)
+iniparser_getstring: const char *(const dictionary *, const char *, const char *, const char *)
+iniparser_load: dictionary *(const char *)
+iniparser_set: int (dictionary *, char *, char *, char *)
+iniparser_unset: void (dictionary *, char *, char *)
+_init: <text variable, no debug info>
+init_iconv: void (void)
+initline: void (int, char *)
+initvol_vfs: void (struct vol *)
+ipc_child_write: int (int, uint16_t, int, void *)
+ipc_client_uds: int (const char *)
+ipc_server_read: int (server_child *, int)
+ipc_server_uds: int (const char *)
+islower_sp: int (uint32_t)
+islower_w: int (uint16_t)
+isupper_sp: int (uint32_t)
+isupper_w: int (uint16_t)
+ldap_auth_dn: 0x0
+ldap_auth_method: 0
+ldap_auth_pw: 0x0
+ldap_config_valid: 0
+ldap_getnamefromuuid: int (const char *, char **, uuidtype_t *)
+ldap_getuuidfromname: int (const char *, uuidtype_t, char **)
+ldap_group_attr: 0x0
+ldap_groupbase: 0x0
+ldap_groupscope: 0
+ldap_name_attr: 0x0
+ldap_prefs: {{pref = 0x0, name = "ldap server", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap auth method", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap auth dn", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap auth pw", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap userbase", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap userscope", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap groupbase", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap groupscope", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uuid attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uuid string", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap name attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap group attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uid attr", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap uuid encoding", strorint = 1, intfromarray = 1, valid = 0, valid_save = 0}, {pref = 0x0, name = 0x0, strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}}
+ldap_server: 0x0
+ldap_uid_attr: 0x0
+ldap_userbase: 0x0
+ldap_userscope: 0
+ldap_uuid_attr: 0x0
+ldap_uuid_encoding: 0
+ldap_uuid_string: 0x0
+list_eas: int (const struct vol *, char *, size_t *, const char *, int)
+load_charset: int (struct vol *)
+load_volumes: int (AFPObj *)
+localuuid_from_id: void (unsigned char *, uuidtype_t, unsigned int)
+lock_reg: int (int, int, int, off_t, int, off_t)
+log_config: {inited = false, syslog_opened = false, console = false, processname = '\0' <repeats 15 times>, syslog_facility = 0, syslog_display_options = 0}
+make_log_entry: void (enum loglevels, enum logtypes, const char *, int, char *, ...)
+make_tdb_data: unsigned char *(uint32_t, const struct stat *, const cnid_t, const char *, const size_t)
+mb_generic_pull: size_t (int (*)(uint16_t *, const unsigned char *), void *, char **, size_t *, char **, size_t *)
+mb_generic_push: size_t (int (*)(unsigned char *, uint16_t), void *, char **, size_t *, char **, size_t *)
+netatalk_panic: void (const char *)
+netatalk_rmdir: int (int, const char *)
+netatalk_rmdir_all_errors: int (int, const char *)
+netatalk_unlink: int (const char *)
+netatalk_unlinkat: int (int, const char *)
+nftw: int (const char *, nftw_func_t, dir_notification_func_t, int, int)
+ochdir: int (const char *, int)
+ochmod: int (char *, mode_t, const struct stat *, int)
+ochown: int (const char *, uid_t, gid_t, int)
+opendirat: DIR *(int, const char *)
+openflags2logstr: const char *(int)
+ostat: int (const char *, struct stat *, int)
+ostatat: int (int, const char *, struct stat *, int)
+parseline: int (int, char *)
+posix_chmod: int (const char *, mode_t)
+posix_fchmod: int (int, mode_t)
+precompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *)
+prefs_array: {{pref = "ldap auth method", valuestring = "none", value = 0}, {pref = "ldap auth method", valuestring = "simple", value = 128}, {pref = "ldap auth method", valuestring = "sasl", value = 163}, {pref = "ldap userscope", valuestring = "base", value = 0}, {pref = "ldap userscope", valuestring = "one", value = 1}, {pref = "ldap userscope", valuestring = "sub", value = 2}, {pref = "ldap groupscope", valuestring = "base", value = 0}, {pref = "ldap groupscope", valuestring = "one", value = 1}, {pref = "ldap groupscope", valuestring = "sub", value = 2}, {pref = "ldap uuid encoding", valuestring = "ms-guid", value = 1}, {pref = "ldap uuid encoding", valuestring = "string", value = 0}, {pref = 0x0, valuestring = 0x0, value = 0}}
+prequeue: qnode_t *(q_t *, void *)
+queue_destroy: void (q_t *, void (*)(void *))
+queue_init: q_t *(void)
+randombytes: void (void *, int)
+readt: ssize_t (int, void *, const size_t, int, int)
+realpath_safe: char *(const char *)
+reconnect_ipc: int (AFPObj *)
+recv_fd: int (int, int)
+rel_path_in_vol: bstring (const char *, const char *)
+remove_acl_vfs: int (const char *)
+remove_ea: int (const struct vol *, const char *, const char *, int)
+run_cmd: int (const char *, char **)
+search_cachebyname: int (const char *, uuidtype_t *, unsigned char *)
+search_cachebyuuid: int (uuidp_t, char **, uuidtype_t *)
+send_fd: int (int, int)
+server_child_add: afp_child_t *(server_child *, int, pid_t, int)
+server_child_alloc: server_child *(const int, const int)
+server_child_free: void (server_child *)
+server_child_kill: void (server_child *, int, int)
+server_child_kill_one_by_id: void (server_child *, int, pid_t, uid_t, uint32_t, char *, uint32_t)
+server_child_remove: int (server_child *, const int, pid_t)
+server_child_setup: void (server_child *, const int, void (*)(const pid_t))
+server_child_transfer_session: int (server_child *, int, pid_t, uid_t, int, uint16_t)
+server_lock: pid_t (char *, char *, int)
+server_reset_signal: void (void)
+set_charset_name: int (charset_t, const char *)
+set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int)
+setfilmode: int (const struct vol *, const char *, mode_t, struct stat *)
+setnonblock: int (int, int)
+set_processname: void (const char *)
+setuplog: void (const char *, const char *)
+statat: int (int, const char *, struct stat *)
+strcasechr_sp: uint16_t *(const uint16_t *, uint32_t)
+strcasechr_w: uint16_t *(const uint16_t *, uint16_t)
+strcasecmp_w: int (const uint16_t *, const uint16_t *)
+strcasestr_w: uint16_t *(const uint16_t *, const uint16_t *)
+strcat_w: uint16_t *(uint16_t *, const uint16_t *)
+strchr_w: uint16_t *(const uint16_t *, uint16_t)
+strcmp_w: int (const uint16_t *, const uint16_t *)
+strdiacasecmp: int (const char *, const char *)
+strdup_w: uint16_t *(const uint16_t *)
+stripped_slashes_basename: char *(char *)
+strlcat: size_t (char *, const char *, size_t)
+strlcpy: size_t (char *, const char *, size_t)
+strlen_w: size_t (const uint16_t *)
+strlower_w: int (uint16_t *)
+strncasecmp_w: int (const uint16_t *, const uint16_t *, size_t)
+strncat_w: uint16_t *(uint16_t *, const uint16_t *, const size_t)
+strncmp_w: int (const uint16_t *, const uint16_t *, size_t)
+strncpy_w: uint16_t *(uint16_t *, const uint16_t *, const size_t)
+strndiacasecmp: int (const char *, const char *, size_t)
+strndup_w: uint16_t *(const uint16_t *, size_t)
+strnlen_w: size_t (const uint16_t *, size_t)
+strstr_w: uint16_t *(const uint16_t *, const uint16_t *)
+strtok_quote: char *(char *, const char *)
+strupper_w: int (uint16_t *)
+sys_ea_copyfile: int (const struct vol *, int, const char *, const char *)
+sys_fgetxattr: ssize_t (int, const char *, void *, size_t)
+sys_fsetxattr: int (int, const char *, const void *, size_t, int)
+sys_ftruncate: int (int, off_t)
+sys_get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int)
+sys_get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *)
+sys_getxattr: ssize_t (const char *, const char *, void *, size_t)
+sys_getxattrfd: int (int, const char *, int, ...)
+sys_lgetxattr: ssize_t (const char *, const char *, void *, size_t)
+sys_list_eas: int (const struct vol *, char *, size_t *, const char *, int)
+sys_listxattr: ssize_t (const char *, char *, size_t)
+sys_llistxattr: ssize_t (const char *, char *, size_t)
+sys_lremovexattr: int (const char *, const char *)
+sys_lsetxattr: int (const char *, const char *, const void *, size_t, int)
+sys_remove_ea: int (const struct vol *, const char *, const char *, int)
+sys_removexattr: int (const char *, const char *)
+sys_sendfile: ssize_t (int, int, off_t *, size_t)
+sys_set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int)
+sys_setxattr: int (const char *, const char *, const void *, size_t, int)
+tdb_add_flags: void (struct tdb_context *, unsigned int)
+tdb_allocate: tdb_off_t (struct tdb_context *, tdb_len_t, struct tdb_record *)
+tdb_alloc_read: unsigned char *(struct tdb_context *, tdb_off_t, tdb_len_t)
+tdb_append: int (struct tdb_context *, TDB_DATA, TDB_DATA)
+tdb_brlock: int (struct tdb_context *, tdb_off_t, int, int, int, size_t)
+tdb_brlock_upgrade: int (struct tdb_context *, tdb_off_t, size_t)
+tdb_chainlock: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_mark: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_nonblock: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_read: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_unmark: int (struct tdb_context *, TDB_DATA)
+tdb_chainunlock: int (struct tdb_context *, TDB_DATA)
+tdb_chainunlock_read: int (struct tdb_context *, TDB_DATA)
+tdb_check: int (struct tdb_context *, int (*)(TDB_DATA, TDB_DATA, void *), void *)
+tdb_close: int (struct tdb_context *)
+tdb_convert: void *(void *, uint32_t)
+tdb_delete: int (struct tdb_context *, TDB_DATA)
+tdb_do_delete: int (struct tdb_context *, tdb_off_t, struct tdb_record *)
+tdb_dump_all: void (struct tdb_context *)
+tdb_enable_seqnum: void (struct tdb_context *)
+tdb_error: enum TDB_ERROR (struct tdb_context *)
+tdb_errorstr: const char *(struct tdb_context *)
+tdb_exists: int (struct tdb_context *, TDB_DATA)
+tdb_expand: int (struct tdb_context *, tdb_off_t)
+tdb_fd: int (struct tdb_context *)
+tdb_fetch: TDB_DATA (struct tdb_context *, TDB_DATA)
+tdb_find_lock_hash: tdb_off_t (struct tdb_context *, TDB_DATA, uint32_t, int, struct tdb_record *)
+tdb_firstkey: TDB_DATA (struct tdb_context *)
+tdb_free: int (struct tdb_context *, tdb_off_t, struct tdb_record *)
+tdb_freelist_size: int (struct tdb_context *)
+tdb_get_flags: int (struct tdb_context *)
+tdb_get_logging_private: void *(struct tdb_context *)
+tdb_get_seqnum: int (struct tdb_context *)
+tdb_hash_size: int (struct tdb_context *)
+tdb_increment_seqnum_nonblock: void (struct tdb_context *)
+tdb_io_init: void (struct tdb_context *)
+tdb_lock: int (struct tdb_context *, int, int)
+tdb_lockall: int (struct tdb_context *)
+tdb_lockall_mark: int (struct tdb_context *)
+tdb_lockall_nonblock: int (struct tdb_context *)
+tdb_lockall_read: int (struct tdb_context *)
+tdb_lockall_read_nonblock: int (struct tdb_context *)
+tdb_lockall_unmark: int (struct tdb_context *)
+tdb_lock_nonblock: int (struct tdb_context *, int, int)
+tdb_lock_record: int (struct tdb_context *, tdb_off_t)
+tdb_log_fn: tdb_log_func (struct tdb_context *)
+tdb_map_size: size_t (struct tdb_context *)
+tdb_mmap: void (struct tdb_context *)
+tdb_munmap: int (struct tdb_context *)
+tdb_name: const char *(struct tdb_context *)
+tdb_nextkey: TDB_DATA (struct tdb_context *, TDB_DATA)
+tdb_null: {dptr = 0x0, dsize = 0}
+tdb_ofs_read: int (struct tdb_context *, tdb_off_t, tdb_off_t *)
+tdb_ofs_write: int (struct tdb_context *, tdb_off_t, tdb_off_t *)
+tdb_open: struct tdb_context *(const char *, int, int, int, mode_t)
+tdb_open_ex: struct tdb_context *(const char *, int, int, int, mode_t, const struct tdb_logging_context *, tdb_hash_func)
+tdb_parse_data: int (struct tdb_context *, TDB_DATA, tdb_off_t, tdb_len_t, int (*)(TDB_DATA, TDB_DATA, void *), void *)
+tdb_parse_record: int (struct tdb_context *, TDB_DATA, int (*)(TDB_DATA, TDB_DATA, void *), void *)
+tdb_printfreelist: int (struct tdb_context *)
+tdb_rec_free_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *)
+tdb_rec_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *)
+tdb_rec_write: int (struct tdb_context *, tdb_off_t, struct tdb_record *)
+tdb_remove_flags: void (struct tdb_context *, unsigned int)
+tdb_reopen: int (struct tdb_context *)
+tdb_reopen_all: int (int)
+tdb_repack: int (struct tdb_context *)
+tdb_setalarm_sigptr: void (struct tdb_context *, volatile sig_atomic_t *)
+tdb_set_logging_function: void (struct tdb_context *, const struct tdb_logging_context *)
+tdb_set_max_dead: void (struct tdb_context *, int)
+tdb_store: int (struct tdb_context *, TDB_DATA, TDB_DATA, int)
+_tdb_transaction_cancel: int (struct tdb_context *)
+tdb_transaction_cancel: int (struct tdb_context *)
+tdb_transaction_commit: int (struct tdb_context *)
+tdb_transaction_lock: int (struct tdb_context *, int)
+tdb_transaction_prepare_commit: int (struct tdb_context *)
+tdb_transaction_recover: int (struct tdb_context *)
+tdb_transaction_start: int (struct tdb_context *)
+tdb_transaction_unlock: int (struct tdb_context *)
+tdb_traverse: int (struct tdb_context *, tdb_traverse_func, void *)
+tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *)
+tdb_unlock: int (struct tdb_context *, int, int)
+tdb_unlockall: int (struct tdb_context *)
+tdb_unlockall_read: int (struct tdb_context *)
+tdb_unlock_record: int (struct tdb_context *, tdb_off_t)
+tdb_validate_freelist: int (struct tdb_context *, int *)
+tdb_wipe_all: int (struct tdb_context *)
+tdb_write_lock_record: int (struct tdb_context *, tdb_off_t)
+tdb_write_unlock_record: int (struct tdb_context *, tdb_off_t)
+tolower_sp: uint32_t (uint32_t)
+tolower_w: uint16_t (uint16_t)
+toupper_sp: uint32_t (uint32_t)
+toupper_w: uint16_t (uint16_t)
+type_configs: {{set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}}
+ucs2_to_charset: size_t (charset_t, const uint16_t *, char *, size_t)
+ucs2_to_charset_allocate: size_t (charset_t, char **, const uint16_t *)
+unbecome_root: void (void)
+unix_rename: int (int, const char *, int, const char *)
+unix_strlower: size_t (const char *, size_t, char *, size_t)
+unix_strupper: size_t (const char *, size_t, char *, size_t)
+unload_volumes: void (AFPObj *)
+utf8_charlen: size_t (char *)
+utf8_decompose: size_t (char *, size_t, char *, size_t)
+utf8_precompose: size_t (char *, size_t, char *, size_t)
+utf8_strlen_validate: size_t (char *)
+utf8_strlower: size_t (const char *, size_t, char *, size_t)
+utf8_strupper: size_t (const char *, size_t, char *, size_t)
+utf8_to_charset_allocate: size_t (charset_t, char **, const char *)
+uuid_bin2string: const char *(const unsigned char *)
+uuidcache_dump: void (void)
+uuid_string2bin: void (const char *, unsigned char *)
+uuidtype: {"", "USER", "GROUP", "LOCAL"}
+volume_free: void (struct vol *)
+volume_unlink: void (struct vol *)
+writet: ssize_t (int, void *, const size_t, int, int)
License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-
#include "tdb_private.h"
/* check for an out of bounds access - if it is out of bounds then
if (!(tdb->flags & TDB_NOMMAP)) {
tdb->map_ptr = mmap(NULL, tdb->map_size,
PROT_READ|(tdb->read_only? 0:PROT_WRITE),
- MAP_SHARED|MAP_FILE, tdb->fd, 0);
+ MAP_SHARED, tdb->fd, 0);
/*
* NB. When mmap fails it returns MAP_FAILED *NOT* NULL !!!!
License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-#if 0
-#include "replace.h"
-#include "system/filesys.h"
-#include "system/time.h"
-#include "system/shmem.h"
-#include "system/select.h"
-#include "system/wait.h"
-#include "tdb.h"
-#endif
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
#include <unistd.h>
#include <stdint.h>
#include <stdio.h>
#include <errno.h>
#include <sys/param.h>
+#include <stddef.h>
#ifndef __STRING
#define __STRING(x) #x
typedef uint32_t tdb_len_t;
typedef uint32_t tdb_off_t;
-#ifndef offsetof
-#define offsetof(t,f) ((unsigned int)&((t *)0)->f)
-#endif
-
#define TDB_MAGIC_FOOD "TDB file\n"
#define TDB_VERSION (0x26011967 + 6)
#define TDB_MAGIC (0x26011999U)
return 0;
}
+void free_charset_names(void)
+{
+ for (int ch = 0; ch < MAX_CHARSETS; ch++) {
+ if (charset_names[ch]) {
+ free(charset_names[ch]);
+ charset_names[ch] = NULL;
+ }
+ }
+}
+
static struct charset_functions* get_charset_functions (charset_t ch)
{
if (charsets[ch] != NULL)
* for e.g. HFS cdroms.
*/
-static size_t pull_charset_flags (charset_t from_set, charset_t cap_set, const char *src, size_t srclen, char* dest, size_t destlen, uint16_t *flags)
+static size_t pull_charset_flags (charset_t from_set, charset_t to_set, charset_t cap_set, const char *src, size_t srclen, char* dest, size_t destlen, uint16_t *flags)
{
const uint16_t option = (flags ? *flags : 0);
size_t i_len, o_len;
char* outbuf = dest;
atalk_iconv_t descriptor;
atalk_iconv_t descriptor_cap;
+ char escch; /* 150210: uninitialized OK, depends on j */
if (srclen == (size_t)-1)
srclen = strlen(src) + 1;
i_len=srclen;
o_len=destlen;
+ if ((option & CONV_ESCAPEDOTS) && i_len >= 2 && inbuf[0] == '.') {
+ if (o_len < 6) {
+ errno = E2BIG;
+ goto end;
+ }
+ ucs2_t ucs2 = ':';
+ memcpy(outbuf, &ucs2, sizeof(ucs2_t));
+ ucs2 = '2';
+ memcpy(outbuf + sizeof(ucs2_t), &ucs2, sizeof(ucs2_t));
+ ucs2 = 'e';
+ memcpy(outbuf + 2 * sizeof(ucs2_t), &ucs2, sizeof(ucs2_t));
+ outbuf += 6;
+ o_len -= 6;
+ inbuf++;
+ i_len--;
+ *flags |= CONV_REQESCAPE;
+ }
+
while (i_len > 0) {
for (j = 0; j < i_len; ++j)
- if (inbuf[j] == ':')
+ if (inbuf[j] == ':' || inbuf[j] == '/') {
+ escch = inbuf[j];
break;
+ }
j = i_len - j;
i_len -= j;
}
if (j) {
- /* we have a ':' */
+ /* we have a ':' or '/' */
i_len = j, j = 0;
- if ((option & CONV_UNESCAPEHEX)) {
- /* treat it as a CAP hex encoded char */
- char h[MAXPATHLEN];
- size_t hlen = 0;
-
- while (i_len >= 3 && inbuf[0] == ':' &&
- isxdigit(inbuf[1]) && isxdigit(inbuf[2])) {
- h[hlen++] = (hextoint(inbuf[1]) << 4) | hextoint(inbuf[2]);
- inbuf += 3;
- i_len -= 3;
- }
- if (hlen) {
- const char *h_buf = h;
- if (atalk_iconv(descriptor_cap, &h_buf, &hlen, &outbuf, &o_len) == (size_t)-1) {
- i_len += hlen * 3;
- inbuf -= hlen * 3;
- if (errno == EILSEQ && (option & CONV_IGNORE)) {
+ if (escch == ':') {
+ if ((option & CONV_UNESCAPEHEX)) {
+ /* treat it as a CAP hex encoded char */
+ char h[MAXPATHLEN];
+ size_t hlen = 0;
+
+ while (i_len >= 3 && inbuf[0] == ':' &&
+ isxdigit(inbuf[1]) && isxdigit(inbuf[2])) {
+ h[hlen++] = (hextoint(inbuf[1]) << 4) | hextoint(inbuf[2]);
+ inbuf += 3;
+ i_len -= 3;
+ }
+ if (hlen) {
+ const char *h_buf = h;
+ if (atalk_iconv(descriptor_cap, &h_buf, &hlen, &outbuf, &o_len) == (size_t)-1) {
+ i_len += hlen * 3;
+ inbuf -= hlen * 3;
+ if (errno == EILSEQ && (option & CONV_IGNORE)) {
+ *flags |= CONV_REQMANGLE;
+ return destlen - o_len;
+ }
+ goto end;
+ }
+ } else {
+ /* We have an invalid :xx sequence */
+ errno = EILSEQ;
+ if ((option & CONV_IGNORE)) {
*flags |= CONV_REQMANGLE;
return destlen - o_len;
}
goto end;
}
- } else {
- /* We have an invalid :xx sequence */
- errno = EILSEQ;
- if ((option & CONV_IGNORE)) {
- *flags |= CONV_REQMANGLE;
- return destlen - o_len;
+ } else if (option & CONV_ESCAPEHEX) {
+ if (o_len < 6) {
+ errno = E2BIG;
+ goto end;
}
- goto end;
+ ucs2_t ucs2 = ':';
+ memcpy(outbuf, &ucs2, sizeof(ucs2_t));
+ ucs2 = '3';
+ memcpy(outbuf + sizeof(ucs2_t), &ucs2, sizeof(ucs2_t));
+ ucs2 = 'a';
+ memcpy(outbuf + 2 * sizeof(ucs2_t), &ucs2, sizeof(ucs2_t));
+ outbuf += 6;
+ o_len -= 6;
+ inbuf++;
+ i_len--;
+ } else if (to_set == CH_UTF8_MAC || to_set == CH_MAC) {
+ /* convert to a '/' */
+ ucs2_t slash = 0x002f;
+ memcpy(outbuf, &slash, sizeof(ucs2_t));
+ outbuf += 2;
+ o_len -= 2;
+ inbuf++;
+ i_len--;
+ } else {
+ /* keep as ':' */
+ ucs2_t ucs2 = 0x003a;
+ memcpy(outbuf, &ucs2, sizeof(ucs2_t));
+ outbuf += 2;
+ o_len -= 2;
+ inbuf++;
+ i_len--;
}
} else {
- /* a ':' that we just convert to a '/' */
- ucs2_t slash = 0x002f;
- memcpy(outbuf, &slash, sizeof(ucs2_t));
- outbuf += 2;
- o_len -= 2;
- inbuf++;
- i_len--;
+ /* '/' */
+ if (option & CONV_ESCAPEHEX) {
+ if (o_len < 6) {
+ errno = E2BIG;
+ goto end;
+ }
+ ucs2_t ucs2 = ':';
+ memcpy(outbuf, &ucs2, sizeof(ucs2_t));
+ ucs2 = '2';
+ memcpy(outbuf + sizeof(ucs2_t), &ucs2, sizeof(ucs2_t));
+ ucs2 = 'f';
+ memcpy(outbuf + 2 * sizeof(ucs2_t), &ucs2, sizeof(ucs2_t));
+ outbuf += 6;
+ o_len -= 6;
+ inbuf++;
+ i_len--;
+ } else if ((from_set == CH_UTF8_MAC || from_set == CH_MAC)
+ && (to_set != CH_UTF8_MAC || to_set != CH_MAC)) {
+ /* convert to ':' */
+ ucs2_t ucs2 = 0x003a;
+ memcpy(outbuf, &ucs2, sizeof(ucs2_t));
+ outbuf += 2;
+ o_len -= 2;
+ inbuf++;
+ i_len--;
+ } else {
+ /* keep as '/' */
+ ucs2_t ucs2 = 0x002f;
+ memcpy(outbuf, &ucs2, sizeof(ucs2_t));
+ outbuf += 2;
+ o_len -= 2;
+ inbuf++;
+ i_len--;
+ }
}
}
}
char* outbuf = (char*)dest;
atalk_iconv_t descriptor;
atalk_iconv_t descriptor_cap;
- char escch; /* 150210: uninitialized OK, depends on j */
descriptor = conv_handles[CH_UCS2][to_set];
descriptor_cap = conv_handles[CH_UCS2][cap_set];
i_len=srclen;
o_len=destlen;
- if ((option & CONV_ESCAPEDOTS) &&
- i_len >= 2 && SVAL(inbuf, 0) == 0x002e) { /* 0x002e = . */
- if (o_len < 3) {
- errno = E2BIG;
- goto end;
- }
- *outbuf++ = ':';
- *outbuf++ = '2';
- *outbuf++ = 'e';
- o_len -= 3;
- inbuf += 2;
- i_len -= 2;
- *flags |= CONV_REQESCAPE;
- }
-
while (i_len >= 2) {
- for (i = 0; i < i_len; i += 2) {
- ucs2_t c = SVAL(inbuf, i);
- switch (c) {
- case 0x003a: /* 0x003a = ':' */
- if ( ! (option & CONV_ALLOW_COLON)) {
- errno = EILSEQ;
- goto end;
- }
- escch = c;
- j = i_len - i;
- i_len = i;
- break;
- case 0x002f: /* 0x002f = '/' */
- if (option & CONV_ALLOW_SLASH) break;
- escch = c;
- j = i_len - i;
- i_len = i;
- break;
- }
- }
while (i_len > 0 &&
atalk_iconv(descriptor, &inbuf, &i_len, &outbuf, &o_len) == (size_t)-1) {
if (errno == EILSEQ) {
}
goto end;
}
+ } /* while (i_len >= 2) */
- if (j) {
- /* we have a ':' or '/' */
- i_len = j, j = 0;
-
- if ((option & CONV_ESCAPEHEX)) {
- /* CAP hex encode it */
- if (o_len < 3) {
- errno = E2BIG;
- goto end;
- }
- switch (escch) {
- case '/':
- *outbuf++ = ':';
- *outbuf++ = '2';
- *outbuf++ = 'f';
- break;
- case ':':
- *outbuf++ = ':';
- *outbuf++ = '3';
- *outbuf++ = 'a';
- break;
- default:
- /*
- * THIS SHOULD NEVER BE REACHED !!!
- * As a safety net I put in a ' ' here
- */
- *outbuf++ = ':';
- *outbuf++ = '2';
- *outbuf++ = '0';
- break;
- }
- o_len -= 3;
- inbuf += 2;
- i_len -= 2;
- } else {
- switch (escch) {
- case '/':
- case ':':
- *outbuf++ = ':';
- break;
- default: /* should never be reached */
- *outbuf++ = ' ';
- break;
- }
- o_len--;
- inbuf += 2;
- i_len -= 2;
- }
- }
- }
if (i_len > 0) errno = EINVAL;
end:
return (i_len + j == 0 || (option & CONV_FORCE)) ? destlen - o_len : (size_t)-1;
lazy_initialize_conv();
/* convert from_set to UCS2 */
- if ((size_t)(-1) == ( o_len = pull_charset_flags( from_set, cap_charset, src, src_len,
+ if ((size_t)(-1) == ( o_len = pull_charset_flags( from_set, to_set, cap_charset, src, src_len,
(char *) buffer, sizeof(buffer) -2, flags)) ) {
LOG(log_error, logtype_default, "Conversion failed ( %s to CH_UCS2 )", charset_name(from_set));
return (size_t) -1;
/*
- * $Id: mac_roman.h,v 1.2 2005-04-28 20:50:04 bfernhomberg Exp $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
while (*a && *b) {
if ((0xD800 <= *a) && (*a < 0xDC00)) {
- if (ret = tolower_sp((uint32_t)*a << 16 | (uint32_t)a[1]) - tolower_sp((uint32_t)*b << 16 | (uint32_t)b[1])) return ret;
+ if ((ret = tolower_sp((uint32_t)*a << 16 | (uint32_t)a[1]) - tolower_sp((uint32_t)*b << 16 | (uint32_t)b[1]))) return ret;
a++;
b++;
if (!(*a && *b)) return (tolower_w(*a) - tolower_w(*b)); /* avoid buffer over run */
} else {
- if (ret = tolower_w(*a) - tolower_w(*b)) return ret;
+ if ((ret = tolower_w(*a) - tolower_w(*b))) return ret;
}
a++;
b++;
while ((n < len) && *a && *b) {
if ((0xD800 <= *a) && (*a < 0xDC00)) {
- if (ret = tolower_sp((uint32_t)*a << 16 | (uint32_t)a[1]) - tolower_sp((uint32_t)*b << 16 | (uint32_t)b[1])) return ret;
+ if ((ret = tolower_sp((uint32_t)*a << 16 | (uint32_t)a[1]) - tolower_sp((uint32_t)*b << 16 | (uint32_t)b[1]))) return ret;
a++;
b++;
n++;
if (!((n < len) && *a && *b)) return (tolower_w(*a) - tolower_w(*b));
} else {
- if (ret = tolower_w(*a) - tolower_w(*b)) return ret;
+ if ((ret = tolower_w(*a) - tolower_w(*b))) return ret;
}
a++;
b++;
base_sp = ((uint32_t)base << 16) | (uint32_t)comb;
do {
comb_sp = ((uint32_t)in[1] << 16) | (uint32_t)in[2];
- if (result_sp = do_precomposition_sp(base_sp, comb_sp)) {
+ if ((result_sp = do_precomposition_sp(base_sp, comb_sp))) {
base_sp = result_sp;
i += 4;
in +=2;
}
/* Binary Search for BMP */
- else if (result = do_precomposition(base, comb)) {
+ else if ((result = do_precomposition(base, comb))) {
base = result;
}
cnid.c \
fault.c \
getiface.c \
+ gettok.c \
locking.c \
logger.c \
module.c \
#include <atalk/ftw.h>
+#ifndef HAVE_MEMPCPY
#define mempcpy(D, S, N) ((void *) ((char *) memcpy (D, S, N) + (N)))
+#endif
#define NDEBUG 1
#include <assert.h>
--- /dev/null
+/*
+ *
+ * Copyright (c) 1990,1994 Regents of The University of Michigan.
+ * All Rights Reserved. See COPYRIGHT.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include <sys/param.h>
+#include <string.h>
+#include <ctype.h>
+#include <pwd.h>
+
+#include <atalk/globals.h>
+
+static char *l_curr;
+static char *l_end;
+
+void initline( int len, char *line)
+{
+ l_curr = line;
+ l_end = line + len;
+}
+
+#define ST_QUOTE 0
+#define ST_WORD 1
+#define ST_BEGIN 2
+
+int
+parseline(int len, char *token)
+{
+ char *p, *e;
+ int state;
+
+ state = ST_BEGIN;
+ p = token;
+ e = token + len;
+
+ for (;;) {
+ if ( l_curr > l_end ) { /* end of line */
+ *token = '\0';
+ return( -1 );
+ }
+
+ switch ( *l_curr ) {
+ case '"' :
+ if ( state == ST_QUOTE ) {
+ state = ST_WORD;
+ } else {
+ state = ST_QUOTE;
+ }
+ break;
+
+ case '\0' :
+ case '\t' :
+ case '\n' :
+ case ' ' :
+ if ( state == ST_WORD ) {
+ *p = '\0';
+ return( p - token );
+ }
+ if ( state != ST_QUOTE ) {
+ break;
+ }
+ /* FALL THROUGH */
+
+ default :
+ if ( state == ST_BEGIN ) {
+ state = ST_WORD;
+ }
+ if ( p > e ) { /* end of token */
+ *token = '\0';
+ return( -1 );
+ }
+ *p++ = *l_curr;
+ break;
+ }
+
+ l_curr++;
+ }
+}
+
+#ifdef notdef
+void parseline(char *token, char *user)
+{
+ char *p = pos, *t = token, *u, *q, buf[ MAXPATHLEN ];
+ struct passwd *pwent;
+ int quoted = 0;
+
+ while ( isspace( *p )) {
+ p++;
+ }
+
+ /*
+ * If we've reached the end of the line, or a comment,
+ * don't return any more tokens.
+ */
+ if ( *p == '\0' || *p == '#' ) {
+ *token = '\0';
+ return;
+ }
+
+ if ( *p == '"' ) {
+ p++;
+ quoted = 1;
+ }
+ while ( *p != '\0' && ( quoted || !isspace( *p ))) {
+ if ( *p == '"' ) {
+ if ( quoted ) {
+ *t = '\0';
+ break;
+ }
+ quoted = 1;
+ p++;
+ } else {
+ *t++ = *p++;
+ }
+ }
+ pos = p;
+ *t = '\0';
+
+ /*
+ * We got to the end of the line without closing an open quote
+ */
+ if ( *p == '\0' && quoted ) {
+ *token = '\0';
+ return;
+ }
+
+ t = token;
+ if ( *t == '~' ) {
+ t++;
+ if ( *t == '\0' || *t == '/' ) {
+ u = user;
+ if ( *t == '/' ) {
+ t++;
+ }
+ } else {
+ u = t;
+ if (( q = strchr( t, '/' )) == NULL ) {
+ t = "";
+ } else {
+ *q = '\0';
+ t = q + 1;
+ }
+ }
+ if ( u == NULL || ( pwent = getpwnam( u )) == NULL ) {
+ *token = '\0';
+ return;
+ }
+ strcpy( buf, pwent->pw_dir );
+ if ( *t != '\0' ) {
+ strcat( buf, "/" );
+ strcat( buf, t );
+ }
+ strcpy( token, buf );
+ }
+ return;
+}
+#endif /* notdef */
/*
- $Id: locking.c,v 1.4 2010-01-05 19:05:52 franklahm Exp $
Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
This program is free software; you can redistribute it and/or modify
"CNID", \
"AFPDaemon", \
"DSI", \
- "ATalkDaemon", \
- "PAPDaemon", \
"UAMS", \
- "end_of_list_marker"} \
+ "FCE", \
+ "ad", \
+ "end_of_list_marker"}
/* =========================================================================
Config
DEFAULT_LOG_CONFIG, /* logtype_cnid */
DEFAULT_LOG_CONFIG, /* logtype_afpd */
DEFAULT_LOG_CONFIG, /* logtype_dsi */
- DEFAULT_LOG_CONFIG, /* logtype_atalkd */
- DEFAULT_LOG_CONFIG, /* logtype_papd */
- DEFAULT_LOG_CONFIG /* logtype_uams */
+ DEFAULT_LOG_CONFIG, /* logtype_uams */
+ DEFAULT_LOG_CONFIG, /* logtype_fce */
+ DEFAULT_LOG_CONFIG /* logtype_ad */
};
static void syslog_setup(int loglevel, enum logtypes logtype, int display_options, int facility);
/*
- * $Id: module.c,v 1.5 2003-02-17 02:03:12 srittau Exp $
*/
#ifdef HAVE_CONFIG_H
#include <atalk/uuid.h>
#include <atalk/netatalk_conf.h>
#include <atalk/bstrlib.h>
+#include <atalk/bstradd.h>
#define VOLPASSLEN 8
#ifndef UUID_PRINTABLE_STRING_LENGTH
/*!
* check access list
*
- * this function wants something of the following form:
- * "@group,name,name2,@group2,name3" or "@group name name2 @group2 name3"
+ * this function wants a string consisting of names seperated by comma
+ * or space. Names may be quoted within a pair of quotes. Groups are
+ * denoted by a leading @ symbol.
+ * Example:
+ * user1 user2, user3, @group1 @group2, @group3 "user name1", "@group name1"
* A NULL argument allows everybody to have access.
* We return three things:
* -1: no list
*/
static int accessvol(const AFPObj *obj, const char *args, const char *name)
{
- char buf[MAXPATHLEN + 1], *p;
+ EC_INIT;
+ char *names = NULL, *p;
struct group *gr;
if (!args)
- return -1;
+ EC_EXIT_STATUS(-1);
- strlcpy(buf, args, sizeof(buf));
- if ((p = strtok(buf, ", ")) == NULL) /* nothing, return okay */
- return -1;
+ EC_NULL_LOG( names = strdup(args) );
+
+ if ((p = strtok_quote(names, ", ")) == NULL) /* nothing, return okay */
+ EC_EXIT_STATUS(-1);
while (p) {
if (*p == '@') { /* it's a group */
if ((gr = getgrnam(p + 1)) && gmem(gr->gr_gid, obj->ngroups, obj->groups))
- return 1;
+ EC_EXIT_STATUS(1);
} else if (strcasecmp(p, name) == 0) /* it's a user name */
- return 1;
- p = strtok(NULL, ", ");
+ EC_EXIT_STATUS(1);
+ p = strtok_quote(NULL, ", ");
}
- return 0;
+EC_CLEANUP:
+ if (names)
+ free(names);
+ EC_EXIT;
}
static int hostaccessvol(const AFPObj *obj, const char *volname, const char *args)
*/
static const char *getoption(const dictionary *conf, const char *vol, const char *opt, const char *defsec, const char *defval)
{
- EC_INIT;
const char *result;
if ((!(result = iniparser_getstring(conf, vol, opt, NULL))) && (defsec != NULL))
result = iniparser_getstring(conf, defsec, opt, NULL);
-EC_CLEANUP:
if (result == NULL)
result = defval;
return result;
*/
static int getoption_bool(const dictionary *conf, const char *vol, const char *opt, const char *defsec, int defval)
{
- EC_INIT;
int result;
if (((result = iniparser_getboolean(conf, vol, opt, -1)) == -1) && (defsec != NULL))
result = iniparser_getboolean(conf, defsec, opt, -1);
-EC_CLEANUP:
if (result == -1)
result = defval;
return result;
* @param pwd (r) struct passwd of logged in user, may be NULL in master afpd
* @param section (r) volume name wo variables expanded (exactly as in iniconfig)
* @param name (r) volume name
- * @param path (r) volume path
+ * @param path_in (r) volume path
* @param preset (r) default preset, may be NULL
* @returns vol on success, NULL on error
*/
const struct passwd *pwd,
const char *section,
const char *name,
- const char *path,
+ const char *path_in,
const char *preset)
{
EC_INIT;
struct vol *volume = NULL;
int i, suffixlen, vlen, tmpvlen, u8mvlen, macvlen;
- char *tmpname;
+ char tmpname[AFPVOL_U8MNAMELEN+1];
+ char path[MAXPATHLEN + 1];
ucs2_t u8mtmpname[(AFPVOL_U8MNAMELEN+1)*2], mactmpname[(AFPVOL_MACNAMELEN+1)*2];
char suffix[6]; /* max is #FFFF */
uint16_t flags;
const char *val;
char *p, *q;
+ strlcpy(path, path_in, MAXPATHLEN);
+
LOG(log_debug, logtype_afpd, "createvol(volume: '%s', path: \"%s\", preset: '%s'): BEGIN",
name, path, preset ? preset : "-");
if ( name == NULL || *name == '\0' ) {
- if ((name = strrchr( path, '/' )) == NULL) {
+ if ((name = strrchr( path, '/' )) == NULL)
EC_FAIL;
- }
-
/* if you wish to share /, you need to specify a name. */
if (*++name == '\0')
EC_FAIL;
}
/* Once volumes are loaded, we never change options again, we just delete em when they're removed from afp.conf */
+
for (struct vol *vol = Volumes; vol; vol = vol->v_next) {
- if (STRCMP(path, ==, vol->v_path)) {
- LOG(log_debug, logtype_afpd, "createvol('%s'): already loaded", name);
+ if (STRCMP(name, ==, vol->v_localname) && vol->v_deleted) {
+ /*
+ * reloading config, volume still present, nothing else to do,
+ * we don't change options for volumes once they're loaded
+ */
vol->v_deleted = 0;
volume = vol;
- goto EC_CLEANUP;
+ EC_EXIT_STATUS(0);
+ }
+ if (STRCMP(path, ==, vol->v_path)) {
+ LOG(log_note, logtype_afpd, "volume \"%s\" path \"%s\" is the same as volumes \"%s\" path",
+ name, path, vol->v_configname);
+ EC_EXIT_STATUS(0);
}
+ /*
+ * We could check for nested volume paths here, but
+ * nobody was able to come up with an implementation yet,
+ * that is simple, fast and correct.
+ */
}
/*
volume->v_vfs_ea = AFPVOL_EA_AUTO;
volume->v_umask = obj->options.umask;
- if (val = getoption(obj->iniconfig, section, "password", preset, NULL))
+ if ((val = getoption(obj->iniconfig, section, "password", preset, NULL)))
EC_NULL( volume->v_password = strdup(val) );
- if (val = getoption(obj->iniconfig, section, "veto files", preset, NULL))
+ if ((val = getoption(obj->iniconfig, section, "veto files", preset, NULL)))
EC_NULL( volume->v_veto = strdup(val) );
/* vol charset is in [G] and [V] */
- if (val = getoption(obj->iniconfig, section, "vol charset", preset, NULL)) {
+ if ((val = getoption(obj->iniconfig, section, "vol charset", preset, NULL))) {
if (strcasecmp(val, "UTF-8") == 0) {
val = strdup("UTF8");
}
EC_NULL( volume->v_volcodepage = strdup(obj->options.volcodepage) );
/* mac charset is in [G] and [V] */
- if (val = getoption(obj->iniconfig, section, "mac charset", preset, NULL)) {
+ if ((val = getoption(obj->iniconfig, section, "mac charset", preset, NULL))) {
if (strncasecmp(val, "MAC", 3) != 0) {
LOG(log_warning, logtype_afpd, "Is '%s' really mac charset? ", val);
}
EC_NULL( volume->v_maccodepage = strdup(obj->options.maccodepage) );
vlen = strlen(name);
- tmpname = strdup(name);
+ strlcpy(tmpname, name, sizeof(tmpname));
for(i = 0; i < vlen; i++)
if(tmpname[i] == '/') tmpname[i] = ':';
bstring dbpath;
- EC_NULL_LOG( val = iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "vol dbpath", _PATH_STATEDIR "CNID/") );
- EC_NULL_LOG( dbpath = bformat("%s/%s/", val, tmpname) );
- EC_NULL_LOG( volume->v_dbpath = strdup(bdata(dbpath)) );
+ EC_NULL( val = 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)) );
bdestroy(dbpath);
- if (val = getoption(obj->iniconfig, section, "cnid scheme", preset, NULL))
+ if ((val = getoption(obj->iniconfig, section, "cnid scheme", preset, NULL)))
EC_NULL( volume->v_cnidscheme = strdup(val) );
else
volume->v_cnidscheme = strdup(DEFAULT_CNID_SCHEME);
- if (val = getoption(obj->iniconfig, section, "umask", preset, NULL))
+ if ((val = getoption(obj->iniconfig, section, "umask", preset, NULL)))
volume->v_umask = (int)strtol(val, NULL, 8);
- if (val = getoption(obj->iniconfig, section, "directory perm", preset, NULL))
+ if ((val = getoption(obj->iniconfig, section, "directory perm", preset, NULL)))
volume->v_dperm = (int)strtol(val, NULL, 8);
- if (val = getoption(obj->iniconfig, section, "file perm", preset, NULL))
+ if ((val = getoption(obj->iniconfig, section, "file perm", preset, NULL)))
volume->v_fperm = (int)strtol(val, NULL, 8);
- if (val = getoption(obj->iniconfig, section, "vol size limit", preset, NULL))
+ if ((val = getoption(obj->iniconfig, section, "vol size limit", preset, NULL)))
volume->v_limitsize = (uint32_t)strtoul(val, NULL, 10);
- if (val = getoption(obj->iniconfig, section, "preexec", preset, NULL))
+ if ((val = getoption(obj->iniconfig, section, "preexec", preset, NULL)))
EC_NULL( volume->v_preexec = volxlate(obj, NULL, MAXPATHLEN, val, pwd, path, name) );
- if (val = getoption(obj->iniconfig, section, "postexec", preset, NULL))
+ if ((val = getoption(obj->iniconfig, section, "postexec", preset, NULL)))
EC_NULL( volume->v_postexec = volxlate(obj, NULL, MAXPATHLEN, val, pwd, path, name) );
- if (val = getoption(obj->iniconfig, section, "root preexec", preset, NULL))
+ if ((val = getoption(obj->iniconfig, section, "root preexec", preset, NULL)))
EC_NULL( volume->v_root_preexec = volxlate(obj, NULL, MAXPATHLEN, val, pwd, path, name) );
- if (val = getoption(obj->iniconfig, section, "root postexec", preset, NULL))
+ if ((val = getoption(obj->iniconfig, section, "root postexec", preset, NULL)))
EC_NULL( volume->v_root_postexec = volxlate(obj, NULL, MAXPATHLEN, val, pwd, path, name) );
- if (val = getoption(obj->iniconfig, section, "appledouble", preset, NULL)) {
+ if ((val = getoption(obj->iniconfig, section, "appledouble", preset, NULL))) {
if (strcmp(val, "v2") == 0)
volume->v_adouble = AD_VERSION2;
else if (strcmp(val, "ea") == 0)
volume->v_adouble = AD_VERSION;
}
- if (val = getoption(obj->iniconfig, section, "cnid server", preset, NULL)) {
+ if ((val = getoption(obj->iniconfig, section, "cnid server", preset, NULL))) {
EC_NULL( p = strdup(val) );
volume->v_cnidserver = p;
- if (q = strrchr(val, ':')) {
+ if ((q = strrchr(val, ':'))) {
*q++ = 0;
volume->v_cnidport = strdup(q);
} else {
volume->v_cnidport = strdup(obj->options.Cnid_port);
}
- if (val = getoption(obj->iniconfig, section, "ea", preset, NULL)) {
+ if ((val = getoption(obj->iniconfig, section, "ea", preset, NULL))) {
if (strcasecmp(val, "ad") == 0)
volume->v_vfs_ea = AFPVOL_EA_AD;
else if (strcasecmp(val, "sys") == 0)
volume->v_vfs_ea = AFPVOL_EA_NONE;
}
- if (val = getoption(obj->iniconfig, section, "casefold", preset, NULL)) {
+ if ((val = getoption(obj->iniconfig, section, "casefold", preset, NULL))) {
if (strcasecmp(val, "tolower") == 0)
volume->v_casefold = AFPVOL_UMLOWER;
else if (strcasecmp(val, "toupper") == 0)
#endif
if (!getoption_bool(obj->iniconfig, section, "convert appledouble", preset, 1))
volume->v_flags |= AFPVOL_NOV2TOEACONV;
+ if (getoption_bool(obj->iniconfig, section, "follow symlinks", preset, 0))
+ volume->v_flags |= AFPVOL_FOLLOWSYM;
if (getoption_bool(obj->iniconfig, section, "preexec close", preset, 0))
volume->v_preexec_close = 1;
volume->v_ad_options |= ADVOL_UNIXPRIV;
if ((volume->v_flags & AFPVOL_INV_DOTS))
volume->v_ad_options |= ADVOL_INVDOTS;
+ if ((volume->v_flags & AFPVOL_FOLLOWSYM))
+ volume->v_ad_options |= ADVOL_FOLLO_SYML;
/* Mac to Unix conversion flags*/
if ((volume->v_flags & AFPVOL_EILSEQ))
/* Unicode Volume Name */
/* Firstly convert name from unixcharset to UTF8-MAC */
- flags = CONV_IGNORE | CONV_ALLOW_SLASH;
+ flags = CONV_IGNORE;
tmpvlen = convert_charset(obj->options.unixcharset, CH_UTF8_MAC, 0, name, vlen, tmpname, AFPVOL_U8MNAMELEN, &flags);
if (tmpvlen <= 0) {
strcpy(tmpname, "???");
/* Do we have to mangle ? */
if ( (flags & CONV_REQMANGLE) || (tmpvlen > obj->options.volnamelen)) {
if (tmpvlen + suffixlen > obj->options.volnamelen) {
- flags = CONV_FORCE | CONV_ALLOW_SLASH;
+ flags = CONV_FORCE;
tmpvlen = convert_charset(obj->options.unixcharset, CH_UTF8_MAC, 0, name, vlen, tmpname, obj->options.volnamelen - suffixlen, &flags);
tmpname[tmpvlen >= 0 ? tmpvlen : 0] = 0;
}
/* Maccharset Volume Name */
/* Firsty convert name from unixcharset to maccharset */
- flags = CONV_IGNORE | CONV_ALLOW_SLASH;
+ flags = CONV_IGNORE;
tmpvlen = convert_charset(obj->options.unixcharset, obj->options.maccharset, 0, name, vlen, tmpname, AFPVOL_U8MNAMELEN, &flags);
if (tmpvlen <= 0) {
strcpy(tmpname, "???");
/* Do we have to mangle ? */
if ( (flags & CONV_REQMANGLE) || (tmpvlen > AFPVOL_MACNAMELEN)) {
if (tmpvlen + suffixlen > AFPVOL_MACNAMELEN) {
- flags = CONV_FORCE | CONV_ALLOW_SLASH;
+ flags = CONV_FORCE;
tmpvlen = convert_charset(obj->options.unixcharset,
obj->options.maccharset,
0,
EC_NULL( volume->v_localname = strdup(name) );
EC_NULL( volume->v_u8mname = strdup_w(u8mtmpname) );
EC_NULL( volume->v_macname = strdup_w(mactmpname) );
- EC_NULL( volume->v_path = malloc(strlen(path) + 1) );
-
+ EC_NULL( volume->v_path = strdup(path) );
+
volume->v_name = utf8_encoding(obj) ? volume->v_u8mname : volume->v_macname;
- strcpy(volume->v_path, path);
#ifdef __svr4__
volume->v_qfd = -1;
EC_CLEANUP:
LOG(log_debug, logtype_afpd, "createvol: END: %d", ret);
if (ret != 0) {
- if (volume) {
+ if (volume)
volume_free(volume);
- free(volume);
- }
return NULL;
}
return volume;
EC_INIT;
static int regexerr = -1;
static regex_t reg;
- char path[MAXPATHLEN + 1];
+ char *realvolpath;
char volname[AFPVOL_U8MNAMELEN + 1];
- char tmp[MAXPATHLEN + 1];
+ char path[MAXPATHLEN + 1], tmp[MAXPATHLEN + 1];
const char *preset, *default_preset, *p, *basedir;
- char *q, *u;
int i;
- struct passwd *pw;
regmatch_t match[1];
LOG(log_debug, logtype_afpd, "readvolfile: BEGIN");
/* no user home */
continue;
+ if ((realpath(pwent->pw_dir, tmp)) == NULL)
+ continue;
+
/* check if user home matches our "basedir regex" */
if ((basedir = iniparser_getstring(obj->iniconfig, INISEC_HOMES, "basedir regex", NULL)) == NULL) {
LOG(log_error, logtype_afpd, "\"basedir regex =\" must be defined in [Homes] section");
char errbuf[1024];
regerror(regexerr, ®, errbuf, sizeof(errbuf));
LOG(log_debug, logtype_default, "readvolfile: bad basedir regex: %s", errbuf);
+ continue;
}
- if (regexec(®, pwent->pw_dir, 1, match, 0) == REG_NOMATCH) {
- LOG(log_debug, logtype_default, "readvolfile: user home \"%s\" doesn't match basedir regex \"%s\"",
- pwent->pw_dir, basedir);
+ if (regexec(®, tmp, 1, match, 0) == REG_NOMATCH) {
+ LOG(log_error, logtype_default, "readvolfile: user home \"%s\" doesn't match basedir regex \"%s\"",
+ tmp, basedir);
continue;
}
- strlcpy(tmp, pwent->pw_dir, MAXPATHLEN);
- strlcat(tmp, "/", MAXPATHLEN);
- if (p = iniparser_getstring(obj->iniconfig, INISEC_HOMES, "path", NULL))
+ if ((p = iniparser_getstring(obj->iniconfig, INISEC_HOMES, "path", NULL))) {
+ strlcat(tmp, "/", MAXPATHLEN);
strlcat(tmp, p, MAXPATHLEN);
+ }
} else {
/* Get path */
if ((p = iniparser_getstring(obj->iniconfig, secname, "path", NULL)) == NULL)
preset = iniparser_getstring(obj->iniconfig, secname, "vol preset", NULL);
- creatvol(obj, pwent, secname, volname, path, preset ? preset : default_preset ? default_preset : NULL);
+ if ((realvolpath = realpath_safe(path)) == NULL)
+ continue;
+
+ creatvol(obj, pwent, secname, volname, realvolpath, preset ? preset : default_preset ? default_preset : NULL);
+ free(realvolpath);
+ }
+
+// EC_CLEANUP:
+ EC_EXIT;
+}
+
+static struct extmap *Extmap = NULL, *Defextmap = NULL;
+static int Extmap_cnt;
+
+static int setextmap(char *ext, char *type, char *creator)
+{
+ EC_INIT;
+ struct extmap *em;
+ int cnt;
+
+ if (Extmap == NULL) {
+ EC_NULL_LOG( Extmap = calloc(1, sizeof( struct extmap )) );
+ }
+
+ ext++;
+
+ for (em = Extmap, cnt = 0; em->em_ext; em++, cnt++)
+ if ((strdiacasecmp(em->em_ext, ext)) == 0)
+ goto EC_CLEANUP;
+
+ EC_NULL_LOG( Extmap = realloc(Extmap, sizeof(struct extmap) * (cnt + 2)) );
+ (Extmap + cnt + 1)->em_ext = NULL;
+ em = Extmap + cnt;
+
+ EC_NULL( em->em_ext = strdup(ext) );
+
+ if ( *type == '\0' ) {
+ memcpy(em->em_type, "\0\0\0\0", sizeof( em->em_type ));
+ } else {
+ memcpy(em->em_type, type, sizeof( em->em_type ));
+ }
+ if ( *creator == '\0' ) {
+ memcpy(em->em_creator, "\0\0\0\0", sizeof( em->em_creator ));
+ } else {
+ memcpy(em->em_creator, creator, sizeof( em->em_creator ));
+ }
+
+EC_CLEANUP:
+ EC_EXIT;
+}
+
+/* -------------------------- */
+static int extmap_cmp(const void *map1, const void *map2)
+{
+ const struct extmap *em1 = map1;
+ const struct extmap *em2 = map2;
+ return strdiacasecmp(em1->em_ext, em2->em_ext);
+}
+
+static void sortextmap( void)
+{
+ struct extmap *em;
+
+ Extmap_cnt = 0;
+ if ((em = Extmap) == NULL) {
+ return;
+ }
+ while (em->em_ext) {
+ em++;
+ Extmap_cnt++;
+ }
+ if (Extmap_cnt) {
+ qsort(Extmap, Extmap_cnt, sizeof(struct extmap), extmap_cmp);
+ if (*Extmap->em_ext == 0) {
+ /* the first line is really "." the default entry,
+ * we remove the leading '.' in setextmap
+ */
+ Defextmap = Extmap;
+ }
+ }
+}
+
+static void free_extmap( void)
+{
+ struct extmap *em;
+
+ if (Extmap) {
+ for ( em = Extmap; em->em_ext; em++) {
+ free (em->em_ext);
+ }
+ free(Extmap);
+ Extmap = NULL;
+ Defextmap = Extmap;
+ Extmap_cnt = 0;
+ }
+}
+
+static int ext_cmp_key(const void *key, const void *obj)
+{
+ const char *p = key;
+ const struct extmap *em = obj;
+ return strdiacasecmp(p, em->em_ext);
+}
+
+struct extmap *getextmap(const char *path)
+{
+ char *p;
+ struct extmap *em;
+
+ if (!Extmap_cnt || NULL == ( p = strrchr( path, '.' )) ) {
+ return( Defextmap );
+ }
+ p++;
+ if (!*p) {
+ return( Defextmap );
+ }
+ em = bsearch(p, Extmap, Extmap_cnt, sizeof(struct extmap), ext_cmp_key);
+ if (em) {
+ return( em );
+ } else {
+ return( Defextmap );
+ }
+}
+
+struct extmap *getdefextmap(void)
+{
+ return( Defextmap );
+}
+
+static int readextmap(const char *file)
+{
+ EC_INIT;
+ FILE *fp;
+ char ext[256];
+ char buf[256];
+ char type[5], creator[5];
+
+ LOG(log_debug, logtype_afpd, "readextmap: loading \"%s\"", file);
+
+ EC_NULL_LOGSTR( fp = fopen(file, "r"), "Couldn't open extension maping file %s", file);
+
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ initline(strlen(buf), buf);
+ parseline(sizeof(ext) - 1, ext);
+
+ switch (ext[0]) {
+ case '.' :
+ parseline(sizeof(type) - 1, type);
+ parseline(sizeof(creator) - 1, creator);
+ setextmap(ext, type, creator);
+ LOG(log_debug, logtype_afpd, "readextmap: mapping: '%s' -> %s/%s", ext, type, creator);
+ break;
+ }
}
+ sortextmap();
+ EC_ZERO( fclose(fp) );
+
+ LOG(log_debug, logtype_afpd, "readextmap: done", file);
+
EC_CLEANUP:
EC_EXIT;
}
}
/*!
- * Free all resources allocated in a struct vol, only struct dir *v_root can't be freed
+ * Free all resources allocated in a struct vol in load_volumes()
+ *
+ * Actually opening a volume (afp_openvol()) will allocate additional
+ * ressources which are freed in closevol()
*/
void volume_free(struct vol *vol)
{
- LOG(log_debug, logtype_afpd, "volume_free('%s'): BEGIN", vol->v_localname);
-
+ free(vol->v_configname);
free(vol->v_localname);
free(vol->v_u8mname);
free(vol->v_macname);
free(vol->v_uuid);
free(vol->v_cnidserver);
free(vol->v_cnidport);
+ free(vol->v_preexec);
free(vol->v_root_preexec);
free(vol->v_postexec);
+ free(vol->v_root_postexec);
- LOG(log_debug, logtype_afpd, "volume_free: END");
+ free(vol);
}
/*!
* @param obj (r) handle
* @param delvol_fn (r) callback called for deleted volumes
*/
-int load_volumes(AFPObj *obj, void (*delvol_fn)(const AFPObj *obj, struct vol *))
+int load_volumes(AFPObj *obj)
{
EC_INIT;
int fd = -1;
EC_ZERO_LOG( readvolfile(obj, pwent) );
- for ( vol = Volumes; vol; vol = vol->v_next ) {
- if (vol->v_deleted) {
+ struct vol *p, *prevvol;
+
+ vol = Volumes;
+ prevvol = NULL;
+
+ while (vol) {
+ if (vol->v_deleted && !(vol->v_flags & AFPVOL_OPEN)) {
LOG(log_debug, logtype_afpd, "load_volumes: deleted: %s", vol->v_localname);
- if (delvol_fn)
- delvol_fn(obj, vol);
- vol = Volumes;
+ if (prevvol)
+ prevvol->v_next = vol->v_next;
+ else
+ Volumes = NULL;
+ p = vol->v_next;
+ volume_free(vol);
+ vol = p;
+ } else {
+ prevvol = vol;
+ vol = vol->v_next;
}
}
void unload_volumes(AFPObj *obj)
{
- struct vol *vol;
+ struct vol *vol, *p;
LOG(log_debug, logtype_afpd, "unload_volumes: BEGIN");
- for (vol = Volumes; vol; vol = vol->v_next)
+ p = Volumes;
+ while (p) {
+ vol = p;
+ p = vol->v_next;
volume_free(vol);
+ }
Volumes = NULL;
obj->options.volfile.mtime = 0;
const struct passwd *pw;
char volname[AFPVOL_U8MNAMELEN + 1];
char abspath[MAXPATHLEN + 1];
- char volpath[MAXPATHLEN + 1];
+ char volpath[MAXPATHLEN + 1], *realvolpath = NULL;
char tmpbuf[MAXPATHLEN + 1];
const char *secname, *basedir, *p = NULL, *subpath = NULL, *subpathconfig;
char *user = NULL, *prw;
p++;
EC_NULL_LOG( user = strdup(p) );
- if (prw = strchr(user, '/'))
+ if ((prw = strchr(user, '/')))
*prw++ = 0;
if (prw != 0)
subpath = prw;
strlcat(tmpbuf, "/", MAXPATHLEN);
/* (6) */
- if (subpathconfig = iniparser_getstring(obj->iniconfig, INISEC_HOMES, "path", NULL)) {
+ if ((subpathconfig = iniparser_getstring(obj->iniconfig, INISEC_HOMES, "path", NULL))) {
+ /*
if (!subpath || strncmp(subpathconfig, subpath, strlen(subpathconfig)) != 0) {
EC_FAIL;
}
+ */
strlcat(tmpbuf, subpathconfig, MAXPATHLEN);
strlcat(tmpbuf, "/", MAXPATHLEN);
}
/* (7) */
if (volxlate(obj, volpath, sizeof(volpath) - 1, tmpbuf, pw, NULL, NULL) == NULL)
- return NULL;
+ EC_FAIL;
+ EC_NULL( realvolpath = realpath_safe(volpath) );
EC_NULL( pw = getpwnam(user) );
- LOG(log_debug, logtype_afpd, "getvolbypath(\"%s\"): user: %s, homedir: %s => volpath: \"%s\"",
- path, user, pw->pw_dir, volpath);
+ LOG(log_debug, logtype_afpd, "getvolbypath(\"%s\"): user: %s, homedir: %s => realvolpath: \"%s\"",
+ path, user, pw->pw_dir, realvolpath);
/* do variable substitution for volume name */
p = iniparser_getstring(obj->iniconfig, INISEC_HOMES, "home name", "$u's home");
if (strstr(p, "$u") == NULL)
p = "$u's home";
strlcpy(tmpbuf, p, AFPVOL_U8MNAMELEN);
- EC_NULL_LOG( volxlate(obj, volname, sizeof(volname) - 1, tmpbuf, pw, volpath, NULL) );
+ EC_NULL_LOG( volxlate(obj, volname, sizeof(volname) - 1, tmpbuf, pw, realvolpath, NULL) );
const char *preset, *default_preset;
default_preset = iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "vol preset", NULL);
preset = iniparser_getstring(obj->iniconfig, INISEC_HOMES, "vol preset", NULL);
- vol = creatvol(obj, pw, INISEC_HOMES, volname, volpath, preset ? preset : default_preset ? default_preset : NULL);
+ vol = creatvol(obj, pw, INISEC_HOMES, volname, realvolpath, preset ? preset : default_preset ? default_preset : NULL);
EC_CLEANUP:
if (user)
free(user);
+ if (realvolpath)
+ free(realvolpath);
if (ret != 0)
vol = NULL;
return vol;
EC_INIT;
dictionary *config;
struct afp_options *options = &AFPObj->options;
- int i, c;
- const char *p, *tmp;
+ int c;
+ const char *p;
char *q, *r;
char val[MAXVAL];
/* figure out options w values */
options->loginmesg = iniparser_getstrdup(config, INISEC_GLOBAL, "login message", NULL);
options->guest = iniparser_getstrdup(config, INISEC_GLOBAL, "guest account", "nobody");
- options->passwdfile = iniparser_getstrdup(config, INISEC_GLOBAL, "passwd file",_PATH_AFPDPWFILE);
+ options->extmapfile = iniparser_getstrdup(config, INISEC_GLOBAL, "extmap file", _PATH_CONFDIR "extmap.conf");
+ options->passwdfile = iniparser_getstrdup(config, INISEC_GLOBAL, "passwd file", _PATH_AFPDPWFILE);
options->uampath = iniparser_getstrdup(config, INISEC_GLOBAL, "uam path", _PATH_AFPDUAMPATH);
options->uamlist = iniparser_getstrdup(config, INISEC_GLOBAL, "uam list", "uams_dhx.so uams_dhx2.so");
options->port = iniparser_getstrdup(config, INISEC_GLOBAL, "afp port", "548");
options->k5realm = iniparser_getstrdup(config, INISEC_GLOBAL, "k5 realm", NULL);
options->listen = iniparser_getstrdup(config, INISEC_GLOBAL, "afp listen", NULL);
options->ntdomain = iniparser_getstrdup(config, INISEC_GLOBAL, "nt domain", NULL);
+ options->addomain = iniparser_getstrdup(config, INISEC_GLOBAL, "ad domain", NULL);
options->ntseparator = iniparser_getstrdup(config, INISEC_GLOBAL, "nt separator", NULL);
options->mimicmodel = iniparser_getstrdup(config, INISEC_GLOBAL, "mimic model", NULL);
options->adminauthuser = iniparser_getstrdup(config, INISEC_GLOBAL, "admin auth user",NULL);
LOG(log_debug, logtype_afpd, "Locale charset is '%s'", p);
#else /* system doesn't have LOCALE support */
LOG(log_warning, logtype_afpd, "system doesn't have LOCALE support");
- p = strdup("UTF8");
+ p = "UTF8";
#endif
}
if (strcasecmp(p, "UTF-8") == 0) {
- p = strdup("UTF8");
+ p = "UTF8";
}
options->unixcodepage = strdup(p);
set_charset_name(CH_UNIX, p);
options->volcodepage = strdup(options->unixcodepage);
} else {
if (strcasecmp(p, "UTF-8") == 0) {
- p = strdup("UTF8");
+ p = "UTF8";
}
options->volcodepage = strdup(p);
}
options->maccharset = CH_MAC;
LOG(log_debug, logtype_afpd, "Global mac charset is %s", options->maccodepage);
+ if (readextmap(options->extmapfile) != 0) {
+ LOG(log_error, logtype_afpd, "Couldn't load extension -> type/creator mappings file \"%s\"",
+ options->extmapfile);
+ }
+
/* Check for sane values */
if (options->tickleval <= 0)
options->tickleval = 30;
EC_CLEANUP:
EC_EXIT;
}
+
+#define CONFIG_ARG_FREE(a) do { \
+ free(a); \
+ a = NULL; \
+ } while (0);
+
+/* get rid of any allocated afp_option buffers. */
+void afp_config_free(AFPObj *obj)
+{
+ if (obj->options.configfile)
+ CONFIG_ARG_FREE(obj->options.configfile);
+ if (obj->options.sigconffile)
+ CONFIG_ARG_FREE(obj->options.sigconffile);
+ if (obj->options.uuidconf)
+ CONFIG_ARG_FREE(obj->options.uuidconf);
+ if (obj->options.logconfig)
+ CONFIG_ARG_FREE(obj->options.logconfig);
+ if (obj->options.logfile)
+ CONFIG_ARG_FREE(obj->options.logfile);
+ if (obj->options.loginmesg)
+ CONFIG_ARG_FREE(obj->options.loginmesg);
+ if (obj->options.guest)
+ CONFIG_ARG_FREE(obj->options.guest);
+ if (obj->options.extmapfile)
+ CONFIG_ARG_FREE(obj->options.extmapfile);
+ if (obj->options.passwdfile)
+ CONFIG_ARG_FREE(obj->options.passwdfile);
+ if (obj->options.uampath)
+ CONFIG_ARG_FREE(obj->options.uampath);
+ if (obj->options.uamlist)
+ CONFIG_ARG_FREE(obj->options.uamlist);
+ if (obj->options.port)
+ CONFIG_ARG_FREE(obj->options.port);
+ if (obj->options.signatureopt)
+ CONFIG_ARG_FREE(obj->options.signatureopt);
+ if (obj->options.k5service)
+ CONFIG_ARG_FREE(obj->options.k5service);
+ if (obj->options.k5realm)
+ CONFIG_ARG_FREE(obj->options.k5realm);
+ if (obj->options.listen)
+ CONFIG_ARG_FREE(obj->options.listen);
+ if (obj->options.ntdomain)
+ CONFIG_ARG_FREE(obj->options.ntdomain);
+ if (obj->options.addomain)
+ CONFIG_ARG_FREE(obj->options.addomain);
+ if (obj->options.ntseparator)
+ CONFIG_ARG_FREE(obj->options.ntseparator);
+ if (obj->options.mimicmodel)
+ CONFIG_ARG_FREE(obj->options.mimicmodel);
+ if (obj->options.adminauthuser)
+ CONFIG_ARG_FREE(obj->options.adminauthuser);
+ if (obj->options.hostname)
+ CONFIG_ARG_FREE(obj->options.hostname);
+ if (obj->options.k5keytab)
+ CONFIG_ARG_FREE(obj->options.k5keytab);
+ if (obj->options.Cnid_srv)
+ CONFIG_ARG_FREE(obj->options.Cnid_srv);
+ if (obj->options.Cnid_port)
+ CONFIG_ARG_FREE(obj->options.Cnid_port);
+ if (obj->options.fqdn)
+ CONFIG_ARG_FREE(obj->options.fqdn);
+
+ if (obj->options.unixcodepage)
+ CONFIG_ARG_FREE(obj->options.unixcodepage);
+ if (obj->options.maccodepage)
+ CONFIG_ARG_FREE(obj->options.maccodepage);
+ if (obj->options.volcodepage)
+ CONFIG_ARG_FREE(obj->options.volcodepage);
+
+ obj->options.flags = 0;
+ obj->options.passwdbits = 0;
+
+ /* Free everything called from afp_config_parse() */
+ free_extmap();
+ iniparser_freedict(obj->iniconfig);
+ free_charset_names();
+}
fork = (server_child_fork *) children->fork + forkid;
/* if we already have an entry. just return. */
- if (child = resolve_child(fork->table, pid))
+ if ((child = resolve_child(fork->table, pid)))
goto exit;
if ((child = calloc(1, sizeof(afp_child_t))) == NULL)
EC_INIT;
server_child_fork *fork;
struct server_child_data *child;
- int i;
fork = (server_child_fork *) children->fork + forkid;
if ((child = resolve_child(fork->table, pid)) == NULL) {
LOG(log_debug, logtype_afpd, "ipc_server_read(%s): pid: %u",
ipc_cmd_str[ipc.command], ipc.child_pid);
- int afp_socket;
-
switch (ipc.command) {
case IPC_DISCOLDSESSION:
*/
int create_lockfile(const char *program, const char *pidfile)
{
- char buf[10];
FILE *pf;
- pid_t pid;
int mask;
if (check_lockfile(program, pidfile) != 0)
#include <sys/time.h>
#include <time.h>
#include <sys/wait.h>
+#include <libgen.h>
#include <atalk/adouble.h>
#include <atalk/ea.h>
return (strrchr(p, '/') ? strrchr(p, '/') + 1 : p);
}
+/*********************************************************************************
+ * chdir(), chmod(), chown(), stat() wrappers taking an additional option.
+ * Currently the only used options are O_NOFOLLOW, used to switch between symlink
+ * behaviour, and O_NETATALK_ACL for ochmod() indicating chmod_acl() shall be
+ * called which does special ACL handling depending on the filesytem
+ *********************************************************************************/
+
+int ostat(const char *path, struct stat *buf, int options)
+{
+ if (options & O_NOFOLLOW)
+ return lstat(path, buf);
+ else
+ return stat(path, buf);
+}
+
+int ochown(const char *path, uid_t owner, gid_t group, int options)
+{
+ if (options & O_NOFOLLOW)
+ return lchown(path, owner, group);
+ else
+ return chown(path, owner, group);
+}
+
+/*!
+ * chmod() wrapper for symlink and ACL handling
+ *
+ * @param path (r) path
+ * @param mode (r) requested mode
+ * @param sb (r) stat() of path or NULL
+ * @param option (r) O_NOFOLLOW | O_NETATALK_ACL
+ *
+ * Options description:
+ * O_NOFOLLOW: don't chmod() symlinks, do nothing, return 0
+ * O_NETATALK_ACL: call chmod_acl() instead of chmod()
+ */
+int ochmod(char *path, mode_t mode, const struct stat *st, int options)
+{
+ struct stat sb;
+
+ if (!st) {
+ if (lstat(path, &sb) != 0)
+ return -1;
+ st = &sb;
+ }
+
+ if (options & O_NOFOLLOW)
+ if (S_ISLNK(st->st_mode))
+ return 0;
+
+ if (options & O_NETATALK_ACL) {
+ return chmod_acl(path, mode);
+ } else {
+ return chmod(path, mode);
+ }
+}
+
+/*
+ * @brief ostat/fsstatat multiplexer
+ *
+ * ostatat mulitplexes ostat and fstatat. If we dont HAVE_ATFUNCS, dirfd is ignored.
+ *
+ * @param dirfd (r) Only used if HAVE_ATFUNCS, ignored else, -1 gives AT_FDCWD
+ * @param path (r) pathname
+ * @param st (rw) pointer to struct stat
+ */
+int ostatat(int dirfd, const char *path, struct stat *st, int options)
+{
+#ifdef HAVE_ATFUNCS
+ if (dirfd == -1)
+ dirfd = AT_FDCWD;
+ return fstatat(dirfd, path, st, (options & O_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0);
+#else
+ return ostat(path, st, options);
+#endif
+
+ /* DEADC0DE */
+ return -1;
+}
+
/*!
* @brief symlink safe chdir replacement
*
- * Only chdirs to dir if it doesn't contain symlinks.
+ * Only chdirs to dir if it doesn't contain symlinks or if symlink checking
+ * is disabled
*
* @returns 1 if a path element is a symlink, 0 otherwise, -1 on syserror
*/
-int lchdir(const char *dir)
+int ochdir(const char *dir, int options)
{
char buf[MAXPATHLEN+1];
char cwd[MAXPATHLEN+1];
char *test;
int i;
+ if (!(options & O_NOFOLLOW))
+ return chdir(dir);
+
/*
dir is a canonical path (without "../" "./" "//" )
but may end with a /
}
return( 0 );
}
+
+/*
+ * realpath() replacement that always allocates storage for returned path
+ */
+char *realpath_safe(const char *path)
+{
+ char *resolved_path;
+
+#ifdef REALPATH_TAKES_NULL
+ if ((resolved_path = realpath(path, NULL)) == NULL) {
+ LOG(log_error, logtype_afpd, "realpath() cannot resolve path \"%s\"", path);
+ return NULL;
+ }
+ return resolved_path;
+#else
+ if ((resolved_path = malloc(MAXPATHLEN+1)) == NULL)
+ return NULL;
+ if (realpath(path, resolved_path) == NULL) {
+ free(resolved_path);
+ LOG(log_error, logtype_afpd, "realpath() cannot resolve path \"%s\"", path);
+ return NULL;
+ }
+ /* Safe some memory */
+ char *tmp;
+ if ((tmp = strdup(resolved_path)) == NULL) {
+ free(resolved_path);
+ return NULL;
+ }
+ free(resolved_path);
+ resolved_path = tmp;
+ return resolved_path;
+#endif
+}
+
+/**
+ * Returns pointer to static buffer with basename of path
+ **/
+const char *basename_safe(const char *path)
+{
+ static char buf[MAXPATHLEN+1];
+ strlcpy(buf, path, MAXPATHLEN);
+ return basename(buf);
+}
+
+/**
+ * extended strtok allows the quoted strings
+ * modified strtok.c in glibc 2.0.6
+ **/
+char *strtok_quote(char *s, const char *delim)
+{
+ static char *olds = NULL;
+ char *token;
+
+ if (s == NULL)
+ s = olds;
+
+ /* Scan leading delimiters. */
+ s += strspn (s, delim);
+ if (*s == '\0')
+ return NULL;
+
+ /* Find the end of the token. */
+ token = s;
+
+ if (token[0] == '\"') {
+ token++;
+ s = strpbrk (token, "\"");
+ } else {
+ s = strpbrk (token, delim);
+ }
+
+ if (s == NULL) {
+ /* This token finishes the string. */
+ olds = strchr (token, '\0');
+ } else {
+ /* Terminate the token and make OLDS point past it. */
+ *s = '\0';
+ olds = s + 1;
+ }
+ return token;
+}
char *u;
size_t inplen;
size_t outlen;
- uint16_t flags = CONV_ESCAPEHEX | CONV_ALLOW_COLON;
+ uint16_t flags = CONV_ESCAPEHEX;
if (!mpath)
return NULL;
if (ea->ea_count == 0) {
/* Check if EA header exists and remove it */
eaname = ea_path(ea, NULL, 0);
- if ((lstatat(ea->dirfd, eaname, &st)) == 0) {
+ if ((statat(ea->dirfd, eaname, &st)) == 0) {
if ((netatalk_unlinkat(ea->dirfd, eaname)) != 0) {
LOG(log_error, logtype_afpd, "ea_close('%s'): unlink: %s",
eaname, strerror(errno));
}
}
- if ((lchown(ea_path(&ea, NULL, 0), uid, gid)) != 0) {
+ if ((ochown(ea_path(&ea, NULL, 0), uid, gid, vol_syml_opt(vol))) != 0) {
switch (errno) {
case EPERM:
case EACCES:
ret = AFPERR_MISC;
goto exit;
}
- if ((lchown(eaname, uid, gid)) != 0) {
+ if ((ochown(eaname, uid, gid, vol_syml_opt(vol))) != 0) {
switch (errno) {
case EPERM:
case EACCES:
}
/* Set mode on EA header file */
- if ((setfilmode(ea_path(&ea, NULL, 0), ea_header_mode(mode), NULL, vol->v_umask)) != 0) {
+ if ((setfilmode(vol, ea_path(&ea, NULL, 0), ea_header_mode(mode), NULL)) != 0) {
LOG(log_error, logtype_afpd, "ea_chmod_file('%s'): %s", ea_path(&ea, NULL, 0), strerror(errno));
switch (errno) {
case EPERM:
ret = AFPERR_MISC;
goto exit;
}
- if ((setfilmode(eaname, ea_mode(mode), NULL, vol->v_umask)) != 0) {
+ if ((setfilmode(vol, eaname, ea_mode(mode), NULL)) != 0) {
LOG(log_error, logtype_afpd, "ea_chmod_file('%s'): %s", eaname, strerror(errno));
switch (errno) {
case EPERM:
}
/* Set mode on EA header */
- if ((setfilmode(ea_path(&ea, NULL, 0), ea_header_mode(mode), NULL, vol->v_umask)) != 0) {
+ if ((setfilmode(vol, ea_path(&ea, NULL, 0), ea_header_mode(mode), NULL)) != 0) {
LOG(log_error, logtype_afpd, "ea_chmod_dir('%s'): %s", ea_path(&ea, NULL, 0), strerror(errno));
switch (errno) {
case EPERM:
ret = AFPERR_MISC;
goto exit;
}
- if ((setfilmode(eaname, ea_mode(mode), NULL, vol->v_umask)) != 0) {
+ if ((setfilmode(vol, eaname, ea_mode(mode), NULL)) != 0) {
LOG(log_error, logtype_afpd, "ea_chmod_dir('%s'): %s", eaname, strerror(errno));
switch (errno) {
case EPERM:
if (!*name)
continue;
+ if (STRCMP(name, ==, AD_EA_META))
+ continue;
+
if (sfd != -1) {
if (fchdir(sfd) == -1) {
LOG(log_error, logtype_afpd, "sys_ea_copyfile: cant chdir to sfd: %s",
EC_FAIL;
default:
LOG(log_debug, logtype_default, "open(\"%s\"): %s", fullpathname(path), strerror(errno));
- errno = ENOATTR;
EC_FAIL;
}
}
EC_FAIL;
default:
LOG(log_debug, logtype_default, "openat(\"%s\"): %s", fullpathname(path), strerror(errno));
- errno = ENOATTR;
EC_FAIL;
}
}
}
/* --------------------- */
-int setfilmode(const char * name, mode_t mode, struct stat *st, mode_t v_umask)
+int setfilmode(const struct vol *vol, const char *name, mode_t mode, struct stat *st)
{
struct stat sb;
mode_t mask = S_IRWXU | S_IRWXG | S_IRWXO; /* rwx for owner group and other, by default */
st = &sb;
}
- if (S_ISLNK(st->st_mode))
- return 0; /* we don't want to change link permissions */
-
mode |= st->st_mode & ~mask; /* keep other bits from previous mode */
- if ( chmod_acl( name, mode & ~v_umask ) < 0 && errno != EPERM ) {
+ if (ochmod((char *)name, mode & ~vol->v_umask, st, vol_syml_opt(vol) | O_NETATALK_ACL) < 0 && errno != EPERM ) {
return -1;
}
return 0;
int ret = 0;
int sfd = -1;
int dfd = -1;
- ssize_t cc;
- size_t buflen;
- char filebuf[NETATALK_DIOSZ_STACK];
#ifdef HAVE_ATFUNCS
if (dirfd == -1)
return -1;
}
-/*
- * @brief lstat/fsstatat multiplexer
- *
- * lstatat mulitplexes lstat and fstatat. If we dont HAVE_ATFUNCS, dirfd is ignored.
- *
- * @param dirfd (r) Only used if HAVE_ATFUNCS, ignored else, -1 gives AT_FDCWD
- * @param path (r) pathname
- * @param st (rw) pointer to struct stat
- */
-int lstatat(int dirfd, const char *path, struct stat *st)
-{
-#ifdef HAVE_ATFUNCS
- if (dirfd == -1)
- dirfd = AT_FDCWD;
- return (fstatat(dirfd, path, st, AT_SYMLINK_NOFOLLOW));
-#else
- return (lstat(path, st));
-#endif
-
- /* DEADC0DE */
- return -1;
-}
-
/*
* @brief opendir wrapper for *at semantics support
*
gid_t gid;
};
-typedef int (*rf_loop)(struct dirent *, char *, void *, int , mode_t );
+typedef int (*rf_loop)(const struct vol *, struct dirent *, char *, void *, int);
/* ----------------------------- */
static int
-for_each_adouble(const char *from, const char *name, rf_loop fn, void *data, int flag, mode_t v_umask)
+for_each_adouble(const char *from, const char *name, rf_loop fn, const struct vol *vol, void *data, int flag)
{
char buf[ MAXPATHLEN + 1];
char *m;
}
strlcat(buf, de->d_name, sizeof(buf));
- if (fn && (ret = fn(de, buf, data, flag, v_umask))) {
+ if (fn && (ret = fn(vol, de, buf, data, flag))) {
closedir(dp);
return ret;
}
}
/* ----------------- */
-static int deletecurdir_adouble_loop(struct dirent *de, char *name, void *data _U_, int flag _U_, mode_t v_umask)
+static int deletecurdir_adouble_loop(const struct vol *vol, struct dirent *de, char *name, void *data _U_, int flag _U_)
{
struct stat st;
int err;
/* delete stray .AppleDouble files. this happens to get .Parent files
as well. */
- if ((err = for_each_adouble("deletecurdir", ".AppleDouble", deletecurdir_adouble_loop, NULL, 1, vol->v_umask)))
+ if ((err = for_each_adouble("deletecurdir", ".AppleDouble", deletecurdir_adouble_loop, vol, NULL, 1)))
return err;
return netatalk_rmdir(-1, ".AppleDouble" );
}
/* ----------------- */
-static int adouble_setfilmode(const char * name, mode_t mode, struct stat *st, mode_t v_umask)
+static int adouble_setfilmode(const struct vol *vol, const char *name, mode_t mode, struct stat *st)
{
- return setfilmode(name, ad_hf_mode(mode), st, v_umask);
+ return setfilmode(vol, name, ad_hf_mode(mode), st);
}
static int RF_setfilmode_adouble(VFS_FUNC_ARGS_SETFILEMODE)
{
- return adouble_setfilmode(vol->ad_path(name, ADFLAGS_HF ), mode, st, vol->v_umask);
+ return adouble_setfilmode(vol, vol->ad_path(name, ADFLAGS_HF ), mode, st);
}
/* ----------------- */
static int RF_setdirunixmode_adouble(VFS_FUNC_ARGS_SETDIRUNIXMODE)
{
const char *adouble = vol->ad_path(name, ADFLAGS_DIR );
- int dropbox = vol->v_flags;
if (dir_rx_set(mode)) {
if (chmod_acl(ad_dir(adouble), (DIRBITS | mode) & ~vol->v_umask) < 0 )
return -1;
}
- if (adouble_setfilmode(vol->ad_path(name, ADFLAGS_DIR ), mode, st, vol->v_umask) < 0)
+ if (adouble_setfilmode(vol, vol->ad_path(name, ADFLAGS_DIR ), mode, st) < 0)
return -1;
if (!dir_rx_set(mode)) {
}
/* ----------------- */
-static int setdirmode_adouble_loop(struct dirent *de _U_, char *name, void *data, int flag, mode_t v_umask)
+static int setdirmode_adouble_loop(const struct vol *vol, struct dirent *de _U_, char *name, void *data, int flag)
{
mode_t hf_mode = *(mode_t *)data;
struct stat st;
- if ( stat( name, &st ) < 0 ) {
+ if (ostat(name, &st, vol_syml_opt(vol)) < 0 ) {
if (flag)
return 0;
LOG(log_error, logtype_afpd, "setdirmode: stat %s: %s", name, strerror(errno) );
}
else if (!S_ISDIR(st.st_mode)) {
- if (setfilmode(name, hf_mode , &st, v_umask) < 0) {
+ if (setfilmode(vol, name, hf_mode, &st) < 0) {
/* FIXME what do we do then? */
}
}
static int RF_setdirmode_adouble(VFS_FUNC_ARGS_SETDIRMODE)
{
- int dropbox = vol->v_flags;
mode_t hf_mode = ad_hf_mode(mode);
const char *adouble = vol->ad_path(name, ADFLAGS_DIR );
const char *adouble_p = ad_dir(adouble);
return -1;
}
- if (for_each_adouble("setdirmode", adouble_p, setdirmode_adouble_loop, &hf_mode, 0, vol->v_umask))
+ if (for_each_adouble("setdirmode", adouble_p, setdirmode_adouble_loop, vol, &hf_mode, 0))
return -1;
if (!dir_rx_set(mode)) {
if (errno == ENOENT) {
struct adouble ad;
- if (lstatat(dirfd, adsrc, &st)) /* source has no ressource fork, */
+ if (ostatat(dirfd, adsrc, &st, vol_syml_opt(vol))) /* source has no ressource fork, */
return 0;
/* We are here because :
}
/* Returns 1 if the entry is NOT an ._ file */
-static int deletecurdir_ea_osx_chkifempty_loop(struct dirent *de, char *name, void *data _U_, int flag _U_, mode_t v_umask _U_)
+static int deletecurdir_ea_osx_chkifempty_loop(const struct vol *vol, struct dirent *de, char *name, void *data _U_, int flag _U_)
{
if (de->d_name[0] != '.' || de->d_name[0] == '_')
return 1;
return 0;
}
-static int deletecurdir_ea_osx_loop(struct dirent *de, char *name, void *data _U_, int flag _U_, mode_t v_umask _U_)
+static int deletecurdir_ea_osx_loop(const struct vol *vol, struct dirent *de, char *name, void *data _U_, int flag _U_)
{
int ret;
/* first check if there's really no other file besides files starting with ._ */
if ((err = for_each_adouble("deletecurdir_ea_osx", ".",
deletecurdir_ea_osx_chkifempty_loop,
- NULL, 0, 0)) != 0) {
+ vol, NULL, 0)) != 0) {
if (err == 1)
return AFPERR_DIRNEMPT;
return AFPERR_MISC;
/* Now delete orphaned ._ files */
if ((err = for_each_adouble("deletecurdir_ea_osx", ".",
deletecurdir_ea_osx_loop,
- NULL, 0, 0)) != 0)
+ vol, NULL, 0)) != 0)
return err;
#endif
static int RF_setfilmode_ea(VFS_FUNC_ARGS_SETFILEMODE)
{
#ifndef HAVE_EAFD
- return adouble_setfilmode(vol->ad_path(name, ADFLAGS_HF ), mode, st, vol->v_umask);
+ return adouble_setfilmode(vol, vol->ad_path(name, ADFLAGS_HF ), mode, st);
#endif
return 0;
}
struct stat st;
err = errno;
- if (errno == ENOENT && lstatat(dirfd, adsrc, &st)) /* source has no ressource fork, */
+ if (errno == ENOENT && ostatat(dirfd, adsrc, &st, vol_syml_opt(vol))) /* source has no ressource fork, */
return 0;
errno = err;
return -1;
EXTRA_DIST = \
afs-check.m4 \
+ ax_pthread.m4 \
cnid-backend.m4 \
config-checks.m4 \
db3-check.m4 \
summary.m4 \
tcp-wrappers.m4 \
util.m4
-
-dnl $Id: afs-check.m4,v 1.4 2005-08-11 20:15:35 didg Exp $
dnl Autoconf macro to check whether AFS support should be enabled
AC_DEFUN([AC_NETATALK_AFS_CHECK], [
--- /dev/null
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_pthread.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+#
+# DESCRIPTION
+#
+# This macro figures out how to build C programs using POSIX threads. It
+# sets the PTHREAD_LIBS output variable to the threads library and linker
+# flags, and the PTHREAD_CFLAGS output variable to any special C compiler
+# flags that are needed. (The user can also force certain compiler
+# flags/libs to be tested by setting these environment variables.)
+#
+# Also sets PTHREAD_CC to any special C compiler that is needed for
+# multi-threaded programs (defaults to the value of CC otherwise). (This
+# is necessary on AIX to use the special cc_r compiler alias.)
+#
+# NOTE: You are assumed to not only compile your program with these flags,
+# but also link it with them as well. e.g. you should link with
+# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
+#
+# If you are only building threads programs, you may wish to use these
+# variables in your default LIBS, CFLAGS, and CC:
+#
+# LIBS="$PTHREAD_LIBS $LIBS"
+# CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+# CC="$PTHREAD_CC"
+#
+# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
+# has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name
+# (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
+#
+# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
+# PTHREAD_PRIO_INHERIT symbol is defined when compiling with
+# PTHREAD_CFLAGS.
+#
+# ACTION-IF-FOUND is a list of shell commands to run if a threads library
+# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it
+# is not found. If ACTION-IF-FOUND is not specified, the default action
+# will define HAVE_PTHREAD.
+#
+# Please let the authors know if this macro fails on any platform, or if
+# you have any other suggestions or comments. This macro was based on work
+# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help
+# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by
+# Alejandro Forero Cuervo to the autoconf macro repository. We are also
+# grateful for the helpful feedback of numerous users.
+#
+# Updated for Autoconf 2.68 by Daniel Richard G.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
+# Copyright (c) 2011 Daniel Richard G. <skunk@iSKUNK.ORG>
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or (at your
+# option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 18
+
+AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
+AC_DEFUN([AX_PTHREAD], [
+AC_REQUIRE([AC_CANONICAL_HOST])
+AC_LANG_PUSH([C])
+ax_pthread_ok=no
+
+# We used to check for pthread.h first, but this fails if pthread.h
+# requires special compiler flags (e.g. on True64 or Sequent).
+# It gets checked for in the link test anyway.
+
+# First of all, check if the user has set any of the PTHREAD_LIBS,
+# etcetera environment variables, and if threads linking works using
+# them:
+if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ save_LIBS="$LIBS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
+ AC_TRY_LINK_FUNC(pthread_join, ax_pthread_ok=yes)
+ AC_MSG_RESULT($ax_pthread_ok)
+ if test x"$ax_pthread_ok" = xno; then
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+ fi
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+fi
+
+# We must check for the threads library under a number of different
+# names; the ordering is very important because some systems
+# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
+# libraries is broken (non-POSIX).
+
+# Create a list of thread flags to try. Items starting with a "-" are
+# C compiler flags, and other items are library names, except for "none"
+# which indicates that we try without any flags at all, and "pthread-config"
+# which is a program returning the flags for the Pth emulation library.
+
+ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
+
+# The ordering *is* (sometimes) important. Some notes on the
+# individual items follow:
+
+# pthreads: AIX (must check this before -lpthread)
+# none: in case threads are in libc; should be tried before -Kthread and
+# other compiler flags to prevent continual compiler warnings
+# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
+# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
+# -pthreads: Solaris/gcc
+# -mthreads: Mingw32/gcc, Lynx/gcc
+# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
+# doesn't hurt to check since this sometimes defines pthreads too;
+# also defines -D_REENTRANT)
+# ... -mt is also the pthreads flag for HP/aCC
+# pthread: Linux, etcetera
+# --thread-safe: KAI C++
+# pthread-config: use pthread-config program (for GNU Pth library)
+
+case ${host_os} in
+ solaris*)
+
+ # On Solaris (at least, for some versions), libc contains stubbed
+ # (non-functional) versions of the pthreads routines, so link-based
+ # tests will erroneously succeed. (We need to link with -pthreads/-mt/
+ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
+ # a function called by this macro, so we could check for that, but
+ # who knows whether they'll stub that too in a future libc.) So,
+ # we'll just look for -pthreads and -lpthread first:
+
+ ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags"
+ ;;
+
+ darwin*)
+ ax_pthread_flags="-pthread $ax_pthread_flags"
+ ;;
+esac
+
+if test x"$ax_pthread_ok" = xno; then
+for flag in $ax_pthread_flags; do
+
+ case $flag in
+ none)
+ AC_MSG_CHECKING([whether pthreads work without any flags])
+ ;;
+
+ -*)
+ AC_MSG_CHECKING([whether pthreads work with $flag])
+ PTHREAD_CFLAGS="$flag"
+ ;;
+
+ pthread-config)
+ AC_CHECK_PROG(ax_pthread_config, pthread-config, yes, no)
+ if test x"$ax_pthread_config" = xno; then continue; fi
+ PTHREAD_CFLAGS="`pthread-config --cflags`"
+ PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
+ ;;
+
+ *)
+ AC_MSG_CHECKING([for the pthreads library -l$flag])
+ PTHREAD_LIBS="-l$flag"
+ ;;
+ esac
+
+ save_LIBS="$LIBS"
+ save_CFLAGS="$CFLAGS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+ # Check for various functions. We must include pthread.h,
+ # since some functions may be macros. (On the Sequent, we
+ # need a special flag -Kthread to make this header compile.)
+ # We check for pthread_join because it is in -lpthread on IRIX
+ # while pthread_create is in libc. We check for pthread_attr_init
+ # due to DEC craziness with -lpthreads. We check for
+ # pthread_cleanup_push because it is one of the few pthread
+ # functions on Solaris that doesn't have a non-functional libc stub.
+ # We try pthread_create on general principles.
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
+ static void routine(void *a) { a = 0; }
+ static void *start_routine(void *a) { return a; }],
+ [pthread_t th; pthread_attr_t attr;
+ pthread_create(&th, 0, start_routine, 0);
+ pthread_join(th, 0);
+ pthread_attr_init(&attr);
+ pthread_cleanup_push(routine, 0);
+ pthread_cleanup_pop(0) /* ; */])],
+ [ax_pthread_ok=yes],
+ [])
+
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+
+ AC_MSG_RESULT($ax_pthread_ok)
+ if test "x$ax_pthread_ok" = xyes; then
+ break;
+ fi
+
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+done
+fi
+
+# Various other checks:
+if test "x$ax_pthread_ok" = xyes; then
+ save_LIBS="$LIBS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+ # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
+ AC_MSG_CHECKING([for joinable pthread attribute])
+ attr_name=unknown
+ for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
+ [int attr = $attr; return attr /* ; */])],
+ [attr_name=$attr; break],
+ [])
+ done
+ AC_MSG_RESULT($attr_name)
+ if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
+ AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name,
+ [Define to necessary symbol if this constant
+ uses a non-standard name on your system.])
+ fi
+
+ AC_MSG_CHECKING([if more special flags are required for pthreads])
+ flag=no
+ case ${host_os} in
+ aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";;
+ osf* | hpux*) flag="-D_REENTRANT";;
+ solaris*)
+ if test "$GCC" = "yes"; then
+ flag="-D_REENTRANT"
+ else
+ flag="-mt -D_REENTRANT"
+ fi
+ ;;
+ esac
+ AC_MSG_RESULT(${flag})
+ if test "x$flag" != xno; then
+ PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
+ fi
+
+ AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
+ ax_cv_PTHREAD_PRIO_INHERIT, [
+ AC_LINK_IFELSE([
+ AC_LANG_PROGRAM([[#include <pthread.h>]], [[int i = PTHREAD_PRIO_INHERIT;]])],
+ [ax_cv_PTHREAD_PRIO_INHERIT=yes],
+ [ax_cv_PTHREAD_PRIO_INHERIT=no])
+ ])
+ AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"],
+ AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], 1, [Have PTHREAD_PRIO_INHERIT.]))
+
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+
+ # More AIX lossage: must compile with xlc_r or cc_r
+ if test x"$GCC" != xyes; then
+ AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC})
+ else
+ PTHREAD_CC=$CC
+ fi
+else
+ PTHREAD_CC="$CC"
+fi
+
+AC_SUBST(PTHREAD_LIBS)
+AC_SUBST(PTHREAD_CFLAGS)
+AC_SUBST(PTHREAD_CC)
+
+# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+if test x"$ax_pthread_ok" = xyes; then
+ ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
+ :
+else
+ ax_pthread_ok=no
+ $2
+fi
+AC_LANG_POP
+])dnl AX_PTHREAD
dnl Autoconf macro to check for the existence of grep
-dnl $Id: grep-check.m4,v 1.2 2002-02-14 18:02:04 jmarcus Exp $
AC_DEFUN([AC_PROG_GREP], [
AC_REQUIRE([AC_EXEEXT])dnl
dnl Whether to disable bundled libevent
AC_DEFUN([AC_NETATALK_LIBEVENT], [
- use_bundled_libevent=no
- AC_MSG_CHECKING([whether to use bundled or installed libevent])
+ AC_MSG_CHECKING([whether to use bundled libevent])
+ AC_ARG_WITH(
+ libevent,
+ [AS_HELP_STRING([--with-libevent],[whether to use the bundled libevent (default: yes)])],
+ use_bundled_libevent=$withval,
+ use_bundled_libevent=yes
+ )
AC_ARG_WITH(
libevent-header,
[AS_HELP_STRING([--with-libevent-header],[path to libevent header files])],
- LIBEVENT_CFLAGS=-I$withval,
- use_bundled_libevent=yes
+ [use_bundled_libevent=no; LIBEVENT_CFLAGS=-I$withval]
)
AC_ARG_WITH(
libevent-lib,
- [AS_HELP_STRING([--with-libevent-lib],[path to libevent header library])],
- LIBEVENT_LDFLAGS=-L$withval,
- use_bundled_libevent=yes
+ [AS_HELP_STRING([--with-libevent-lib],[path to libevent library])],
+ [use_bundled_libevent=no; LIBEVENT_LDFLAGS=-L$withval]
)
- AC_MSG_RESULT([$use_bundled_libevent])
- if test x"$use_bundled_libevent" = x"yes" ; then
- AC_CONFIG_SUBDIRS([libevent])
+ if test x"$LIBEVENT_CFLAGS" = x"-Iyes" -o x"$LIBEVENT_LDFLAGS" = x"-Lyes" ; then
+ AC_MSG_ERROR([--with-libevent requires a path])
fi
+ AC_MSG_RESULT([$use_bundled_libevent])
+ AC_CONFIG_SUBDIRS([libevent])
AC_SUBST(LIBEVENT_CFLAGS)
AC_SUBST(LIBEVENT_LDFLAGS)
AM_CONDITIONAL(USE_BUILTIN_LIBEVENT, test x"$use_bundled_libevent" = x"yes")
dnl ----- Linux specific -----
if test x"$this_os" = "xlinux"; then
AC_MSG_RESULT([ * Linux specific configuration])
-
+ AC_DEFINE(LINUX, 1, [OS is Linux])
dnl ----- check if we need the quotactl wrapper
AC_CHECK_HEADERS(linux/dqblk_xfs.h,,
[AC_CHECK_HEADERS(linux/xqm.h linux/xfs_fs.h)
save_LIBS="$LIBS"
CFLAGS="$KRB5_CFLAGS"
LIBS="$KRB5_LIBS"
-AC_CHECK_FUNCS([krb5_free_unparsed_name krb5_free_error_message])
+AC_CHECK_FUNCS([krb5_free_unparsed_name krb5_free_error_message krb5_free_keytab_entry_contents krb5_kt_free_entry])
CFLAGS="$save_CFLAGS"
LIBS="$save_LIBS"
])
-dnl $Id: pam-check.m4,v 1.6 2010-01-11 13:06:02 franklahm Exp $
dnl PAM finding macro
AC_DEFUN([AC_NETATALK_PATH_PAM], [
PAM_ACCOUNT=system
PAM_PASSWORD=system
PAM_SESSION=system
+ dnl Solaris 11+
+ elif test -f "$pampath/other" ; then
+ PAM_DIRECTIVE=include
+ PAM_AUTH=${PAMDIR}etc/pam.d/other
+ PAM_ACCOUNT=${PAMDIR}etc/pam.d/other
+ PAM_PASSWORD=${PAMDIR}etc/pam.d/other
+ PAM_SESSION=${PAMDIR}etc/pam.d/other
dnl Fallback
else
PAM_DIRECTIVE=required
dnl Autoconf macro to check for the existence of Perl
-dnl $Id: perl-check.m4,v 1.4 2002-03-12 11:03:49 srittau Exp $
AC_DEFUN([AC_PROG_PERL], [
AC_REQUIRE([AC_EXEEXT])dnl
dnl Autoconf macro to check for the existence of ps
-dnl $Id: ps-check.m4,v 1.2 2002-02-14 18:02:04 jmarcus Exp $
AC_DEFUN([AC_PROG_PS], [
AC_REQUIRE([AC_EXEEXT])dnl
-dnl $Id: quota-check.m4,v 1.6 2005-07-20 23:58:21 didg Exp $
dnl Autoconf macro to check for quota support
dnl FIXME: This is in now way complete.
-dnl $Id: ssl-check.m4,v 1.14 2008-11-22 12:07:26 didg Exp $
dnl Autoconf macro to check for SSL or OpenSSL
AC_DEFUN([AC_NETATALK_CRYPT], [
dnl # Display summary of libraries detected
AC_MSG_RESULT([Using libraries:])
- AC_MSG_RESULT([ LIBS = $LIBS])
- AC_MSG_RESULT([ CFLAGS = $CFLAGS])
+ AC_MSG_RESULT([ LIBS = $LIBS])
+ AC_MSG_RESULT([ CFLAGS = $CFLAGS])
+ AC_MSG_RESULT([ PTHREADS:])
+ AC_MSG_RESULT([ LIBS = $PTHREAD_LIBS])
+ AC_MSG_RESULT([ CFLAGS = $PTHREAD_CFLAGS])
if test x"$neta_cv_have_openssl" = x"yes"; then
AC_MSG_RESULT([ SSL:])
AC_MSG_RESULT([ LIBS = $SSL_LIBS])
AC_MSG_RESULT([ LIBS = $LDAP_LDLFLAGS $LDAP_LIBS])
AC_MSG_RESULT([ CFLAGS = $LDAP_CFLAGS])
fi
+ AC_MSG_RESULT([ LIBEVENT:])
+ if test x"$use_bundled_libevent" = x"yes"; then
+ AC_MSG_RESULT([ bundled])
+ else
+ AC_MSG_RESULT([ LIBS = $LIBEVENT_CFLAGS])
+ AC_MSG_RESULT([ CFLAGS = $LIBEVENT_LDFLAGS])
+ fi
])
-dnl $Id: tcp-wrappers.m4,v 1.4 2008-08-11 20:44:03 didg Exp $
AC_DEFUN([AC_NETATALK_TCP_WRAPPERS], [
check=maybe
'\" t
.\" Title: ad
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
+.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
.\" Date: 02 Sep 2011
.\" Manual: Netatalk 3.0
.\" Source: Netatalk 3.0
.\"
.TH "AD" "1" "02 Sep 2011" "Netatalk 3.0" "Netatalk 3.0"
.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
.SH "DESCRIPTION"
.PP
\fBad\fR
-is a UNIX file utlity suite with Netatalk compatibity\&. AppleDouble
+is a UNIX file utility suite with Netatalk compatibility\&. AppleDouble
files in
\&.AppleDouble
-directories and the CNID databases are updated as appropiate\&.
+directories and the CNID databases are updated as appropriate\&.
.SH "AVAILABLE COMMANDS"
.HP \w'\fBad\ ls\fR\ 'u
\fBad ls\fR [\-dRl\ [u]] {file|dir\ [\&.\&.\&.]}
l = No delete (f/d)
o = No copy (f)
-Note: any letter appearing in uppercase means the flag is set but it\'s a directory for which the flag is not allowed\&.
+Note: any letter appearing in uppercase means the flag is set but it\*(Aqs a directory for which the flag is not allowed\&.
.fi
.if n \{\
.RE
.PP
In the first synopsis form, the cp utility copies the contents of the source_file to the target_file\&. In the second synopsis form, the contents of each named source_file is copied to the destination target_directory\&. The names of the files themselves are not changed\&. If cp detects an attempt to copy a file to itself, the copy will fail\&.
.PP
-Netatalk AFP volumes are detected by means of their "\&.AppleDesktop" directory which is located in their volume root\&. When a copy targetting an AFP volume is detected, its CNID database daemon is connected and all copies will also go through the CNID database\&. AppleDouble files are also copied and created as needed when the target is an AFP volume\&.
+Netatalk AFP volumes are detected by means of their "\&.AppleDesktop" directory which is located in their volume root\&. When a copy targeting an AFP volume is detected, its CNID database daemon is connected and all copies will also go through the CNID database\&. AppleDouble files are also copied and created as needed when the target is an AFP volume\&.
.PP
Options:
.PP
.PP
\-i
.RS 4
-Cause cp to write a prompt to the standard error output before copying a file that would overwrite an existing file\&. If the response from the standard input begins with the character \'y\' or \'Y\', the file copy is attempted\&. (The \-i option overrides any pre\- vious \-f or \-n options\&.)
+Cause cp to write a prompt to the standard error output before copying a file that would overwrite an existing file\&. If the response from the standard input begins with the character \*(Aqy\*(Aq or \*(AqY\*(Aq, the file copy is attempted\&. (The \-i option overrides any pre\- vious \-f or \-n options\&.)
.RE
.PP
\-n
source AFP volume != destination AFP volume
.RE
.sp
-.RE
the files are copied and removed from the source\&.
.PP
Options:
.PP
\-i
.RS 4
-Cause mv to write a prompt to standard error before moving a file that would overwrite an existing file\&. If the response from the standard input begins with the character `y\' or `Y\', the move is attempted\&. (The \-i option overrides any previous \-f or \-n options\&.)
+Cause mv to write a prompt to standard error before moving a file that would overwrite an existing file\&. If the response from the standard input begins with the character `y\*(Aq or `Y\*(Aq, the move is attempted\&. (The \-i option overrides any previous \-f or \-n options\&.)
.RE
.PP
\-n
'\" t
.\" Title: afpldaptest
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
+.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
.\" Date: 22 Mar 2012
.\" Manual: Netatalk 3.0
.\" Source: Netatalk 3.0
.\"
.TH "AFPLDAPTEST" "1" "22 Mar 2012" "Netatalk 3.0" "Netatalk 3.0"
.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
'\" t
.\" Title: afppasswd
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
+.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
.\" Date: 22 Mar 2012
.\" Manual: Netatalk 3.0
.\" Source: Netatalk 3.0
.\"
.TH "AFPPASSWD" "1" "22 Mar 2012" "Netatalk 3.0" "Netatalk 3.0"
.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
.PP
With this utility you can only change the passwords used by two specific UAMs\&. As they provide only weak password encryption, the use of the "Randnum exchange" and "2\-Way Randnum exchange" UAMs is deprecated unless one has to support very old AFP clients, that can not deal with the more secure "DHCAST128" and "DHX2" UAM instead\&. Please compare with the
Authentication chapter
-inside Netatalk\'s documentation\&.
+inside Netatalk\*(Aqs documentation\&.
.sp .5v
.RE
.SH "EXAMPLE"
'\" t
.\" Title: apple_dump
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
+.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
.\" Date: 16 Jul 2012
.\" Manual: Netatalk 3.0
.\" Source: Netatalk 3.0
.\"
.TH "APPLE_DUMP" "1" "16 Jul 2012" "Netatalk 3.0" "Netatalk 3.0"
.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
.RE
.SH "NOTE"
.PP
-There is no way to detect whether FinderInfo is FileInfo or DirInfo\&. By default, apple_dump examins whether file or directory, a parent directory is \&.AppleDouble, filename is \&._*, filename is \&.Parent, and so on\&.
+There is no way to detect whether FinderInfo is FileInfo or DirInfo\&. By default, apple_dump examines whether file or directory, a parent directory is \&.AppleDouble, filename is \&._*, filename is \&.Parent, and so on\&.
.PP
-If setting option \-e, \-f or \-d, assume FinderInfo and doesn\'t look for another file\&.
+If setting option \-e, \-f or \-d, assume FinderInfo and doesn\*(Aqt look for another file\&.
.SH "SEE ALSO"
.PP
\fBad\fR(1),
'\" t
.\" Title: asip-status.pl
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
+.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
.\" Date: 24 Jul 2012
.\" Manual: Netatalk 3.0
.\" Source: Netatalk 3.0
.\"
.TH "ASIP\-STATUS\&.PL" "1" "24 Jul 2012" "Netatalk 3.0" "Netatalk 3.0"
.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
.SH "DESCRIPTION"
.PP
\fBasip\-status\&.pl\fR
-is a perl script that sends a FPGetSrvrInfo request to an AFP server at HOSTNAME:PORT and displays the results, namely "Machine type", the server\'s name, supported AFP versions, UAMs and AFP flags, the "server signature" and the network addresses, the server provides AFP services on\&.
+is a perl script that sends a FPGetSrvrInfo request to an AFP server at HOSTNAME:PORT and displays the results, namely "Machine type", the server\*(Aqs name, supported AFP versions, UAMs and AFP flags, the "server signature" and the network addresses, the server provides AFP services on\&.
.PP
-When you don\'t supply :PORT, then the default AFP port, 548, will be used\&.
+When you don\*(Aqt supply :PORT, then the default AFP port, 548, will be used\&.
.SH "OPTIONS"
.PP
\fB\-d\fR
'\" t
.\" Title: dbd
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
-.\" Date: 14 Sep 2012
+.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
+.\" Date: 28 Dec 2012
.\" Manual: Netatalk 3.0
.\" Source: Netatalk 3.0
.\" Language: English
.\"
-.TH "DBD" "1" "14 Sep 2012" "Netatalk 3.0" "Netatalk 3.0"
+.TH "DBD" "1" "28 Dec 2012" "Netatalk 3.0" "Netatalk 3.0"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
dbd \- CNID database maintenance
.SH "SYNOPSIS"
.HP \w'\fBdbd\fR\fB\fR\ 'u
-\fBdbd\fR\fB\fR [\-evx] {\-d\ [\-i] | \-s\ [\-c|\-n] | \-r\ [\-c|\-f|\-C] | \-u} \fIvolumepath\fR
+\fBdbd\fR\fB\fR [\-fsv] \fIvolumepath\fR
.SH "DESCRIPTION"
.PP
\fBdbd\fR
-can dump, scan, reindex and rebuild
-\fINetatalk\fR
-dbd CNID databases\&. It must be run with appropiate permissions i\&.e\&. as root\&.
-\fBdbd\fR
-\fB\-s|\-r\fR
-can be run on active volumes, but
-\fBdbd \-rf\fR, which wipes the db before rebuilding it, checks and enforces that the chosen volume is not in use\&.
-.SH "COMMANDS"
-.PP
-\-d
-.RS 4
-Dump CNID database\&. With
-\fB\-i \fRdump indexes too\&.
-.RE
-.PP
-\-s
-.RS 4
-Scan volume:
-.sp
-Compare CNIDs in database with volume, test if \&.AppleDouble directories exist, test if AppleDouble files exist, report orphaned AppleDouble files, report directories inside \&.AppleDouble directories, check name encoding, heck for orphaned CNIDs in database (requires
-\fB\-e\fR)\&.
-.sp
-Options:
-.PP
-\-c
-.RS 4
-Don\'t check \&.AppleDouble stuff, only check orphaned\&.
-.RE
-.PP
-\-n
-.RS 4
-Don\'t open CNID database, skip CNID checks, only traverse filesystem
-.RE
-.RE
-.PP
-\-r
-.RS 4
-Rebuild volume:
-.sp
-Sync CNIDSs from database with volume, ensure \&.AppleDouble directories exist, ensure AppleDouble files exist, delete orphaned AppleDouble files, report directories inside \&.AppleDouble directories, check name encoding by roundtripping, delete orphaned CNIDs in database (requires
-\fB\-e\fR)\&.
-.sp
-Options:
-.PP
-\-C
-.RS 4
-Converts volume from adouble:v2 to adouble:ea
-.RE
+scans all file and directories of AFP volumes, updating the CNID database of the volume\&. It must be run with appropriate permissions i\&.e\&. as root\&.\&.
+.SH "OPTIONS"
.PP
\-c
.RS 4
-Don\'t create \&.AppleDouble stuff, only cleanup orphaned\&.
+convert from adouble:v2 to adouble:ea
.RE
.PP
\-f
.RS 4
-Wipe database and rebuild from IDs stored in AppleDouble files, only available for volumes without
-\fBnocnidcache\fR
-option\&. Implies
-\fB\-e\fR\&.
-.RE
+delete and recreate CNID database
.RE
.PP
-\-u
+\-F
.RS 4
-Upgrade:
-.sp
-Opens the database which triggers any necessary upgrades, then closes and exits\&.
+location of the afp\&.conf config file
.RE
-.SH "OPTIONS"
.PP
-\-e
+\-s
.RS 4
-Only work on inactive volumes and lock them (exclusive)
+scan volume: treat the volume as read only and don\*(Aqt perform any filesystem modifications
.RE
.PP
-\-x
+\-t
.RS 4
-Rebuild indexes (just for completeness, mostly useless!)
+show statistics while running
.RE
.PP
\-v
.RS 4
verbose
.RE
-.SH "WARNING"
-.PP
-In order to be able to run
-\fB\-rf\fR
-reconstructing the CNIDs in the database from the
-\fIAppleDouble\fR
-files, make sure you\'ve run a
-\fB\-r\fR
-rebuild sometimes before, where the CNIDs then would have been synched between database and
-\fIAppleDouble\fR
-files\&.
.PP
-Also be careful about the option
-\fBnocnidcache\fR\&. Avoid this option if at all possible, because if prevents you from being able to use
-\fB\-f\fR\&.
+\-V
+.RS 4
+display version info
+.RE
.SH "CNID BACKGROUND"
.PP
-The CNID backends maintains name to ID mappings\&. If you change a filename outside afpd(8) (shell, samba), the CNID db will not know and not reflect that change\&. Netatalk tries to recover from such inconsistencies as gracefully as possible\&. The mechanisms to resolve such inconsistencies may fail sometimes, though, as this is not an easy task to accomplish\&. E\&.g\&. if several names in the path to the file or directory have changed, things may go wrong\&.
-.PP
-If you change a lot of filenames at once, chances are higher that the afpds fallback mechanisms fail, i\&.e\&. files will be assigned new IDs, even though the file hasn\'t changed\&.
+The CNID backends maintains name to ID mappings\&. If you change a filename outside afpd(8) (shell, samba), the CNID database will not reflect that change\&. Netatalk tries to recover from such inconsistencies as gracefully as possible\&.
.SH "SEE ALSO"
.PP
\fBcnid_metad\fR(8),
-.so man1/megatron.1
+.so megatron.1
-.so man1/megatron.1
+.so megatron.1
'\" t
.\" Title: macusers
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
+.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
.\" Date: 13 Oct 2011
.\" Manual: Netatalk 3.0
.\" Source: Netatalk 3.0
.\"
.TH "MACUSERS" "1" "13 Oct 2011" "Netatalk 3.0" "Netatalk 3.0"
.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
'\" t
.\" Title: megatron
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
+.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
.\" Date: 02 Sep 2011
.\" Manual: Netatalk 3.0
.\" Source: Netatalk 3.0
.\"
.TH "MEGATRON" "1" "02 Sep 2011" "Netatalk 3.0" "Netatalk 3.0"
.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
\fBnetatalk\fR
Apple Filing Protocol (AppleShare) server\&. BinHex, MacBinary, and AppleSingle are commonly used formats for transferring Macintosh files between machines via email or file transfer protocols\&.
\fBmegatron\fR
-uses its name to determine what type of tranformation is being asked of it\&.
+uses its name to determine what type of transformation is being asked of it\&.
.PP
If
\fBmegatron\fR
,
\fBunbin\fR
or
-\fBunsingle\fR, it tries to convert file(s) from BinHex, MacBinary, or AppleSingle into AppleDouble format\&. BinHex is the format most often used to send Macintosh files by e\-mail\&. Usually these files have an extension of "\&.hqx"\&. MacBinary is the format most often used by terminal emulators "on the fly" when transferring Macintosh files in binary mode\&. MacBinary files often have an extension of "\&.bin"\&. Some Macintosh LAN\-based email packages use uuencoded AppleSingle format to "attach" or "enclose" files in email\&. AppleSingle files don\'t have a standard filename extension\&.
+\fBunsingle\fR, it tries to convert file(s) from BinHex, MacBinary, or AppleSingle into AppleDouble format\&. BinHex is the format most often used to send Macintosh files by e\-mail\&. Usually these files have an extension of "\&.hqx"\&. MacBinary is the format most often used by terminal emulators "on the fly" when transferring Macintosh files in binary mode\&. MacBinary files often have an extension of "\&.bin"\&. Some Macintosh LAN\-based email packages use uuencoded AppleSingle format to "attach" or "enclose" files in email\&. AppleSingle files don\*(Aqt have a standard filename extension\&.
.PP
If
\fBmegatron\fR
\fBsingle2bin\fR, or
\fBmacbinary\fR, it will try to convert the file(s) from BinHex, AppleSingle, or AppleDouble into MacBinary\&. This last translation may be useful in moving Macintosh files from your
\fBafpd\fR
-server to some other machine when you can\'t copy them from the server using a Macintosh for some reason\&.
+server to some other machine when you can\*(Aqt copy them from the server using a Macintosh for some reason\&.
.PP
If
\fBmegatron\fR
.PP
If no source file is given, or if
\fIsourcefile\fR
-is `\fB\-\fR\', and if the conversion is from a BinHex or MacBinary file,
+is `\fB\-\fR\*(Aq, and if the conversion is from a BinHex or MacBinary file,
\fBmegatron\fR
will read from standard input\&.
.PP
'\" t
.\" Title: netatalk-config
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
+.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
.\" Date: 09 June 2001
.\" Manual: The Netatalk Project
.\" Source: Netatalk 3.0
.\"
.TH "NETATALK\-CONFIG" "1" "09 June 2001" "Netatalk 3.0" "The Netatalk Project"
.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
-.so man1/megatron.1
+.so megatron.1
-.so man1/megatron.1
+.so megatron.1
-.so man1/megatron.1
+.so megatron.1
'\" t
.\" Title: uniconv
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
-.\" Date: 23 Mar 2012
+.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
+.\" Date: 19 Jan 2013
.\" Manual: Netatalk 3.0
.\" Source: Netatalk 3.0
.\" Language: English
.\"
-.TH "UNICONV" "1" "23 Mar 2012" "Netatalk 3.0" "Netatalk 3.0"
+.TH "UNICONV" "1" "19 Jan 2013" "Netatalk 3.0" "Netatalk 3.0"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.PP
\-d
.RS 4
-don\'t HEX encode leading dots (:2e), equivalent to
+don\*(Aqt HEX encode leading dots (:2e), equivalent to
\fBuse dots = yes\fR
in
\fBafp.conf\fR(5)
.PP
\-n
.RS 4
-"dry run", don\'t do any real changes
+"dry run", don\*(Aqt do any real changes
.RE
.PP
\-t
should
\fInot\fR
be running while you change the volume encoding\&. Remember to change
-\fBvolcodepage\fR
+\fBunix charset\fR
+or
+\fBvol charset\fR
in
-\fBAppleVolumes.default\fR(5)
+\fBafp.conf\fR(5)
to the new codepage, before restarting afpd\&.
.PP
In case of
.PP
The CNID backends maintains name to ID mappings\&. If you change a filename outside afpd(8) (shell, samba), the CNID db, i\&.e\&. the DIDNAME index, gets inconsistent\&. Netatalk tries to recover from such inconsistencies as gracefully as possible\&. The mechanisms to resolve such inconsistencies may fail sometimes, though, as this is not an easy task to accomplish\&. I\&.e\&. if several names in the path to the file or directory have changed, things may go wrong\&.
.PP
-If you change a lot of filenames at once, chances are higher that the afpds fallback mechanisms fail, i\&.e\&. files will be assigned new IDs, even though the file hasn\'t changed\&.
+If you change a lot of filenames at once, chances are higher that the afpds fallback mechanisms fail, i\&.e\&. files will be assigned new IDs, even though the file hasn\*(Aqt changed\&.
\fBuniconv\fR
therefore updates the CNID entry for each file/directory directly after it changes the name to avoid inconsistencies\&. The two supported backends for volumes, dbd and cdb, use the same CNID db format\&. Therefore, you
\fIcould\fR
-.so man1/megatron.1
+.so megatron.1
-e "s@:COMPILED_BACKENDS:@${compiled_backends}@g" \
<$< >$@
-GENERATED_MANS = afp.conf.5 afp_signature.conf.5 afp_voluuid.conf.5
-TEMPLATE_FILES = afp.conf.5.tmpl afp_signature.conf.5.tmpl afp_voluuid.conf.5.tmpl
+GENERATED_MANS = afp.conf.5 afp_signature.conf.5 afp_voluuid.conf.5 extmap.conf.5
+TEMPLATE_FILES = afp.conf.5.tmpl afp_signature.conf.5.tmpl afp_voluuid.conf.5.tmpl extmap.conf.5.tmpl
NONGENERATED_MANS =
man_MANS = $(GENERATED_MANS) $(NONGENERATED_MANS)
'\" t
.\" Title: afp.conf
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
-.\" Date: 25 Jul 2012
+.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
+.\" Date: 19 Jan 2013
.\" Manual: Netatalk 3.0
.\" Source: Netatalk 3.0
.\" Language: English
.\"
-.TH "AFP\&.CONF" "5" "25 Jul 2012" "Netatalk 3.0" "Netatalk 3.0"
+.TH "AFP\&.CONF" "5" "19 Jan 2013" "Netatalk 3.0" "Netatalk 3.0"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.RS 4
.\}
.nf
-\fIname\fR = \fIvalue \fR
-
+ \fIname\fR = \fIvalue \fR
+
.fi
.if n \{\
.RE
Any line beginning with a semicolon (\(lq;\(rq) or a hash (\(lq#\(rq) character is ignored, as are lines containing only whitespace\&.
.PP
Any line ending in a
-\(lq\e\(rq
+\(lq \e \(rq
is continued on the next line in the customary UNIX fashion\&.
.PP
The values following the equals sign in parameters are all either a string (no quotes needed) or a boolean, which may be given as yes/no, 1/0 or true/false\&. Case is not significant in boolean values, but is preserved in string values\&. Some items such as create masks are numeric\&.
\fIvol preset\fR
which can be selected in other volume sections via the
\fBvol preset\fR
-option and constitutes defaults for the volume\&. For any option speficied both in a preset
+option and constitutes defaults for the volume\&. For any option specified both in a preset
\fIand\fR
-in a volume section the volume section setting completly substitutes the preset option\&.
+in a volume section the volume section setting completely substitutes the preset option\&.
.PP
The access rights granted by the server are masked by the access rights granted to the specified or guest UNIX user by the host system\&. The server does not grant more access than the host system grants\&.
.PP
.RS 4
.\}
.nf
-[baz]
-path = /foo/bar
-
+ [baz]
+ path = /foo/bar
.fi
.if n \{\
.RE
This section enable sharing of the UNIX server user home directories\&. Specifying an optional
\fBpath\fR
parameter means that not the whole user home will be shared but the subdirectory
-\fBpath\fR\&. It is neccessary to define the
+\fBpath\fR\&. It is necessary to define the
\fBbasedir regex\fR
option\&. It should be a regex which matches the parent directory of the user homes\&. Parameters denoted by a (H) belong to volume sections\&. The optional parameter
\fBhome name\fR
can be used to change the AFP volume name which
-\fI$u\'s home\fR
+\fI$u\*(Aqs home\fR
by default\&. See below under VARIABLE SUBSTITUTIONS\&.
.PP
The following example illustrates this\&. Given all user home directories are stored under
.RS 4
.\}
.nf
-[Homes]
-path = afp\-data
-basedir regex = /home
-
+ [Homes]
+ path = afp\-data
+ basedir regex = /home
.fi
.if n \{\
.RE
\fIjohn\fR
this results in an AFP home volume with a path of
/home/john/afp\-data\&.
+.PP
+If
+\fBbasedir regex\fR
+contains symlink, set the canonicalized absolute path\&. When
+/home
+links to
+/usr/home:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+ [Homes]
+ basedir regex = /usr/home
+.fi
+.if n \{\
+.RE
+.\}
.SH "PARAMETERS"
.PP
Parameters define the specific attributes of sections\&.
.sp -1
.IP " 2." 4.2
.\}
-if you specify a known variable, but that variable doesn\'t have a value, it will get ignored\&.
+if you specify a known variable, but that variable doesn\*(Aqt have a value, it will get ignored\&.
.RE
.PP
The variables which can be used for substitutions are:
.PP
$c
.RS 4
-client\'s ip address
+client\*(Aqs ip address
.RE
.PP
$d
.PP
$i
.RS 4
-client\'s ip, without port
+client\*(Aqs ip, without port
.RE
.PP
$s
.SH "EXPLANATION OF GLOBAL PARAMETERS"
.SS "Authentication Options"
.PP
+ad domain = \fIDOMAIN\fR \fB(G)\fR
+.RS 4
+Append @DOMAIN to username when authenticating\&. Useful in Active Directory environments that otherwise would require the user to enter the full user@domain string\&.
+.RE
+.PP
admin auth user = \fIuser\fR \fB(G)\fR
.RS 4
Specifying eg "\fBadmin auth user = root\fR" whenever a normal user login fails, afpd will try to authenticate as the specified
These are required if the server supports the Kerberos 5 authentication UAM\&.
.RE
.PP
-ldap auth method = \fInone|simple|sasl\fR \fB(G)\fR
-.RS 4
-Authentication method:
-\fBnone | simple | sasl\fR
-.PP
-none
-.RS 4
-anonymous LDAP bind
-.RE
-.PP
-simple
-.RS 4
-simple LDAP bind
-.RE
-.PP
-sasl
+nt domain = \fIDOMAIN\fR \fB(G)\fR, nt separator = \fISEPARATOR\fR \fB(G)\fR
.RS 4
-SASL\&. Not yet supported !
-.RE
-.RE
-.PP
-ldap auth dn = \fIdn\fR \fB(G)\fR
-.RS 4
-Distinguished Name of the user for simple bind\&.
-.sp
-.RE
-.PP
-ldap auth pw = \fIpassword\fR \fB(G)\fR
-.RS 4
-Distinguished Name of the user for simple bind\&.
-.sp
-.RE
-.PP
-ldap server = \fIhost\fR \fB(G)\fR
-.RS 4
-Name or IP address of your LDAP Server\&. This is only needed for explicit ACL support in order to be able to query LDAP for UUIDs\&.
-.sp
-You can use
-\fBafpldaptest\fR(1)
-to syntactically check your config\&.
-.RE
-.PP
-ldap userbase = \fIbase dn\fR \fB(G)\fR
-.RS 4
-DN of the user container in LDAP\&.
-.sp
-.RE
-.PP
-ldap userscope = \fIscope\fR \fB(G)\fR
-.RS 4
-Search scope for user search:
-\fBbase | one | sub\fR
-.sp
-.RE
-.PP
-ldap groupbase = \fIbase dn\fR \fB(G)\fR
-.RS 4
-DN of the group container in LDAP\&.
-.sp
-.RE
-.PP
-ldap groupscope = \fIscope\fR \fB(G)\fR
-.RS 4
-Search scope for user search:
-\fBbase | one | sub\fR
-.sp
-.RE
-.PP
-ldap uuid attr = \fIdn\fR \fB(G)\fR
-.RS 4
-Name of the LDAP attribute with the UUIDs\&.
-.sp
-Note: this is used both for users and groups\&.
-.sp
-.RE
-.PP
-ldap name attr = \fIdn\fR \fB(G)\fR
-.RS 4
-Name of the LDAP attribute with the users short name\&.
-.sp
-.RE
-.PP
-ldap uuid string = \fISTRING\fR \fB(G)\fR
-.RS 4
-Format of the uuid string in the directory\&. A series of x and \-, where every x denotes a value 0\-9a\-f and every \- is a seperator\&.
-.sp
-Default: xxxxxxxx\-xxxx\-xxxx\-xxxx\-xxxxxxxxxxxx
-.RE
-.PP
-ldap uuid encoding = \fIstring | ms\-guid (default: string)\fR \fB(G)\fR
-.RS 4
-Format of the UUID of the LDAP attribute, allows usage of the binary objectGUID fields from Active Directory\&. If left unspecified, string is the default, which passes through the ASCII UUID returned by most other LDAP stores\&. If set to ms\-guid, the internal UUID representation is converted to and from the binary format used in the objectGUID attribute found on objects in Active Directory when interacting with the server\&.
-.PP
-string
-.RS 4
-UUID is a string, use with eg OpenDirectory\&.
-.RE
-.PP
-ms\-guid
-.RS 4
-Binary objectGUID from Active Directory
-.RE
-.RE
-.PP
-ldap group attr = \fIdn\fR \fB(G)\fR
-.RS 4
-Name of the LDAP attribute with the groups short name\&.
-.sp
-.RE
-.PP
-nt domain = \fIDOMAIN\fR \fB(G)\fR, nt separator = \fISEPERATOR\fR \fB(G)\fR
-.RS 4
-Use for eg\&. winbind authentication, prepends both strings before the username from login and then tries to authenticate with the result through the availabel and active UAM authentication modules\&.
+Use for eg\&. winbind authentication, prepends both strings before the username from login and then tries to authenticate with the result through the available and active UAM authentication modules\&.
.RE
.PP
save password = \fIBOOLEAN\fR (default: \fIyes\fR) \fB(G)\fR
.PP
To be able to serve AFP3 and older clients at the same time,
\fBafpd\fR
-needs to be able to convert between UTF\-8 and Mac charsets\&. Even OS X clients partly still rely on the mac charset\&. As there\'s no way,
+needs to be able to convert between UTF\-8 and Mac charsets\&. Even OS X clients partly still rely on the mac charset\&. As there\*(Aqs no way,
\fBafpd\fR
can detect the codepage a pre AFP3 client uses, you have to specify it using the
\fBmac charset\fR
.PP
As
\fBafpd\fR
-needs to interact with UNIX operating system as well, it need\'s to be able to convert from UTF8\-MAC / Mac charset to the UNIX charset\&. By default
+needs to interact with UNIX operating system as well, it need\*(Aqs to be able to convert from UTF8\-MAC / Mac charset to the UNIX charset\&. By default
\fBafpd\fR
uses
\fIUTF8\fR\&. You can set the UNIX charset using the
\fBunix charset\fR
-option\&. If you\'re using extended characters in the configuration files for
+option\&. If you\*(Aqre using extended characters in the configuration files for
\fBafpd\fR, make sure your terminal matches the
\fBunix charset\fR\&.
.PP
Specifies the servers unix charset, e\&.g\&.
\fIISO\-8859\-15\fR
or
-\fIEUC\-JP\fR\&. This is used to convert strings to/from the systems locale, e\&.g\&. for authenthication, server messages and volume names\&. If
+\fIEUC\-JP\fR\&. This is used to convert strings to/from the systems locale, e\&.g\&. for authentication, server messages and volume names\&. If
\fILOCALE\fR
is set, the systems locale is used\&. Defaults to
\fIUTF8\fR\&.
.PP
advertise ssh = \fIBOOLEAN\fR (default: \fIno\fR) \fB(G)\fR
.RS 4
-Allows old Mac OS X clients (10\&.3\&.3\-10\&.4) to automagically establish a tunneled AFP connection through SSH\&. If this option is set, the server\'s answers to client\'s FPGetSrvrInfo requests contain an additional entry\&. It depends on both client\'s settings and a correctly configured and running
+Allows old Mac OS X clients (10\&.3\&.3\-10\&.4) to automagically establish a tunneled AFP connection through SSH\&. If this option is set, the server\*(Aqs answers to client\*(Aqs FPGetSrvrInfo requests contain an additional entry\&. It depends on both client\*(Aqs settings and a correctly configured and running
\fBsshd\fR(8)
on the server to let things work\&.
.if n \{\
\fBNote\fR
.ps -1
.br
-Setting this option is not recommended since globally encrypting AFP connections via SSH will increase the server\'s load significantly\&. On the other hand, Apple\'s client side implementation of this feature in MacOS X versions prior to 10\&.3\&.4 contained a security flaw\&.
+Setting this option is not recommended since globally encrypting AFP connections via SSH will increase the server\*(Aqs load significantly\&. On the other hand, Apple\*(Aqs client side implementation of this feature in MacOS X versions prior to 10\&.3\&.4 contained a security flaw\&.
.sp .5v
.RE
.RE
.PP
-afp listen = \fIip address[:port] [ip adress[:port] \&.\&.\&.]\fR \fB(G)\fR
+afp listen = \fIip address[:port] [ip address[:port] \&.\&.\&.]\fR \fB(G)\fR
.RS 4
Specifies the IP address that the server should advertise
\fBand\fR
option\&.
.RE
.PP
-cnid listen = \fIip address[:port] [ip adress[:port] \&.\&.\&.]\fR \fB(G)\fR
+cnid listen = \fIip address[:port] [ip address[:port] \&.\&.\&.]\fR \fB(G)\fR
.RS 4
Specifies the IP address that the CNID server should listen on\&. The default is
\fBlocalhost:4700\fR\&.
.PP
hostname = \fIname\fR \fB(G)\fR
.RS 4
-Use this instead of the result from calling hostname for dertermening which IP address to advertise, therfore the hostname is resolved to an IP which is the advertised\&. This is NOT used for listening and it is also overwritten by
+Use this instead of the result from calling hostname for determining which IP address to advertise, therefore the hostname is resolved to an IP which is the advertised\&. This is NOT used for listening and it is also overwritten by
\fBafp listen\fR\&.
.RE
.PP
.PP
server quantum = \fInumber\fR \fB(G)\fR
.RS 4
-This specifies the DSI server quantum\&. The default value is 303840\&. The maximum value is 0xFFFFFFFFF, the minimum is 32000\&. If you specify a value that is out of range, the default value will be set\&. Do not change this value unless you\'re absolutely sure, what you\'re doing
+This specifies the DSI server quantum\&. The default value is 303840\&. The maximum value is 0xFFFFFFFFF, the minimum is 32000\&. If you specify a value that is out of range, the default value will be set\&. Do not change this value unless you\*(Aqre absolutely sure, what you\*(Aqre doing
.RE
.PP
sleep time = \fInumber\fR \fB(G)\fR
.PP
afp read locks = \fIBOOLEAN\fR (default: \fIno\fR) \fB(G)\fR
.RS 4
-Whether to apply locks to the byte region read in FPRead calls\&. The AFP spec mandates this, but it\'s not really in line with UNIX semantics and is a performance hug\&.
+Whether to apply locks to the byte region read in FPRead calls\&. The AFP spec mandates this, but it\*(Aqs not really in line with UNIX semantics and is a performance hug\&.
.RE
.PP
basedir regex = \fIregex\fR \fB(H)\fR
.RS 4
-Regular expression which matches the parent directory of the user homes\&. In the simple case this is just a path ie
+Regular expression which matches the parent directory of the user homes\&. If
+\fBbasedir regex\fR
+contains symlink, you must set the canonicalized absolute path\&. In the simple case this is just a path ie
\fBbasedir regex = /home\fR
.RE
.PP
close vol = \fIBOOLEAN\fR (default: \fIno\fR) \fB(G)\fR
.RS 4
-Whether to close volumes possibly opened by clients when they\'re removed from the configuration and the configuration is reloaded\&.
+Whether to close volumes possibly opened by clients when they\*(Aqre removed from the configuration and the configuration is reloaded\&.
.RE
.PP
cnid server = \fIipaddress[:port]\fR \fB(G)/(V)\fR
Default size is 8192, maximum size is 131072\&. Given value is rounded up to nearest power of 2\&. Each entry takes about 100 bytes, which is not much, but remember that every afpd child process for every connected user has its cache\&.
.RE
.PP
-fce listener = \fIhost[:port]\fR \fB(G)\fR
-.RS 4
-Enables sending FCE events to the specified
-\fIhost\fR, default
-\fIport\fR
-is 12250 if not specified\&. Specifying mutliple listeners is done by having this option once for each of them\&.
-.RE
-.PP
-fce events = \fIfmod,fdel,ddel,fcre,dcre,tmsz\fR \fB(G)\fR
-.RS 4
-Speficies which FCE events are active, default is
-\fIfmod,fdel,ddel,fcre,dcre\fR\&.
-.RE
-.PP
-fce coalesce = \fIall|delete|create\fR \fB(G)\fR
-.RS 4
-Coalesce FCE events\&.
-.RE
-.PP
-fce holdfmod = \fIseconds\fR \fB(G)\fR
+extmap file = \fIpath\fR \fB(G)\fR
.RS 4
-This determines the time delay in seconds which is always waited if another file modification for the same file is done by a client before sending an FCE file modification event (fmod)\&. For example saving a file in Photoshop would generate multiple events by itself because the application is opening, modifying and closing a file mutliple times for every "save"\&. Defautl: 60 seconds\&.
+Sets the path to the file which defines file extension type/creator mappings\&. (default is :ETCDIR:/extmap\&.conf)\&.
.RE
.PP
guest account = \fIname\fR \fB(G)\fR
home name = \fIname\fR \fB(H)\fR
.RS 4
AFP user home volume name\&. The default is
-\fIusers\'s home\fR\&.
+\fIuser\*(Aqs home\fR\&.
.RE
.PP
keep sessions = \fIBOOLEAN\fR (default: \fIno\fR) \fB(G)\fR
.RS 4
-Enable "Continuous AFP Service"\&. This means restarting AFP and CNID service daemons master processes, but keeping the AFP session processes\&. This can be used to install (most) updates to Netatalk without interruping active AFP sessions\&. Existing AFP sessions will still run the version from before updating, but new AFP sessions will run the updated code\&. After enabling this option when sending SIGQUIT to the
+Enable "Continuous AFP Service"\&. This means restarting AFP and CNID service daemons master processes, but keeping the AFP session processes\&. This can be used to install (most) updates to Netatalk without interrupting active AFP sessions\&. Existing AFP sessions will still run the version from before updating, but new AFP sessions will run the updated code\&. After enabling this option when sending SIGQUIT to the
\fInetatalk\fR
service controller process, the AFP and CNID daemons will exit and then the service controller will restart them\&. AFP session processes are notified of the master afpd shutdown, they will then sleep 15\-20 seconds and then try to reconnect their IPC channel to the master afpd process\&. The IPC channel between the AFP master service daemon and the AFP session child is used for keeping session state of AFP sessions in the AFP master process\&. The session state is needed when AFP clients experience eg network outages and try to reconnect to the AFP server\&.
.RE
.PP
vol dbpath = \fIpath\fR \fB(G)\fR
.RS 4
-Sets the database information to be stored in path\&. You have to specifiy a writable location, even if the volume is read only\&. The default is
+Sets the database information to be stored in path\&. You have to specify a writable location, even if the volume is read only\&. The default is
:STATEDIR:/netatalk/CNID/\&.
.RE
.PP
.RS 4
.\}
.nf
-73: limit of Mac OS X 10\&.1
-80: limit of Mac OS X 10\&.4/10\&.5 (default)
-255: limit of recent Mac OS X
+ 73: limit of Mac OS X 10\&.1 80: limit of Mac
+ OS X 10\&.4/10\&.5 (default) 255: limit of recent Mac OS
+ X
.fi
.if n \{\
.RE
.\}
.sp
-Mac OS 9 and earlier are not influenced by this, because Maccharset volume name is always limitted to 27 bytes\&.
+Mac OS 9 and earlier are not influenced by this, because Maccharset volume name is always limited to 27 bytes\&.
.RE
.PP
vol preset = \fIname\fR \fB(G)/(V)\fR
.RS 4
Use section
\fBname\fR
-as option preset for all volumes (when set in the [Global] section) or for one volume (when set in that volume\'s section)\&.
+as option preset for all volumes (when set in the [Global] section) or for one volume (when set in that volume\*(Aqs section)\&.
.RE
.SS "Logging Options"
.PP
log file = \fIlogfile\fR \fB(G)\fR
.RS 4
-If not specified Netatalk logs to syslogs daemon facilify\&. Otherwise it logs to
+If not specified Netatalk logs to syslogs daemon facility\&. Otherwise it logs to
\fBlogfile\fR\&.
.RE
.PP
.sp .5v
.RE
.RE
+.SS "Filesystem Change Events (FCE)"
+.PP
+Netatalk includes a nifty filesystem change event mechanism where afpd processes notify interested listeners about certain filesystem event by UDP network datagrams\&.
+.PP
+fce listener = \fIhost[:port]\fR \fB(G)\fR
+.RS 4
+Enables sending FCE events to the specified
+\fIhost\fR, default
+\fIport\fR
+is 12250 if not specified\&. Specifying multiple listeners is done by having this option once for each of them\&.
+.RE
+.PP
+fce events = \fIfmod,fdel,ddel,fcre,dcre,tmsz\fR \fB(G)\fR
+.RS 4
+Specifies which FCE events are active, default is
+\fIfmod,fdel,ddel,fcre,dcre\fR\&.
+.RE
+.PP
+fce coalesce = \fIall|delete|create\fR \fB(G)\fR
+.RS 4
+Coalesce FCE events\&.
+.RE
+.PP
+fce holdfmod = \fIseconds\fR \fB(G)\fR
+.RS 4
+This determines the time delay in seconds which is always waited if another file modification for the same file is done by a client before sending an FCE file modification event (fmod)\&. For example saving a file in Photoshop would generate multiple events by itself because the application is opening, modifying and closing a file multiple times for every "save"\&. Default: 60 seconds\&.
+.RE
.SS "Debug Parameters"
.PP
These options are useful for debugging only\&.
.PP
client polling = \fIBOOLEAN\fR (default: \fIno\fR) \fB(G)\fR
.RS 4
-With this option enabled, afpd won\'t advertise that it is capable of server notifications, so that connected clients poll the server every 10 seconds to detect changes in opened server windows\&.
-\fINote\fR: Depending on the number of simultaneously connected clients and the network\'s speed, this can lead to a significant higher load on your network!
+With this option enabled, afpd won\*(Aqt advertise that it is capable of server notifications, so that connected clients poll the server every 10 seconds to detect changes in opened server windows\&.
+\fINote\fR: Depending on the number of simultaneously connected clients and the network\*(Aqs speed, this can lead to a significant higher load on your network!
.sp
Do not use this option any longer as present Netatalk correctly supports server notifications, allowing connected clients to update folder listings in case another client changed the contents\&.
.RE
+.SS "Options for ACL handling"
+.PP
+For a basic mode of operation there\*(Aqs nothing to configure\&. afpd reads ACLs on the fly, calculating effective permissions and returning the calculated permissions via the so called UARights permission bits\&. On a Mac the Finder uses these bits to adjust permission in Finder windows\&. For example folder whos UNIX mode would only result in in read\-only permissions for a user will not be displayed with a read\-only icon and the user will be able to write to the folder given the folder has an ACL giving the user write access\&.
+.PP
+However, neither in Finder "Get Info" windows nor in Terminal will you be able to see the ACLs, that\*(Aqs a result of how ACLs in OS X are designed\&. If you want to be able to display ACLs on the client, things get more involved as you must then setup both client and server to be part on a authentication domain (directory service, eg LDAP, OpenDirectory)\&. The reason is, that in OS X ACLs are bound to UUIDs, not just uid\*(Aqs or gid\*(Aqs\&. Therefor afpd must be able to map every filesystem uid and gid to a UUID so that it can return the server side ACLs which are bound to UNIX uid and gid mapped to OS X UUIDs\&. Get it? Read on\&.
+.PP
+Netatalk can query a directory server using LDAP queries\&. Either the directory server already provides an UUID attribute for user and groups (Active Directory, Open Directory) or you reuse an unused attribute (or add a new one) to you directory server (eg OpenLDAP)\&.
+.PP
+The following LDAP options must be configured for Netatalk:
+.PP
+ldap auth method = \fInone|simple|sasl\fR \fB(G)\fR
+.RS 4
+Authentication method:
+\fBnone | simple | sasl\fR
+.PP
+none
+.RS 4
+anonymous LDAP bind
+.RE
+.PP
+simple
+.RS 4
+simple LDAP bind
+.RE
+.PP
+sasl
+.RS 4
+SASL\&. Not yet supported !
+.RE
+.RE
+.PP
+ldap auth dn = \fIdn\fR \fB(G)\fR
+.RS 4
+Distinguished Name of the user for simple bind\&.
+.RE
+.PP
+ldap auth pw = \fIpassword\fR \fB(G)\fR
+.RS 4
+Distinguished Name of the user for simple bind\&.
+.RE
+.PP
+ldap server = \fIhost\fR \fB(G)\fR
+.RS 4
+Name or IP address of your LDAP Server\&. This is only needed for explicit ACL support in order to be able to query LDAP for UUIDs\&.
+.sp
+You can use
+\fBafpldaptest\fR(1)
+to syntactically check your config\&.
+.RE
+.PP
+ldap userbase = \fIbase dn\fR \fB(G)\fR
+.RS 4
+DN of the user container in LDAP\&.
+.RE
+.PP
+ldap userscope = \fIscope\fR \fB(G)\fR
+.RS 4
+Search scope for user search:
+\fBbase | one | sub\fR
+.RE
+.PP
+ldap groupbase = \fIbase dn\fR \fB(G)\fR
+.RS 4
+DN of the group container in LDAP\&.
+.RE
+.PP
+ldap groupscope = \fIscope\fR \fB(G)\fR
+.RS 4
+Search scope for user search:
+\fBbase | one | sub\fR
+.RE
+.PP
+ldap uuid attr = \fIdn\fR \fB(G)\fR
+.RS 4
+Name of the LDAP attribute with the UUIDs\&.
+.sp
+Note: this is used both for users and groups\&.
+.RE
+.PP
+ldap name attr = \fIdn\fR \fB(G)\fR
+.RS 4
+Name of the LDAP attribute with the users short name\&.
+.RE
+.PP
+ldap uuid string = \fISTRING\fR \fB(G)\fR
+.RS 4
+Format of the uuid string in the directory\&. A series of x and \-, where every x denotes a value 0\-9a\-f and every \- is a separator\&.
+.sp
+Default: xxxxxxxx\-xxxx\-xxxx\-xxxx\-xxxxxxxxxxxx
+.RE
+.PP
+ldap uuid encoding = \fIstring | ms\-guid (default: string)\fR \fB(G)\fR
+.RS 4
+Format of the UUID of the LDAP attribute, allows usage of the binary objectGUID fields from Active Directory\&. If left unspecified, string is the default, which passes through the ASCII UUID returned by most other LDAP stores\&. If set to ms\-guid, the internal UUID representation is converted to and from the binary format used in the objectGUID attribute found on objects in Active Directory when interacting with the server\&.
+.PP
+string
+.RS 4
+UUID is a string, use with eg OpenDirectory\&.
+.RE
+.PP
+ms\-guid
+.RS 4
+Binary objectGUID from Active Directory
+.RE
+.RE
+.PP
+ldap group attr = \fIdn\fR \fB(G)\fR
+.RS 4
+Name of the LDAP attribute with the groups short name\&.
+.RE
.SH "EXPLANATION OF VOLUME PARAMETERS"
.SS "Parameters"
.PP
The section name defines the volume name which is the name that appears in the Chooser or the "connect to server" dialog on Macintoshes to represent the appropriate share\&. No two volumes may have the same name\&. The volume name cannot contain the
-\':\'
+\*(Aq:\*(Aq
character\&. The volume name is mangled if it is very long\&. Mac charset volume name is limited to 27 characters\&. UTF8\-MAC volume name is limited to volnamelen parameter\&.
.PP
path = \fIPATH\fR \fB(V)\fR
The path name must be a fully qualified path name, or a path name using either the ~ shell shorthand or any of the substitution variables, which are listed below\&.
.sp
The volume name is the name that appears in the Chooser ot the "connect to server" dialog on Macintoshes to represent the appropriate share\&. If volumename is unspecified, the last component of pathname is used\&. No two volumes may have the same name\&. If there are spaces in the name, it should be in quotes (i\&.e\&. "File Share")\&. The volume name cannot contain the
-\':\'
+\*(Aq:\*(Aq
character\&. The volume name is mangled if it is very long\&. Mac charset volume name is limited to 27 characters\&. UTF8\-MAC volume name is limited to volnamelen parameter\&.
.RE
.PP
.RS 4
Useful for Time Machine: limits the reported volume size, thus preventing Time Machine from using the whole real disk space for backup\&. Example: "vol size limit = 1000" would limit the reported disk space to 1 GB\&.
\fBIMPORTANT: \fR
-This is an approimated calculation taking into accout the contents of Time Machine sparsebundle images\&. Therefor you MUST NOT use this volume to store other content when using this option, because it would NOT be accounted\&. The calculation works by reading the band size from the Info\&.plist XML file of the sparsebundle, reading the bands/ directory counting the number of band files, and then multiplying one with the other\&.
+This is an approximated calculation taking into account the contents of Time Machine sparsebundle images\&. Therefor you MUST NOT use this volume to store other content when using this option, because it would NOT be accounted\&. The calculation works by reading the band size from the Info\&.plist XML file of the sparsebundle, reading the bands/ directory counting the number of band files, and then multiplying one with the other\&.
.RE
.PP
-valid users = \fIusers/groups\fR \fB(V)\fR
+valid users = \fIuser @group\fR \fB(V)\fR
.RS 4
-The allow option allows the users and groups that access a share to be specified\&. Users and groups are specified, delimited by spaces or commas\&. Groups are designated by a @ prefix\&. Example: "valid users = user1 user2 @group"
+The allow option allows the users and groups that access a share to be specified\&. Users and groups are specified, delimited by spaces or commas\&. Groups are designated by a @ prefix\&. Names may be quoted in order to allow for spaces in names\&. Example:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+valid users = user "user 2" @group \(lq@group 2"
+.fi
+.if n \{\
+.RE
+.\}
.RE
.PP
invalid users = \fIusers/groups\fR \fB(V)\fR
Try
\fBsys\fR
(by setting an EA on the shared directory itself), fallback to
-\fBad\fR\&. Requires writeable volume for perfoming test\&. "\fBread only = yes\fR" overwrites
+\fBad\fR\&. Requires writable volume for performing test\&. "\fBread only = yes\fR" overwrites
\fBauto\fR
with
-\fBnone\fR\&. Use explicit "\fBea = sys|ad\fR" for read\-only volumes where appropiate\&.
+\fBnone\fR\&. Use explicit "\fBea = sys|ad\fR" for read\-only volumes where appropriate\&.
.RE
.PP
sys
\fBfile perm\fR
is for files only,
\fBdirectory perm\fR
-is for directories only\&. Don\'t use with "\fBunix priv = no\fR"\&.
+is for directories only\&. Don\*(Aqt use with "\fBunix priv = no\fR"\&.
.PP
\fBExample.\ \&Volume for a collaborative workgroup\fR
.sp
.RS 4
.\}
.nf
-file perm = 0660
-directory perm = 0770
+file perm = 0660 directory perm =
+ 0770
.fi
.if n \{\
.RE
.PP
umask = \fImode\fR \fB(V)\fR
.RS 4
-set perm mask\&. Don\'t use with "\fBunix priv = no\fR"\&.
+set perm mask\&. Don\*(Aqt use with "\fBunix priv = no\fR"\&.
.RE
.PP
preexec = \fIcommand\fR \fB(V)\fR
.PP
veto files = \fIvetoed names\fR \fB(V)\fR
.RS 4
-hide files and directories,where the path matches one of the \'/\' delimited vetoed names\&. The veto string must always be terminated with a \'/\', 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\&. "veto1/", "veto1/veto2/"\&.
.RE
.SS "Volume options"
.PP
\fBappledouble = v2\fR
to
\fBappledouble = ea\fR
-is performed when accessing filesystems from clients\&. This is generally useful, but costs some performance\&. It\'s recommdable to run
+is performed when accessing filesystems from clients\&. This is generally useful, but costs some performance\&. It\*(Aqs recommendable to run
\fBdbd\fR
on volumes and do the conversion with that\&. Then this option can be set to no\&.
.RE
.PP
+follow symlinks = \fIBOOLEAN\fR (default: \fIno\fR) \fB(V)\fR
+.RS 4
+The default setting is false thus symlinks are not followed on the server\&. This is the same behaviour as OS X\*(Aqs AFP server\&. Setting the option to true causes afpd to follow symlinks on the server\&. symlinks may point outside of the AFP volume, currently afpd doesn\*(Aqt do any checks for "wide symlinks"\&.
+.RE
+.PP
invisible dots = \fIBOOLEAN\fR (default: \fIno\fR) \fB(V)\fR
.RS 4
make dot files invisible\&.
.PP
time machine = \fIBOOLEAN\fR (default: \fIno\fR) \fB(V)\fR
.RS 4
-Whether to enable Time Machine suport for this volume\&.
+Whether to enable Time Machine support for this volume\&.
.RE
.PP
unix priv = \fIBOOLEAN\fR (default: \fIyes\fR) \fB(V)\fR
.RE
.SH "CNID BACKENDS"
.PP
-The AFP protocol mostly refers to files and directories by ID and not by name\&. Netatalk needs a way to store these ID\'s in a persistent way, to achieve this several different CNID backends are available\&. The CNID Databases are by default located in the
+The AFP protocol mostly refers to files and directories by ID and not by name\&. Netatalk needs a way to store these ID\*(Aqs in a persistent way, to achieve this several different CNID backends are available\&. The CNID Databases are by default located in the
:STATEDIR:/netatalk/CNID/(volumename)/\&.AppleDB/
directory\&.
.PP
cdb
.RS 4
-"Concurrent database", backend is based on Oracle Berkely DB\&. With this backend several
+"Concurrent database", backend is based on Oracle Berkley DB\&. With this backend several
\fBafpd\fR
-deamons access the CNID database directly\&. Berkeley DB locking is used to synchronize access, if more than one
+daemons access the CNID database directly\&. Berkeley DB locking is used to synchronize access, if more than one
\fBafpd\fR
process is active for a volume\&. The drawback is, that the crash of a single
\fBafpd\fR
.PP
last
.RS 4
-This backend is an exception, in terms of ID persistency\&. ID\'s are only valid for the current session\&. This is basically what
+This backend is an exception, in terms of ID persistency\&. ID\*(Aqs are only valid for the current session\&. This is basically what
\fBafpd\fR
did in the 1\&.5 (and 1\&.6) versions\&. This backend is still available, as it is useful for e\&.g\&. sharing cdroms\&. Starting with Netatalk 3\&.0, it becomes the
\fIread only mode\fR
.PP
Even though
\fB\&./configure \-\-help\fR
-might show that there are other CNID backends available, be warned those are likely broken or mainly used for testing\&. Don\'t use them unless you know what you\'re doing, they may be removed without further notice from future versions\&.
+might show that there are other CNID backends available, be warned those are likely broken or mainly used for testing\&. Don\*(Aqt use them unless you know what you\*(Aqre doing, they may be removed without further notice from future versions\&.
.SH "CHARSET OPTIONS"
.PP
With OS X Apple introduced the AFP3 protocol\&. One of the most important changes was that AFP3 uses unicode names encoded as UTF\-8 decomposed\&. Previous AFP/OS versions used codepages, like MacRoman, MacCentralEurope, etc\&.
.PP
\fBafpd\fR
-needs a way to preserve extended macintosh characters, or characters illegal in unix filenames, when saving files on a unix filesystem\&. Earlier versions used the the so called CAP encoding\&. An extended character (>0x7F) would be converted to a :xx sequence, e\&.g\&. the Apple Logo (MacRoman: 0xF0) was saved as
-:f0\&. Some special characters will be converted as to :xx notation as well\&. \'/\' will be encoded to
+needs a way to preserve extended Macintosh characters, or characters illegal in unix filenames, when saving files on a unix filesystem\&. Earlier versions used the the so called CAP encoding\&. An extended character (>0x7F) would be converted to a :xx sequence, e\&.g\&. the Apple Logo (MacRoman: 0xF0) was saved as
+:f0\&. Some special characters will be converted as to :xx notation as well\&. \*(Aq/\*(Aq will be encoded to
:2f, if
\fBusedots\fR
-is not specified, a leading dot \'\&.\' will be encoded as
+is not specified, a leading dot \*(Aq\&.\*(Aq will be encoded as
:2e\&.
.PP
-This version now uses UTF\-8 as the default encoding for names\&. \'/\' will be converted to \':\'\&.
+This version now uses UTF\-8 as the default encoding for names\&. \*(Aq/\*(Aq will be converted to \*(Aq:\*(Aq\&.
.PP
The
\fBvol charset\fR
will convert the UTF\-8
character to
\fBmac charset\fR
-first\&. If this conversion fails, you\'ll receive a \-50 error on the mac\&.
+first\&. If this conversion fails, you\*(Aqll receive a \-50 error on the mac\&.
.PP
\fINote\fR: Whenever you can, please stick with the default UTF\-8 volume format\&.
.SH "SEE ALSO"
\fBafpd\fR(8),
\fBafppasswd\fR(5),
\fBafp_signature.conf\fR(5),
+\fBextmap.conf\fR(5),
\fBcnid_metad\fR(8)
'\" t
.\" Title: afp_signature.conf
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
+.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
.\" Date: 23 Mar 2012
.\" Manual: Netatalk 3.0
.\" Source: Netatalk 3.0
.\"
.TH "AFP_SIGNATURE\&.CONF" "5" "23 Mar 2012" "Netatalk 3.0" "Netatalk 3.0"
.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
'\" t
.\" Title: afp_voluuid.conf
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
+.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
.\" Date: 23 Mar 2012
.\" Manual: Netatalk 3.0
.\" Source: Netatalk 3.0
.\"
.TH "AFP_VOLUUID\&.CONF" "5" "23 Mar 2012" "Netatalk 3.0" "Netatalk 3.0"
.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
--- /dev/null
+'\" t
+.\" Title: extmap.conf
+.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
+.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
+.\" Date: 19 Jan 2013
+.\" Manual: Netatalk 3.0
+.\" Source: Netatalk 3.0
+.\" Language: English
+.\"
+.TH "EXTMAP\&.CONF" "5" "19 Jan 2013" "Netatalk 3.0" "Netatalk 3.0"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+extmap.conf \- Configuration file used by afpd(8) to specify file name extension mappings\&.
+.SH "SYNOPSIS"
+.HP \w'\fB:ETCDIR:/extmap\&.conf\fR\fB\fR\ 'u
+\fB:ETCDIR:/extmap\&.conf\fR\fB\fR
+.SH "DESCRIPTION"
+.PP
+
+:ETCDIR:/extmap\&.conf
+is the configuration file used by
+\fBafpd\fR
+to specify file name extension mappings\&.
+.PP
+The configuration lines are composed like:
+.PP
+\&.extension
+\fI[ type [ creator ] ]\fR
+.PP
+Any line beginning with a hash (\(lq#\(rq) character is ignored\&. The leading\-dot lines specify file name extension mappings\&. The extension \*(Aq\&.\*(Aq sets the default creator and type for otherwise untyped Unix files\&.
+.SH "EXAMPLES"
+.PP
+\fBExample.\ \&Extension is jpg. Type is "JPEG". Creator is "ogle".\fR
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+\&.jpg "JPEG" "ogle"
+.fi
+.if n \{\
+.RE
+.\}
+.PP
+\fBExample.\ \&Extension is lzh. Type is "LHA ". Creator is not defined.\fR
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+\&.lzh "LHA "
+.fi
+.if n \{\
+.RE
+.\}
+.SH "SEE ALSO"
+.PP
+\fBafp.conf\fR(5),
+\fBafpd\fR(8)
'\" t
.\" Title: afpd
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
-.\" Date: 23 Mar 2012
+.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
+.\" Date: 19 Jan 2013
.\" Manual: Netatalk 3.0
.\" Source: Netatalk 3.0
.\" Language: English
.\"
-.TH "AFPD" "8" "23 Mar 2012" "Netatalk 3.0" "Netatalk 3.0"
+.TH "AFPD" "8" "19 Jan 2013" "Netatalk 3.0" "Netatalk 3.0"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.RE
.SH "SIGNALS"
.PP
-To shut down a user\'s
+To shut down a user\*(Aqs
\fBafpd\fR
process it is recommended that
\fBSIGKILL (\-9)\fR
\fBafpd\fR
enables
\fImax_debug\fR
-logging for this process\&. The log is sent to fhe file
+logging for this process\&. The log is sent to the file
/tmp/afpd\&.PID\&.XXXXXX\&. Sending another
\fBSIGINT\fR
will revert to the original log settings\&.
list of UUID for Time Machine volume
.RE
.PP
+:ETCDIR:/extmap\&.conf
+.RS 4
+file name extension mapping
+.RE
+.PP
:ETCDIR:/msg/message\&.pid
.RS 4
contains messages to be sent to users\&.
\fBafp.conf\fR(5),
\fBafp_signature.conf\fR(5),
\fBafp_voluuid.conf\fR(5),
+\fBextmap.conf\fR(5),
\fBdbd\fR(1)\&.
'\" t
.\" Title: cnid_dbd
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
+.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
.\" Date: 01 Jan 2012
.\" Manual: Netatalk 3.0
.\" Source: Netatalk 3.0
.\"
.TH "CNID_DBD" "8" "01 Jan 2012" "Netatalk 3.0" "Netatalk 3.0"
.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
.PP
\fBcnid_dbd\fR
uses the
-\fBBerkleley DB\fR
+\fBBerkeley DB\fR
database library and uses transactionally protected updates\&. The
\fBdbd\fR
backend with transactions will avoid corruption of the CNID database even if the system crashes unexpectedly\&.
on startup, which is normally caused by
\fBafpd\fR
serving a netatalk volume to a client\&. It changes to the
-\fBBerkleley DB\fR
+\fBBerkeley DB\fR
database home directory
\fIdbdir\fR
that is associated with the volume\&. If the userid inherited from
can be configured to run forever or to exit after a period of inactivity\&. If
\fBcnid_dbd\fR
receives a TERM or an INT signal it will exit cleanly after flushing dirty database buffers to disk and closing
-\fBBerkleley DB\fR
+\fBBerkeley DB\fR
database environments\&. It is safe to terminate
\fBcnid_dbd\fR
this way, it will be restarted when necessary\&. Other signals are not handled and will cause an immediate exit, possibly leaving the CNID database in an inconsistent state (no transactions) or losing recent updates during recovery (transactions)\&.
.PP
The
-\fBBerkleley DB\fR
+\fBBerkeley DB\fR
database subsystem will create files named log\&.xxxxxxxxxx in the database home directory
-\fIdbdir\fR, where xxxxxxxxxx is a monotonically increasing integer\&. These files contain ithe transactional database changes\&. They will be removed regularily, unless the
+\fIdbdir\fR, where xxxxxxxxxx is a monotonically increasing integer\&. These files contain the transactional database changes\&. They will be removed regularly, unless the
\fBlogfile_autoremove\fR
option is specified in the
\fIdb_param\fR
configuration file (see below) with a value of 0 (default 1)\&.
-.PP
-Do not use
-\fBcnid_dbd\fR
-for databases on NFS mounted file systems\&. It makes the whole point of securing database changes properly moot\&. Use the dbdir: Option in the appropriate
-\fBAppleVolumes\fR
-configuration file to put the database onto a local disk\&.
.SH "OPTIONS"
.PP
\fB\-v, \-V\fR
.RS 4
If set to 0, unused Berkeley DB transactional logfiles (log\&.xxxxxxxxxx in the database home directory) are not removed on startup of
\fBcnid_dbd\fR
-and on a reqular basis\&. Default: 1\&.
+and on a regular basis\&. Default: 1\&.
.RE
.PP
\fBcachesize\fR
\fBdb_stat\fR
utility with the
\fB\-m\fR
-option that comes with Berkely DB can help you determine wether you need to change this value\&. The default is pretty conservative so that a large percentage of requests should be satisfied from the cache directly\&. If memory is not a bottleneck on your system you might want to leave it at that value\&. The
+option that comes with Berkley DB can help you determine ether you need to change this value\&. The default is pretty conservative so that a large percentage of requests should be satisfied from the cache directly\&. If memory is not a bottleneck on your system you might want to leave it at that value\&. The
\fBBerkeley DB Tutorial and Reference Guide\fR
has a section
\fBSelecting a cache size\fR
.PP
Note that the first version to appear
\fIafter\fR
-Netatalk 2\&.1 ie Netatalk 2\&.1\&.1, will support BerkeleyDB updates on the fly without manual intervention\&. In other words Netatalk 2\&.1 does contain code to prepare the BerkeleyDB database for upgrades and to upgrade it in case it has been prepared before\&. That means it can\'t upgrade a 2\&.0\&.x version because that one didn\'t prepare the database\&.
+Netatalk 2\&.1 ie Netatalk 2\&.1\&.1, will support BerkeleyDB updates on the fly without manual intervention\&. In other words Netatalk 2\&.1 does contain code to prepare the BerkeleyDB database for upgrades and to upgrade it in case it has been prepared before\&. That means it can\*(Aqt upgrade a 2\&.0\&.x version because that one didn\*(Aqt prepare the database\&.
.PP
In order to update between older Netatalk releases using different BerkeleyDB library versions, follow this steps:
.sp
'\" t
.\" Title: cnid_metad
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
+.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
.\" Date: 23 Mar 2012
.\" Manual: Netatalk 3.0
.\" Source: Netatalk 3.0
.\"
.TH "CNID_METAD" "8" "23 Mar 2012" "Netatalk 3.0" "Netatalk 3.0"
.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
.PP
\fBcnid_metad\fR
does not block or catch any signals apart from SIGPIPE\&. It will therefore exit on most signals received\&. This will also cause all instances of
-\fBcnid_dbd\'s\fR
+\fBcnid_dbd\*(Aqs\fR
started by that
\fBcnid_metad\fR
to exit gracefully\&. Since state about and IPC access to the subprocesses is only maintained in memory by
'\" t
.\" Title: netatalk
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
+.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
.\" Date: 22 Mar 2012
.\" Manual: Netatalk 3.0
.\" Source: Netatalk 3.0
.\"
.TH "NETATALK" "8" "22 Mar 2012" "Netatalk 3.0" "Netatalk 3.0"
.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
$(top_srcdir)/etc/afpd/file.c \
$(top_srcdir)/etc/afpd/filedir.c \
$(top_srcdir)/etc/afpd/fork.c \
- $(top_srcdir)/etc/afpd/gettok.c \
$(top_srcdir)/etc/afpd/hash.c \
$(top_srcdir)/etc/afpd/mangle.c \
$(top_srcdir)/etc/afpd/messages.c \
/*
- $Id: afpfunc_helpers.c,v 1.1.2.1 2010-02-01 10:56:08 franklahm Exp $
Copyright (c) 2010 Frank Lahm <franklahm@gmail.com>
This program is free software; you can redistribute it and/or modify
/*
- $Id: afpfunc_helpers.h,v 1.1.2.1 2010-02-01 10:56:08 franklahm Exp $
Copyright (c) 2010 Frank Lahm <franklahm@gmail.com>
This program is free software; you can redistribute it and/or modify
/*
- $Id: subtests.h,v 1.1.2.1 2010-02-01 10:56:08 franklahm Exp $
Copyright (c) 2010 Frank Lahm <franklahm@gmail.com>
This program is free software; you can redistribute it and/or modify
TEST_int( afp_config_parse(&obj, NULL), 0);
TEST_int( configinit(&obj), 0);
TEST( cnid_init() );
- TEST( load_volumes(&obj, NULL) );
+ TEST( load_volumes(&obj) );
TEST_int( dircache_init(8192), 0);
obj.afp_version = 32;
/*
- $Id: test.h,v 1.1.2.1 2010-02-01 10:56:08 franklahm Exp $
Copyright (c) 2010 Frank Lahm <franklahm@gmail.com>
This program is free software; you can redistribute it and/or modify