netatalk  4.6.1
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)   (a)->of_ad->ad_name
 

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 ofork * of_alloc (struct vol *, struct dir *, char *, uint16_t *, const int, struct adouble *, struct stat *)
 
void of_dealloc (struct ofork *)
 
struct ofork * of_find (const uint16_t)
 
struct ofork * of_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 adouble * of_ad (const struct vol *, struct path *, struct adouble *)
 
struct ofork * of_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)    (a)->of_ad->ad_name

◆ 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()

static 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