|
| static unsigned long | hashfn (const struct file_key *key) |
| static void | of_hash (struct ofork *of) |
| static void | of_unhash (struct ofork *of) |
| static bool | of_freeq_empty (void) |
| static void | of_freeq_push (uint16_t slot) |
| static int | of_freeq_pop (void) |
| void | of_pforkdesc (FILE *f) |
| int | of_flush (const struct vol *vol) |
| int | of_rename (const struct vol *vol, struct ofork *s_of, struct dir *olddir, const char *oldpath, struct dir *newdir, const char *newpath) |
| struct ofork * | of_alloc (struct vol *vol, struct dir *dir, char *path, uint16_t *ofrefnum, const int eid, struct adouble *ad, struct stat *st) |
| struct ofork * | of_find (const uint16_t ofrefnum) |
| int | of_stat (const struct vol *vol, struct path *path) |
| int | of_fstatat (int dirfd, struct path *path) |
| int | of_statdir (struct vol *vol, struct path *path) |
| | stat the current directory.
|
| struct ofork * | of_findname (const struct vol *vol, struct path *path) |
| 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_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.
|
| void | of_dealloc (struct ofork *of) |
| void | of_log_highwater (void) |
| int | of_closefork (const AFPObj *obj, struct ofork *ofork) |
| struct adouble * | of_ad (const struct vol *vol, struct path *path, struct adouble *ad) |
| void | of_closevol (const AFPObj *obj, const struct vol *vol) |
| void | of_close_all_forks (const AFPObj *obj) |
| 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.
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] | obj | the AFP session object |
| [in] | vol | volume the deleted file lived on |
| [in] | path | deleted file; path->st must be the pre-delete stat (the file no longer exists, so a re-stat cannot rebuild it) |
| 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?
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] | of | a fork this child holds on the file |
| [out] | band | held blocking band bits, positional (may be NULL) |
| [out] | content | set if a content byte-range lock is held (may be NULL) |
- Returns
- nonzero if the delete must be refused
| 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.
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] | vol | volume the target lives on |
| [in] | dirfd | directory fd for openat-style resolution, or -1 |
| [in] | path | target; both fork inodes derive from it |
| [in] | df_get | probe data-fork content if non-zero |
| [in] | df_off | data-fork content offset |
| [in] | df_len | data-fork content length (0 = whole data zone) |
| [in] | rf_get | probe resource-fork content if non-zero |
| [in] | rf_off | resource-fork content offset |
| [in] | rf_len | resource-fork content length (0 = whole zone) |
| [in] | band_request | share-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_root | retry the open as root on EACCES (the band is the server's own bookkeeping, not a user permission) |
| [out] | df_locked | set if the data-fork content range is locked |
| [out] | rf_locked | set if the resource-fork content range is locked |
| [out] | band_held | positional 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).