netatalk 4.4.3
Free and Open Source Apple Filing Protocol (AFP) Server
Loading...
Searching...
No Matches
ea_ad.c File Reference
`#include <arpa/inet.h>`
`#include <dirent.h>`
`#include <errno.h>`
`#include <fcntl.h>`
`#include <stdint.h>`
`#include <stdlib.h>`
`#include <string.h>`
`#include <sys/stat.h>`
`#include <sys/types.h>`
`#include <unistd.h>`
`#include <atalk/adouble.h>`
`#include <atalk/afp.h>`
`#include <atalk/compat.h>`
`#include <atalk/ea.h>`
`#include <atalk/logger.h>`
`#include <atalk/unix.h>`
`#include <atalk/util.h>`
`#include <atalk/vfs.h>`
`#include <atalk/volume.h>`

## Functions
static mode_t | ea_header_mode (mode_t mode)
static mode_t | ea_mode (mode_t mode)
static char * | mtoupath (const struct vol *vol, const char *mpath)
static int | unpack_header (struct ea *ea)
| unpack and verify header file data buffer at ea->ea_data into struct ea
static int | pack_header (struct ea *ea)
| pack everything from struct ea into buffer at ea->ea_data
static int | ea_addentry (struct ea *ea, const char *attruname, size_t attrsize, int bitmap)
| add one EA into ea->ea_entries[]
static int | create_ea_header (const char *uname, struct ea *ea)
| create EA header file, only called from ea_open
static int | write_ea (const struct ea *ea, const char *attruname, const char *ibuf, size_t attrsize)
| write an EA to disk
static int | ea_delentry (struct ea *ea, const char *attruname)
| delete one EA from ea->ea_entries[]
static int | delete_ea_file (const struct ea *ea, const char *eaname)
| delete EA file from disk
char * | ea_path (const struct ea *ea, const char *eaname, int macname)
| return name of ea header filename
int | ea_open (const struct vol *vol, const char *uname, eaflags_t eaflags, struct ea *ea)
| open EA header file, create if it doesnt exits and called with O_CREATE
int | ea_openat (const struct vol *vol, int dirfd, const char *uname, eaflags_t eaflags, struct ea *ea)
| openat like wrapper for ea_open, takes a additional file descriptor
int | ea_close (struct ea *ea)
| flushes and closes an ea handle
int | get_easize (const struct vol *vol, char *rbuf, size_t *rbuflen, const char *uname, int oflag, const char *attruname, int fd)
| get size of an EA
int | get_eacontent (const struct vol *vol, char *rbuf, size_t *rbuflen, const char *uname, int oflag, const char *attruname, int maxreply, int fd)
| copy EA into rbuf
int | list_eas (const struct vol *vol, char *attrnamebuf, size_t *buflen, const char *uname, int oflag, int fd)
| copy names of EAs into attrnamebuf
int | set_ea (const struct vol *vol, const char *uname, const char *attruname, const char *ibuf, size_t attrsize, int oflag, int fd)
| set a Solaris native EA
int | remove_ea (const struct vol *vol, const char *uname, const char *attruname, int oflag, int fd)
| remove a EA from a file
int | ea_deletefile (const struct vol *vol, int dirfd, const char *file)
int | ea_renamefile (const struct vol *vol, int dirfd, const char *src, const char *dst)
int | ea_copyfile (const struct vol *vol, int sfd, const char *src, const char *dst)
| copy EAs
int | ea_chown (const struct vol *vol, const char *path, uid_t uid, gid_t gid)
int | ea_chmod_file (const struct vol *vol, const char *name, mode_t mode, struct stat *st)
int | ea_chmod_dir (const struct vol *vol, const char *name, mode_t mode, struct stat *st)

## Detailed Description

Store Extended Attributes inside .AppleDouble folders as follows:

filename "fileWithEAs" with EAs "testEA1" and "testEA2"

- create header with with the format struct adouble_ea_ondisk, the file is written to ".AppleDouble/fileWithEAs::EA"
- store EAs in files "fileWithEAs::EA::testEA1" and "fileWithEAs::EA::testEA2"

## Function Documentation

## ◆ create_ea_header()

int create_ea_header | ( | const char * | uname,
|  | struct ea * | ea )
| static

create EA header file, only called from ea_open

Parameters

  [in] | uname | filename for which we have to create a header
  [in,out] | ea | ea handle with already allocated storage pointed to by ea->ea_data

Returns
  fd of open header file on success, -1 on error, errno semantics: EEXIST: open with O_CREAT | O_EXCL failed

Note
  Creates EA header file and initialize ea->ea_data buffer. Possibe race condition with other afpd processes: we were called because header file didn't exist in e.g. ea_open. We then try to create a file with O_CREAT | O_EXCL, but the whole process in not atomic. What do we do then? Someone else is in the process of creating the header too, but it might not have finished it. That means we can't just open, read and use it! We therefor currently just break with an error. On return the header file is still r/w locked.

## ◆ delete_ea_file()

int delete_ea_file | ( | const struct ea * | ea,
|  | const char * | eaname )
| static

delete EA file from disk

Parameters

  [in] | ea | struct ea handle
  [in] | eaname | EA name

Returns
  0 on success, -1 on error

## ◆ ea_addentry()

int ea_addentry | ( | struct ea * | ea,
|  | const char * | attruname,
|  | size_t | attrsize,
|  | int | bitmap )
| static

add one EA into ea->ea_entries[]

Parameters

  [in,out] | ea | pointer to struct ea
  [in] | attruname | name of EA
  [in] | attrsize | size of ea
  [in] | bitmap | bitmap from FP func

Returns
  new number of EA entries, -1 on error

Note
  Grow array ea->ea_entries[]. If ea->ea_entries is still NULL, start allocating. Otherwise realloc and put entry at the end. Increments ea->ea_count.

## ◆ ea_chmod_dir()

int ea_chmod_dir | ( | const struct vol * | vol,
|  | const char * | name,
|  | mode_t | mode,
|  | struct stat * | st )

## ◆ ea_chmod_file()

int ea_chmod_file | ( | const struct vol * | vol,
|  | const char * | name,
|  | mode_t | mode,
|  | struct stat * | st )

## ◆ ea_chown()

int ea_chown | ( | const struct vol * | vol,
|  | const char * | path,
|  | uid_t | uid,
|  | gid_t | gid )

## ◆ ea_close()

int ea_close | ( | struct ea * | ea | ) |

flushes and closes an ea handle

Parameters

  [in,out] | ea | pointer to ea handle

Returns
  0 on success, -1 on error

Note
  Flushes and then closes and frees all resouces held by ea handle. Pack data in ea into ea_data, then write ea_data to disk

## ◆ ea_copyfile()

int ea_copyfile | ( | const struct vol * | vol,
|  | int | sfd,
|  | const char * | src,
|  | const char * | dst )

copy EAs

Parameters

  [in] | vol | current volume
  [in] | sfd | source file descriptor
  [in] | src | source path
  [in] | dst | destination path

Returns
  AFP code AFP_OK on success or appropriate AFP error code

Note
  Copies EAs from source file to dest file.

## ◆ ea_delentry()

int ea_delentry | ( | struct ea * | ea,
|  | const char * | attruname )
| static

delete one EA from ea->ea_entries[]

Parameters

  [in,out] | ea | pointer to struct ea
  [in] | attruname | EA name

Returns
  new number of EA entries, -1 on error

Note
  Remove entry from ea->ea_entries[]. Decrement ea->ea_count. Marks it as unused just by freeing name and setting it to NULL. ea_close and pack_buffer must honor this.

## ◆ ea_deletefile()

int ea_deletefile | ( | const struct vol * | vol,
|  | int | dirfd,
|  | const char * | file )

## ◆ ea_header_mode()

mode_t ea_header_mode | ( | mode_t | mode | ) |
| inline static

Build mode for EA header from file mode

## ◆ ea_mode()

mode_t ea_mode | ( | mode_t | mode | ) |
| inline static

Build mode for EA file from file mode

## ◆ ea_open()

int ea_open | ( | const struct vol * | vol,
|  | const char * | uname,
|  | eaflags_t | eaflags,
|  | struct ea * | ea )

open EA header file, create if it doesnt exits and called with O_CREATE

Parameters

  [in] | vol | current volume
  [in] | uname | filename for which we have to open a header
  [in] | eaflags | flag to control open behavior: EA_CREATE: create if it doesn't exist (without it won't be created) EA_RDONLY: open read only EA_RDWR: open read/write Either EA_RDONLY or EA_RDWR MUST be requested
  [out] | ea | pointer to a struct ea that we fill

Returns
  0 on success, -1 on misc error with errno = EFAULT, -2 if no EA header exists with errno = ENOENT

Note
  opens header file and stores fd in ea->ea_fd. Size of file is put into ea->ea_size. number of EAs is stored in ea->ea_count. flags are remembered in ea->ea_flags. file is either read or write locked depending on the open flags. When you're done with struct ea you must call ea_close on it.

## ◆ ea_openat()

int ea_openat | ( | const struct vol * | vol,
|  | int | dirfd,
|  | const char * | uname,
|  | eaflags_t | eaflags,
|  | struct ea * | ea )

openat like wrapper for ea_open, takes a additional file descriptor

Parameters

  [in] | vol | current volume
  [in] | dirfd | openat like file descriptor
  [in] | uname | filename for which we have to open a header
  [in] | eaflags | flag to control open behavior: EA_CREATE: create if it doesn't exist (without it won't be created) EA_RDONLY: open read only EA_RDWR: open read/write Either EA_RDONLY or EA_RDWR MUST be requested
  [out] | ea | pointer to a struct ea that we fill

Returns
  0 on success, -1 on misc error with errno = EFAULT, -2 if no EA header exists with errno = ENOENT

Note
  opens header file and stores fd in ea->ea_fd. Size of file is put into ea->ea_size. number of EAs is stored in ea->ea_count. flags are remembered in ea->ea_flags. file is either read or write locked depending on the open flags. When you're done with struct ea you must call ea_close on it.

## ◆ ea_path()

char * ea_path | ( | const struct ea * | ea,
|  | const char * | eaname,
|  | int | macname )

return name of ea header filename

Parameters

  [in] | ea | ea handle
  [in] | eaname | name of EA or NULL
  [in] | macname | if != 0 call mtoupath on eaname

Returns
  pointer to name in static buffer, NULL on error

Note
  - Calls ad_open, copies buffer, appends "::EA" and if supplied append eanme
  - Files: "file" -> "file/.AppleDouble/file::EA"
  - Dirs: "dir" -> "dir/.AppleDouble/.Parent::EA"
  - "file" with EA "myEA" -> "file/.AppleDouble/file::EA:myEA"

## ◆ ea_renamefile()

int ea_renamefile | ( | const struct vol * | vol,
|  | int | dirfd,
|  | const char * | src,
|  | const char * | dst )

## ◆ get_eacontent()

int get_eacontent | ( | const struct vol * | vol,
|  | char * | rbuf,
|  | size_t * | rbuflen,
|  | const char * | uname,
|  | int | oflag,
|  | const char * | attruname,
|  | int | maxreply,
|  | int | fd )

copy EA into rbuf

Parameters

  [in] | vol | current volume
  [out] | rbuf | DSI reply buffer
  [in,out] | rbuflen | current length of data in reply buffer
  [in] | uname | filename
  [in] | oflag | link and create flag
  [in] | attruname | name of attribute
  [in] | maxreply | maximum EA size as of current specs/real-life
  [in] | fd | file descriptor

Returns
  AFP code: AFP_OK on success or appropriate AFP error code

Note
  Copies EA into rbuf. Increments *rbuflen accordingly.

## ◆ get_easize()

int get_easize | ( | const struct vol * | vol,
|  | char * | rbuf,
|  | size_t * | rbuflen,
|  | const char * | uname,
|  | int | oflag,
|  | const char * | attruname,
|  | int | fd )

get size of an EA

Parameters

  [in] | vol | current volume
  [out] | rbuf | DSI reply buffer
  [in,out] | rbuflen | current length of data in reply buffer
  [in] | uname | filename
  [in] | oflag | link and create flag
  [in] | attruname | name of attribute
  [in] | fd | file descriptor

Returns
  AFP code: AFP_OK on success or appropriate AFP error code

Note
  Copies EA size into rbuf in network order. Increments *rbuflen +4.

## ◆ list_eas()

int list_eas | ( | const struct vol * | vol,
|  | char * | attrnamebuf,
|  | size_t * | buflen,
|  | const char * | uname,
|  | int | oflag,
|  | int | fd )

copy names of EAs into attrnamebuf

Parameters

  [in] | vol | current volume
  [out] | attrnamebuf | store names a consecutive C strings here
  [in,out] | buflen | length of names in attrnamebuf
  [in] | uname | filename
  [in] | oflag | link and create flag
  [in] | fd | file descriptor

Returns
  AFP code: AFP_OK on success or appropriate AFP error code

Note
  Copies names of all EAs of uname as consecutive C strings into rbuf. Increments *buflen accordingly.

## ◆ mtoupath()

char * mtoupath | ( | const struct vol * | vol,
|  | const char * | mpath )
| static

## ◆ pack_header()

int pack_header | ( | struct ea * | ea | ) |
| static

pack everything from struct ea into buffer at ea->ea_data

Parameters

  [in,out] | ea | handle to struct ea

Returns
  0 on success, -1 on error

Note
  adjust ea->ea_count in case an ea entry deletetion is detected

## ◆ remove_ea()

int remove_ea | ( | const struct vol * | vol,
|  | const char * | uname,
|  | const char * | attruname,
|  | int | oflag,
|  | int | fd )

remove a EA from a file

Parameters

  [in] | vol | current volume
  [in] | uname | filename
  [in] | attruname | EA name
  [in] | oflag | link and create flag
  [in] | fd | file descriptor

Returns
  AFP code: AFP_OK on success or appropriate AFP error code

Note
  Removes EA attruname from file uname.

## ◆ set_ea()

int set_ea | ( | const struct vol * | vol,
|  | const char * | uname,
|  | const char * | attruname,
|  | const char * | ibuf,
|  | size_t | attrsize,
|  | int | oflag,
|  | int | fd )

set a Solaris native EA

Parameters

  [in] | vol | current volume
  [in] | uname | filename
  [in] | attruname | EA name
  [in] | ibuf | buffer with EA content
  [in] | attrsize | length EA in ibuf
  [in] | oflag | link and create flag
  [in] | fd | file descriptor

Returns
  AFP code: AFP_OK on success or appropriate AFP error code

Note
  Copies names of all EAs of uname as consecutive C strings into rbuf. Increments *rbuflen accordingly.

## ◆ unpack_header()

int unpack_header | ( | struct ea * | ea | ) |
| static

unpack and verify header file data buffer at ea->ea_data into struct ea

Parameters

  [in,out] | ea | handle to struct ea

Returns
  0 on success, -1 on error

Note
  Verifies magic and version.

## ◆ write_ea()

int write_ea | ( | const struct ea * | ea,
|  | const char * | attruname,
|  | const char * | ibuf,
|  | size_t | attrsize )
| static

write an EA to disk

Parameters

  [in] | ea | struct ea handle
  [in] | attruname | EA name
  [in] | ibuf | buffer with EA content
  [in] | attrsize | size of EA

Returns
  0 on success, -1 on error

Note
  Creates/overwrites EA file.