-/**********************************************************************************
- * Solaris EA VFS funcs
- **********************************************************************************/
-
-/*
- * Function: sol_get_easize
- *
- * Purpose: get size of an EA on Solaris native EA
- *
- * Arguments:
- *
- * vol (r) current volume
- * rbuf (w) DSI reply buffer
- * rbuflen (rw) current length of data in reply buffer
- * uname (r) filename
- * oflag (r) link and create flag
- * attruname (r) name of attribute
- *
- * Returns: AFP code: AFP_OK on success or appropiate AFP error code
- *
- * Effects:
- *
- * Copies EA size into rbuf in network order. Increments *rbuflen +4.
- */
-#ifdef HAVE_SOLARIS_EAS
-int sol_get_easize(const struct vol * restrict vol,
- char * restrict rbuf,
- int * restrict rbuflen,
- const char * restrict uname,
- int oflag,
- cons char * restrict attruname)
-{
- int ret, attrdirfd;
- uint32_t attrsize;
- struct stat st;
-
- LOG(log_debug7, logtype_afpd, "sol_getextattr_size(%s): attribute: \"%s\"", uname, attruname);
-
- if ( -1 == (attrdirfd = attropen(uname, ".", O_RDONLY | oflag))) {
- if (errno == ELOOP) {
- /* its a symlink and client requested O_NOFOLLOW */
- LOG(log_debug, logtype_afpd, "sol_getextattr_size(%s): encountered symlink with kXAttrNoFollow", uname);
-
- memset(rbuf, 0, 4);
- *rbuflen += 4;
-
- return AFP_OK;
- }
- LOG(log_error, logtype_afpd, "sol_getextattr_size: attropen error: %s", strerror(errno));
- return AFPERR_MISC;
- }
-
- if ( -1 == (fstatat(attrdirfd, attruname, &st, 0))) {
- LOG(log_error, logtype_afpd, "sol_getextattr_size: fstatat error: %s", strerror(errno));
- ret = AFPERR_MISC;
- goto exit;
- }
- attrsize = (st.st_size > MAX_EA_SIZE) ? MAX_EA_SIZE : st.st_size;
-
- /* Start building reply packet */
-
- LOG(log_debug7, logtype_afpd, "sol_getextattr_size(%s): attribute: \"%s\", size: %u", uname, attruname, attrsize);
-
- /* length of attribute data */
- attrsize = htonl(attrsize);
- memcpy(rbuf, &attrsize, 4);
- *rbuflen += 4;
-
- ret = AFP_OK;
-
-exit:
- close(attrdirfd);
- return ret;
-}
-#endif /* HAVE_SOLARIS_EAS */
-
-/*
- * Function: sol_get_eacontent
- *
- * Purpose: copy Solaris native EA into rbuf
- *
- * Arguments:
- *
- * vol (r) current volume
- * rbuf (w) DSI reply buffer
- * rbuflen (rw) current length of data in reply buffer
- * uname (r) filename
- * oflag (r) link and create flag
- * attruname (r) name of attribute
- * maxreply (r) maximum EA size as of current specs/real-life
- *
- * Returns: AFP code: AFP_OK on success or appropiate AFP error code
- *
- * Effects:
- *
- * Copies EA into rbuf. Increments *rbuflen accordingly.
- */
-#ifdef HAVE_SOLARIS_EAS
-int sol_get_eacontent(const struct vol * restrict vol,
- char * restrict rbuf,
- int * restrict rbuflen,
- const char * restrict uname,
- int oflag,
- char * restrict attruname,
- int maxreply)
-{
- int ret, attrdirfd;
- size_t toread, okread = 0, len;
- char *datalength;
- struct stat st;
-
- if ( -1 == (attrdirfd = attropen(uname, attruname, O_RDONLY | oflag))) {
- if (errno == ELOOP) {
- /* its a symlink and client requested O_NOFOLLOW */
- LOG(log_debug, logtype_afpd, "sol_getextattr_content(%s): encountered symlink with kXAttrNoFollow", uname);
-
- memset(rbuf, 0, 4);
- *rbuflen += 4;
-
- return AFP_OK;
- }
- LOG(log_error, logtype_afpd, "sol_getextattr_content(%s): attropen error: %s", attruname, strerror(errno));
- return AFPERR_MISC;
- }
-
- if ( -1 == (fstat(attrdirfd, &st))) {
- LOG(log_error, logtype_afpd, "sol_getextattr_content(%s): fstatat error: %s", attruname,strerror(errno));
- ret = AFPERR_MISC;
- goto exit;
- }
-
- /* Start building reply packet */
-
- maxreply -= MAX_REPLY_EXTRA_BYTES;
- if (maxreply > MAX_EA_SIZE)
- maxreply = MAX_EA_SIZE;
-
- /* But never send more than the client requested */
- toread = (maxreply < st.st_size) ? maxreply : st.st_size;
-
- LOG(log_debug7, logtype_afpd, "sol_getextattr_content(%s): attribute: \"%s\", size: %u", uname, attruname, maxreply);
-
- /* remember where we must store length of attribute data in rbuf */
- datalength = rbuf;
- rbuf += 4;
- *rbuflen += 4;
-
- while (1) {
- len = read(attrdirfd, rbuf, toread);
- if (len == -1) {
- LOG(log_error, logtype_afpd, "sol_getextattr_content(%s): read error: %s", attruname, strerror(errno));
- ret = AFPERR_MISC;
- goto exit;
- }
- okread += len;
- rbuf += len;
- *rbuflen += len;
- if ((len == 0) || (okread == toread))
- break;
- }
-
- okread = htonl((uint32_t)okread);
- memcpy(datalength, &okread, 4);
-
- ret = AFP_OK;
-
-exit:
- close(attrdirfd);
- return ret;
-}
-#endif /* HAVE_SOLARIS_EAS */
-
-/*
- * Function: sol_list_eas
- *
- * Purpose: copy names of Solaris native EA into attrnamebuf
- *
- * Arguments:
- *
- * vol (r) current volume
- * attrnamebuf (w) store names a consecutive C strings here
- * buflen (rw) length of names in attrnamebuf
- * uname (r) filename
- * oflag (r) link and create flag
- *
- * Returns: AFP code: AFP_OK on success or appropiate AFP error code
- *
- * Effects:
- *
- * Copies names of all EAs of uname as consecutive C strings into rbuf.
- * Increments *rbuflen accordingly.
- */
-#ifdef HAVE_SOLARIS_EAS
-int sol_list_eas(const struct vol * restrict vol,
- char * restrict attrnamebuf,
- int * restrict buflen,
- const char * restrict uname,
- int oflag)
-{
- int ret, attrbuflen = *buflen, len, attrdirfd = 0;
- struct dirent *dp;
- DIR *dirp = NULL;
-
- /* Now list file attribute dir */
- if ( -1 == (attrdirfd = attropen( uname, ".", O_RDONLY | oflag))) {
- if (errno == ELOOP) {
- /* its a symlink and client requested O_NOFOLLOW */
- ret = AFPERR_BADTYPE;
- goto exit;
- }
- LOG(log_error, logtype_afpd, "sol_list_extattr(%s): error opening atttribute dir: %s", uname, strerror(errno));
- ret = AFPERR_MISC;
- goto exit;
- }
-
- if (NULL == (dirp = fdopendir(attrdirfd))) {
- LOG(log_error, logtype_afpd, "sol_list_extattr(%s): error opening atttribute dir: %s", uname, strerror(errno));
- ret = AFPERR_MISC;
- goto exit;
- }
-
- while ((dp = readdir(dirp))) {
- /* check if its "." or ".." */
- if ((strcmp(dp->d_name, ".") == 0) || (strcmp(dp->d_name, "..") == 0) ||
- (strcmp(dp->d_name, "SUNWattr_ro") == 0) || (strcmp(dp->d_name, "SUNWattr_rw") == 0))
- continue;
-
- len = strlen(dp->d_name);
-
- /* Convert name to CH_UTF8_MAC and directly store in in the reply buffer */
- if ( 0 >= ( len = convert_string(vol->v_volcharset, CH_UTF8_MAC, dp->d_name, len, attrnamebuf + attrbuflen, 255)) ) {
- ret = AFPERR_MISC;
- goto exit;
- }
- if (len == 255)
- /* convert_string didn't 0-terminate */
- attrnamebuf[attrbuflen + 255] = 0;
-
- LOG(log_debug7, logtype_afpd, "sol_list_extattr(%s): attribute: %s", uname, dp->d_name);
-
- attrbuflen += len + 1;
- if (attrbuflen > (ATTRNAMEBUFSIZ - 256)) {
- /* Next EA name could overflow, so bail out with error.
- FIXME: evantually malloc/memcpy/realloc whatever.
- Is it worth it ? */
- LOG(log_warning, logtype_afpd, "sol_list_extattr(%s): running out of buffer for EA names", uname);
- ret = AFPERR_MISC;
- goto exit;
- }
- }
-
- ret = AFP_OK;
-
-exit:
- if (dirp)
- closedir(dirp);
-
- if (attrdirfd > 0)
- close(attrdirfd);
-
- *buflen = attrbuflen;
- return ret;
-}
-#endif /* HAVE_SOLARIS_EAS */
-
-/*
- * Function: sol_set_ea
- *
- * Purpose: set a Solaris native EA
- *
- * Arguments:
- *
- * vol (r) current volume
- * uname (r) filename
- * attruname (r) EA name
- * ibuf (r) buffer with EA content
- * attrsize (r) length EA in ibuf
- * oflag (r) link and create flag
- *
- * Returns: AFP code: AFP_OK on success or appropiate AFP error code
- *
- * Effects:
- *
- * Copies names of all EAs of uname as consecutive C strings into rbuf.
- * Increments *rbuflen accordingly.
- */
-#ifdef HAVE_SOLARIS_EAS
-int sol_set_ea(const struct vol * restrict vol,
- const char * restrict u_name,
- const char * restrict attruname,
- const char * restrict ibuf,
- size_t attrsize,
- int oflag)
-{
- int attrdirfd;
-
- if ( -1 == (attrdirfd = attropen(u_name, attruname, oflag, 0666))) {
- if (errno == ELOOP) {
- /* its a symlink and client requested O_NOFOLLOW */
- LOG(log_debug, logtype_afpd, "afp_setextattr(%s): encountered symlink with kXAttrNoFollow", s_path->u_name);
- return AFP_OK;
- }
- LOG(log_error, logtype_afpd, "afp_setextattr(%s): attropen error: %s", s_path->u_name, strerror(errno));
- return AFPERR_MISC;
- }
-
- if ((write(attrdirfd, ibuf, attrsize)) != attrsize) {
- LOG(log_error, logtype_afpd, "afp_setextattr(%s): read error: %s", attruname, strerror(errno));
- return AFPERR_MISC;
- }
-
- return AFP_OK;
-}
-#endif /* HAVE_SOLARIS_EAS */
-
-/*
- * Function: sol_remove_ea
- *
- * Purpose: remove a Solaris native EA
- *
- * Arguments:
- *
- * vol (r) current volume
- * uname (r) filename
- * attruname (r) EA name
- * oflag (r) link and create flag
- *
- * Returns: AFP code: AFP_OK on success or appropiate AFP error code
- *
- * Effects:
- *
- * Removes EA attruname from file uname.
- */
-#ifdef HAVE_SOLARIS_EAS
-int sol_remove_ea(const struct vol * restrict vol,
- const char * restrict uname,
- const char * restrict attruname,
- int oflag)
-{
- int attrdirfd;
-
- if ( -1 == (attrdirfd = attropen(uname, ".", oflag))) {
- switch (errno) {
- case ELOOP:
- /* its a symlink and client requested O_NOFOLLOW */
- LOG(log_debug, logtype_afpd, "afp_remextattr(%s): encountered symlink with kXAttrNoFollow", s_path->u_name);
- return AFP_OK;
- case EACCES:
- LOG(log_debug, logtype_afpd, "afp_remextattr(%s): unlinkat error: %s", s_path->u_name, strerror(errno));
- return AFPERR_ACCESS;
- default:
- LOG(log_error, logtype_afpd, "afp_remextattr(%s): attropen error: %s", s_path->u_name, strerror(errno));
- return AFPERR_MISC;
- }
- }
-
- if ( -1 == (unlinkat(attrdirfd, attruname, 0)) ) {
- if (errno == EACCES) {
- LOG(log_debug, logtype_afpd, "afp_remextattr(%s): unlinkat error: %s", s_path->u_name, strerror(errno));
- return AFPERR_ACCESS;
- }
- LOG(log_error, logtype_afpd, "afp_remextattr(%s): unlinkat error: %s", s_path->u_name, strerror(errno));
- return AFPERR_MISC;
- }
-
-}
-#endif /* HAVE_SOLARIS_EAS */
-