netatalk  4.6.0
Free and Open Source Apple Filing Protocol (AFP) Server
Loading...
Searching...
No Matches
fork.h File Reference
#include <arpa/inet.h>
#include <stdio.h>
#include <atalk/adouble.h>
#include "directory.h"
#include "volume.h"

Go to the source code of this file.

Data Structures

struct  file_key
struct  ofork

Macros

#define OPENFORK_DATA   (0)
#define OPENFORK_RSCS   (1<<7)
#define OPENACC_RD   (1<<0)
#define OPENACC_WR   (1<<1)
#define OPENACC_DRD   (1<<4)
#define OPENACC_DWR   (1<<5)
#define AFPFORK_DATA   (1<<0)
#define AFPFORK_RSRC   (1<<1)
#define AFPFORK_META   (1<<2)
#define AFPFORK_DIRTY   (1<<3)
#define AFPFORK_ACCRD   (1<<4)
#define AFPFORK_ACCWR   (1<<5)
#define AFPFORK_ACCMASK   (AFPFORK_ACCRD | AFPFORK_ACCWR)
#define AFPFORK_MODIFIED   (1<<6)
#define AFPFORK_ERROR   (1<<7)
#define AFPFORK_VIRTUAL   (1<<8)
#define of_name(a)

Enumerations

enum  of_locks_status { OF_LOCKS_ERROR = -1 , OF_LOCKS_OK = 0 , OF_LOCKS_NOENT = 1 }

Functions

static int fork_range_within (off_t offset, off_t length, off_t size)
struct oforkof_alloc (struct vol *, struct dir *, char *, uint16_t *, const int, struct adouble *, struct stat *)
void of_dealloc (struct ofork *)
struct oforkof_find (const uint16_t)
struct oforkof_findname (const struct vol *vol, struct path *)
int of_rename (const struct vol *, struct ofork *, struct dir *, const char *, struct dir *, const char *)
int of_flush (const struct vol *)
void of_pforkdesc (FILE *)
void of_log_highwater (void)
int of_stat (const struct vol *vol, struct path *)
int of_statdir (struct vol *vol, struct path *)
 stat the current directory.
int of_closefork (const AFPObj *obj, struct ofork *ofork)
void of_closevol (const AFPObj *obj, const struct vol *vol)
void of_close_all_forks (const AFPObj *obj)
struct adoubleof_ad (const struct vol *, struct path *, struct adouble *)
struct oforkof_findnameat (int dirfd, struct path *path)
 Search for open fork by dirfd/name.
int of_delete_blocked (const struct ofork *of, uint16_t *band, int *content)
 Does this child hold a delete-blocking claim on the fork's file?
void of_close_inode_forks (const AFPObj *obj, const struct vol *vol, struct path *path)
 Close every fork this child holds on path's inode.
int of_fstatat (int dirfd, struct path *path)
int of_get_locks (const struct vol *vol, int dirfd, struct path *path, int df_get, off_t df_off, off_t df_len, int rf_get, off_t rf_off, off_t rf_len, uint16_t band_request, int try_root, int *df_locked, int *rf_locked, uint16_t *band_held)
 Conflict GET (F_GETLK only): read another holder's locks on a file.
int flushfork (struct ofork *)
int fork_setmode_deny (int access, int f_rddny, int f_wrdny, int f_nodny)
int afp_openfork (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
int afp_bytelock (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
int afp_getforkparams (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
int afp_setforkparams (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
int afp_read (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
int afp_write (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
int afp_flushfork (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
int afp_flush (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
int afp_closefork (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
int afp_bytelock_ext (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
int afp_read_ext (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
int afp_write_ext (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
int afp_syncfork (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)

Macro Definition Documentation

◆ AFPFORK_ACCMASK

#define AFPFORK_ACCMASK   (AFPFORK_ACCRD | AFPFORK_ACCWR)

◆ AFPFORK_ACCRD

#define AFPFORK_ACCRD   (1<<4)

◆ AFPFORK_ACCWR

#define AFPFORK_ACCWR   (1<<5)

◆ AFPFORK_DATA

#define AFPFORK_DATA   (1<<0)

open datafork

◆ AFPFORK_DIRTY

#define AFPFORK_DIRTY   (1<<3)

◆ AFPFORK_ERROR

#define AFPFORK_ERROR   (1<<7)

used to indicate an error in opening the fork

◆ AFPFORK_META

#define AFPFORK_META   (1<<2)

open metadata

◆ AFPFORK_MODIFIED

#define AFPFORK_MODIFIED   (1<<6)

used in FCE for modified files

◆ AFPFORK_RSRC

#define AFPFORK_RSRC   (1<<1)

open rsrcfork

◆ AFPFORK_VIRTUAL

#define AFPFORK_VIRTUAL   (1<<8)

virtual file fork

◆ of_name

#define of_name ( a)
Value:
struct adouble * of_ad(const struct vol *, struct path *, struct adouble *)
Definition ofork.c:1213
char * ad_name
Definition adouble.h:225

◆ OPENACC_DRD

#define OPENACC_DRD   (1<<4)

◆ OPENACC_DWR

#define OPENACC_DWR   (1<<5)

◆ OPENACC_RD

#define OPENACC_RD   (1<<0)

◆ OPENACC_WR

#define OPENACC_WR   (1<<1)

◆ OPENFORK_DATA

#define OPENFORK_DATA   (0)

◆ OPENFORK_RSCS

#define OPENFORK_RSCS   (1<<7)

Enumeration Type Documentation

◆ of_locks_status

Enumerator
OF_LOCKS_ERROR 
OF_LOCKS_OK 
OF_LOCKS_NOENT 

Function Documentation

◆ afp_bytelock()

int afp_bytelock ( AFPObj * obj,
char * ibuf,
size_t ibuflen,
char * rbuf,
size_t * rbuflen )

◆ afp_bytelock_ext()

int afp_bytelock_ext ( AFPObj * obj,
char * ibuf,
size_t ibuflen,
char * rbuf,
size_t * rbuflen )

◆ afp_closefork()

int afp_closefork ( AFPObj * obj,
char * ibuf,
size_t ibuflen,
char * rbuf,
size_t * rbuflen )

◆ afp_flush()

int afp_flush ( AFPObj * obj,
char * ibuf,
size_t ibuflen,
char * rbuf,
size_t * rbuflen )

◆ afp_flushfork()

int afp_flushfork ( AFPObj * obj,
char * ibuf,
size_t ibuflen,
char * rbuf,
size_t * rbuflen )

◆ afp_getforkparams()

int afp_getforkparams ( AFPObj * obj,
char * ibuf,
size_t ibuflen,
char * rbuf,
size_t * rbuflen )

◆ afp_openfork()

int afp_openfork ( AFPObj * obj,
char * ibuf,
size_t ibuflen,
char * rbuf,
size_t * rbuflen )

◆ afp_read()

int afp_read ( AFPObj * obj,
char * ibuf,
size_t ibuflen,
char * rbuf,
size_t * rbuflen )

◆ afp_read_ext()

int afp_read_ext ( AFPObj * obj,
char * ibuf,
size_t ibuflen,
char * rbuf,
size_t * rbuflen )

◆ afp_setforkparams()

int afp_setforkparams ( AFPObj * obj,
char * ibuf,
size_t ibuflen,
char * rbuf,
size_t * rbuflen )

◆ afp_syncfork()

int afp_syncfork ( AFPObj * obj,
char * ibuf,
size_t ibuflen,
char * rbuf,
size_t * rbuflen )
Bug
There is a lot to tell about fsync, fdatasync, F_FULLFSYNC. fsync(2) on OSX is implemented differently than on other platforms.
See also
http://mirror.linux.org.au/pub/linux.conf.au/2007/video/talks/278.pdf

◆ afp_write()

int afp_write ( AFPObj * obj,
char * ibuf,
size_t ibuflen,
char * rbuf,
size_t * rbuflen )

◆ afp_write_ext()

int afp_write_ext ( AFPObj * obj,
char * ibuf,
size_t ibuflen,
char * rbuf,
size_t * rbuflen )

◆ flushfork()

int flushfork ( struct ofork * ofork)
extern

◆ fork_range_within()

int fork_range_within ( off_t offset,
off_t length,
off_t size )
inlinestatic

◆ fork_setmode_deny()

int fork_setmode_deny ( int access,
int f_rddny,
int f_wrdny,
int f_nodny )
extern

◆ of_ad()

struct adouble * of_ad ( const struct vol * vol,
struct path * path,
struct adouble * ad )
extern

◆ of_alloc()

struct ofork * of_alloc ( struct vol * vol,
struct dir * dir,
char * path,
uint16_t * ofrefnum,
const int eid,
struct adouble * ad,
struct stat * st )
extern

◆ of_close_all_forks()

void of_close_all_forks ( const AFPObj * obj)
extern

close all forks

◆ of_close_inode_forks()

void of_close_inode_forks ( const AFPObj * obj,
const struct vol * vol,
struct path * path )
extern

Close every fork this child holds on path's inode.

Same-session sweep for FPDelete, called after a successful delete: every refusal condition (DeleteInhibit, peer claims, the session's own claims via of_delete_blocked()) has already passed and the file is unlinked, so only claim-free forks (any OPEN_* access, no deny mode, no content lock) reach this sweep. Each fork is closed individually — the blocking check needs one fork (shared adouble), the close needs them all. of_closefork() deallocs even on flush error (nothing is stranded), so a failed close is logged and the sweep continues — matching of_closevol().

Parameters
[in]objthe AFP session object
[in]volvolume the deleted file lived on
[in]pathdeleted file; path->st must be the pre-delete stat (the file no longer exists, so a re-stat cannot rebuild it)

◆ of_closefork()

int of_closefork ( const AFPObj * obj,
struct ofork * ofork )
extern

◆ of_closevol()

void of_closevol ( const AFPObj * obj,
const struct vol * vol )
extern

close all forks for a volume

◆ of_dealloc()

void of_dealloc ( struct ofork * of)
extern

◆ of_delete_blocked()

int of_delete_blocked ( const struct ofork * of,
uint16_t * band,
int * content )
extern

Does this child hold a delete-blocking claim on the fork's file?

The cross-process conflict check (deletefile()'s F_GETLK read) cannot by POSIX report the calling process's own locks, so the delete path asks this helper for the local complement: scan the session's own lock bookkeeping for the same claims and apply the same DELETE_BLOCKING_BAND_BITS policy — a deny mode or content byte-range lock refuses the delete whether its holder is a peer process or this session itself. OPEN_* markers never block (an open is just an open; only declared claims do).

Any one fork on the file suffices as of: sibling forks on an inode share one adouble, whose data-fork adf_lock[] holds ALL of the session's band entries (OPEN/DENY incl. the RSRC_* mirrors via rf2off) and its own content ranges; the rfork's adf_lock[] (reached via ad_rfp on the same adouble) holds only rfork content ranges. So one lookup sees every claim — unlike the post-delete sweep, which must visit each fork to close it.

Parameters
[in]ofa fork this child holds on the file
[out]bandheld blocking band bits, positional (may be NULL)
[out]contentset if a content byte-range lock is held (may be NULL)
Returns
nonzero if the delete must be refused

◆ of_find()

struct ofork * of_find ( const uint16_t ofrefnum)
extern

◆ of_findname()

struct ofork * of_findname ( const struct vol * vol,
struct path * path )
extern

◆ of_findnameat()

struct ofork * of_findnameat ( int dirfd,
struct path * path )
extern

Search for open fork by dirfd/name.

Function call of_fstatat with dirfd and path and uses dev and ino to search the open fork table.

Parameters
[in]dirfddirectory fd
[in,out]pathpointer to struct path

◆ of_flush()

int of_flush ( const struct vol * vol)
extern

◆ of_fstatat()

int of_fstatat ( int dirfd,
struct path * path )
extern

◆ of_get_locks()

int of_get_locks ( const struct vol * vol,
int dirfd,
struct path * path,
int df_get,
off_t df_off,
off_t df_len,
int rf_get,
off_t rf_off,
off_t rf_len,
uint16_t band_request,
int try_root,
int * df_locked,
int * rf_locked,
uint16_t * band_held )
extern

Conflict GET (F_GETLK only): read another holder's locks on a file.

Reuses a held fork's fd when one exists, else opens+closes a transient one. Reading through a held fd (never a transient open+close on an inode we hold a lock on) is what keeps the held byte locks from being dropped on close. The rfork is never opened onto of->of_ad (would corrupt ad_rlen / underflow the v2 meta refcount).

Parameters
[in]volvolume the target lives on
[in]dirfddirectory fd for openat-style resolution, or -1
[in]pathtarget; both fork inodes derive from it
[in]df_getprobe data-fork content if non-zero
[in]df_offdata-fork content offset
[in]df_lendata-fork content length (0 = whole data zone)
[in]rf_getprobe resource-fork content if non-zero
[in]rf_offresource-fork content offset
[in]rf_lenresource-fork content length (0 = whole zone)
[in]band_requestshare-mode band bitmap; OR together the per-offset *_BIT aliases from adouble.h (or ALL_BAND_BITS for all ten). Bit n maps to offset AD_FILELOCK_BASE + n.
[in]try_rootretry the open as root on EACCES (the band is the server's own bookkeeping, not a user permission)
[out]df_lockedset if the data-fork content range is locked
[out]rf_lockedset if the resource-fork content range is locked
[out]band_heldpositional bitmap of held band bits (same positions as band_request)
Returns
OF_LOCKS_OK (0) outputs valid (all 0 == nothing locked) OF_LOCKS_NOENT (1) target absent; outputs stay zeroed OF_LOCKS_ERROR(-1) lock state indeterminate -> caller must fail closed Outputs are zeroed on entry and only populated on OF_LOCKS_OK, so a caller that ignores the return still reads zeros, never stale data - but the return MUST be checked (zeros do not mean "no locks").

Data/band fd is fail-closed (any non-ENOENT failure -> ERROR). The rfork-content leg is best-effort (rf_locked stays 0 on open failure / the HAVE_EAFD && SOLARIS skip; the rfork band is still read via the data fd).

◆ of_log_highwater()

void of_log_highwater ( void )
extern

◆ of_pforkdesc()

void of_pforkdesc ( FILE * f)
extern

◆ of_rename()

int of_rename ( const struct vol * vol,
struct ofork * s_of,
struct dir * olddir,
const char * oldpath,
struct dir * newdir,
const char * newpath )
extern

◆ of_stat()

int of_stat ( const struct vol * vol,
struct path * path )
extern

◆ of_statdir()

int of_statdir ( struct vol * vol,
struct path * path )
extern

stat the current directory.

Note
stat(".") works even if "." is deleted thus we have to stat ../name because we want to know if it's there