b_a_t: (Default)
[personal profile] b_a_t
После 5 лет тотальной Perl лоботомии я понял, что забыл С практически начисто... Провозился 2 дня с вылизыванием 80 строчек кода :( Но до сих пор не уверен, что сделал все правильно. Так что, если кто присоветует, что тут еще можно улучщить - пишите :) Да, если по скорости какие-то оптимизации - тоже :)

Да, код под FreeBSD5 :)
#include <errno.h>
#include <sys/types.h>
#include <sys/extattr.h>
#include <stdlib.h>
#include <string.h>

#include <stdio.h>
#include <fcntl.h>

static struct {
    int space;
    const char *name;
    size_t len;
} 
extattr[] = {
	{ EXTATTR_NAMESPACE_SYSTEM, “system.”, sizeof(“system.”) },

        { EXTATTR_NAMESPACE_USER, “user.”, sizeof(“user.”) },
};

ssize_t my_listxattr (int type, const void *arg, char *list, size_t size) {
	ssize_t list_size, tot_size = 0;
	int i, t, len;
	char *buf;
	/* Iterate through extattr(2) namespaces */
	for(t = 0; t < sizeof(extattr)/sizeof(extattr[0]); t++) {
		switch(type) {
			case 0:
				list_size = extattr_list_file((const char*)arg, extattr[t].space, list, size);
				break;
			case 1:
				list_size = extattr_list_link((const char*)arg, extattr[t].space, list, size);
				break;
			case 2:
				list_size = extattr_list_fd(*(int*)arg, extattr[t].space, list, size);
				break;
			default:
				errno = ENOSYS;
				return -1;
		}
		/* Some error happened. Errno should be set by previous call */
		if(list_size < 0)
			return -1;
		/* No attributes */
		if(list_size == 0)
			continue;
		/* XXX: Call with an empty buffer may be used to calculate
		   necessary buffer size. Unfortunately, we can't say, how
		   many attributes were returned, so here is the potential
		   problem with the emulation.
		*/
		if(list == NULL) {
			/* For sure, at least one attribute exists. */
			tot_size += list_size + extattr[t].len - 1;
			continue;
		}
		/* Count necessary offset to fit namespace prefixes */
		len = 0;
		for(i = 0; i < list_size; i += list[i] + 1)
			len += extattr[t].len - 1;

		tot_size += list_size + len;
		/* Buffer is too small to fit the results */
		if(tot_size > size) {
			errno = ERANGE;
			return -1;
		}
		/* Shift the results back, so we can prepend prefixes */
		buf = memmove(list + len, list, list_size);

		for(i = 0; i < list_size; i += len + 1) {
			len = buf[i];
			strncpy(list, extattr[t].name, extattr[t].len);
			strncat(list, buf + i + 1, len);
			list += extattr[t].len + len;
		}
		size -= tot_size;
	}
	return tot_size;
}

ssize_t sys_listxattr (const char *path, char *list, size_t size)
{
	return my_listxattr(0, path, list, size);
}

ssize_t sys_llistxattr (const char *path, char *list, size_t size)
{
	return my_listxattr(1, path, list, size);
}

ssize_t sys_flistxattr (int filedes, char *list, size_t size)
{
	return my_listxattr(2, &filedes, list, size);
}

int main(int argc, char *argv[]) {
    char buf[1024];
    ssize_t size;
    int fd, i = 0;
    
    //size = sys_listxattr(argv[1], buf, sizeof(buf));
    
    fd = open(argv[1], O_RDONLY);
    
    size = sys_flistxattr(fd, buf, sizeof(buf));
    //size = sys_flistxattr(fd, NULL, 0);
    
    printf("Len: %d\n", size);
    for(i = 0; i < size; i += strlen(buf+i)+1) {
	printf("%s\n", buf+i);
    }
    return 0;
}


Кстати, не уверен, насколько верно передавать int a в функцию с void* ptr через &a, а потом приводить через *(int*)ptr. Но в теории, размера указателя может не хватить, чтобы поместить в него int(хотя до сих пор работало:)).

June 2025

S M T W T F S
123 4567
891011121314
15161718192021
22232425262728
2930     

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Feb. 25th, 2026 05:15 am
Powered by Dreamwidth Studios