+int list_extattr(AFPObj *obj, char *attrnamebuf, int *buflen, char *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, "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, "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);
+
+ if ( 0 >= ( len = convert_string(obj->options.unixcharset, 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, "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, "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;
+}