netatalk  4.4.0
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]unamefilename for which we have to create a header
[in,out]eaea 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]eastruct ea handle
[in]eanameEA 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]eapointer to struct ea
[in]attrunamename of EA
[in]attrsizesize of ea
[in]bitmapbitmap 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]eapointer 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]volcurrent volume
[in]sfdsource file descriptor
[in]srcsource path
[in]dstdestination 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]eapointer to struct ea
[in]attrunameEA 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)
inlinestatic

Build mode for EA header from file mode

◆ ea_mode()

mode_t ea_mode ( mode_t mode)
inlinestatic

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]volcurrent volume
[in]unamefilename for which we have to open a header
[in]eaflagsflag 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]eapointer 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]volcurrent volume
[in]dirfdopenat like file descriptor
[in]unamefilename for which we have to open a header
[in]eaflagsflag 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]eapointer 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]eaea handle
[in]eanamename of EA or NULL
[in]macnameif != 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]volcurrent volume
[out]rbufDSI reply buffer
[in,out]rbuflencurrent length of data in reply buffer
[in]unamefilename
[in]oflaglink and create flag
[in]attrunamename of attribute
[in]maxreplymaximum EA size as of current specs/real-life
[in]fdfile 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]volcurrent volume
[out]rbufDSI reply buffer
[in,out]rbuflencurrent length of data in reply buffer
[in]unamefilename
[in]oflaglink and create flag
[in]attrunamename of attribute
[in]fdfile 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]volcurrent volume
[out]attrnamebufstore names a consecutive C strings here
[in,out]buflenlength of names in attrnamebuf
[in]unamefilename
[in]oflaglink and create flag
[in]fdfile 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]eahandle 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]volcurrent volume
[in]unamefilename
[in]attrunameEA name
[in]oflaglink and create flag
[in]fdfile 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]volcurrent volume
[in]unamefilename
[in]attrunameEA name
[in]ibufbuffer with EA content
[in]attrsizelength EA in ibuf
[in]oflaglink and create flag
[in]fdfile 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]eahandle 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]eastruct ea handle
[in]attrunameEA name
[in]ibufbuffer with EA content
[in]attrsizesize of EA
Returns
0 on success, -1 on error
Note
Creates/overwrites EA file.