xref: /haiku/src/bin/addattr/addAttr.cpp (revision ab4411e89a079bc0a40d901995f3418d998c51b3)
1 /*
2  * Copyright 2004-2006, Axel Dörfler, axeld@pinc-software.de.
3  * Copyright 2002, Sebastian Nozzi.
4  *
5  * Distributed under the terms of the MIT license.
6  */
7 
8 
9 #include "addAttr.h"
10 
11 #include <TypeConstants.h>
12 #include <Mime.h>
13 
14 #include <fs_attr.h>
15 
16 #include <ctype.h>
17 #include <errno.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <strings.h>
21 #include <unistd.h>
22 
23 
24 template<class Type>
25 ssize_t
26 writeAttrValue(int fd, const char *name, type_code type, Type value)
27 {
28 	ssize_t bytes = fs_write_attr(fd, name, type, 0, &value, sizeof(Type));
29 	if (bytes < 0)
30 		return errno;
31 
32 	return bytes;
33 }
34 
35 
36 /**	Writes an attribute to a node, taking the type into account and
37  *	converting the value accordingly
38  *
39  *	On success it will return the amount of bytes written
40  *	On failure it returns an error code (negative number)
41  */
42 
43 static ssize_t
44 writeAttr(int fd, type_code type, const char *name, const char *value, size_t length)
45 {
46 	uint64 uint64value = 0;
47 	int64 int64value = 0;
48 	double floatValue = 0.0;
49 
50 	// parse number input at once
51 
52 	switch (type) {
53 		case B_BOOL_TYPE:
54 		case B_INT8_TYPE:
55 		case B_INT16_TYPE:
56 		case B_INT32_TYPE:
57 		case B_INT64_TYPE:
58 			int64value = strtoll(value, NULL, 0);
59 			break;
60 
61 		case B_UINT8_TYPE:
62 		case B_UINT16_TYPE:
63 		case B_UINT32_TYPE:
64 		case B_UINT64_TYPE:
65 			uint64value = strtoull(value, NULL, 0);
66 			break;
67 
68 		case B_FLOAT_TYPE:
69 		case B_DOUBLE_TYPE:
70 			floatValue = strtod(value, NULL);
71 			break;
72 	}
73 
74 	switch (type) {
75 		case B_INT8_TYPE:
76 			return writeAttrValue<int8>(fd, name, type, (int8)int64value);
77 		case B_INT16_TYPE:
78 			return writeAttrValue<int16>(fd, name, type, (int16)int64value);
79 		case B_INT32_TYPE:
80 			return writeAttrValue<int32>(fd, name, type, (int32)int64value);
81 		case B_INT64_TYPE:
82 			return writeAttrValue<int64>(fd, name, type, int64value);
83 
84 		case B_UINT8_TYPE:
85 			return writeAttrValue<uint8>(fd, name, type, (uint8)uint64value);
86 		case B_UINT16_TYPE:
87 			return writeAttrValue<uint16>(fd, name, type, (uint16)uint64value);
88 		case B_UINT32_TYPE:
89 			return writeAttrValue<uint32>(fd, name, type, (uint32)uint64value);
90 		case B_UINT64_TYPE:
91 			return writeAttrValue<uint64>(fd, name, type, uint64value);
92 
93 		case B_FLOAT_TYPE:
94 			return writeAttrValue<float>(fd, name, type, (float)floatValue);
95 		case B_DOUBLE_TYPE:
96 			return writeAttrValue<double>(fd, name, type, (double)floatValue);
97 
98 		case B_BOOL_TYPE:
99 		{
100 			uint8 boolValue = 0;
101 
102 			if (!strcasecmp(value, "true") || !strcasecmp(value, "t")
103 				|| !strcasecmp(value, "on") || !strcasecmp(value, "enabled")
104 				|| (isdigit(value[0]) && int64value == 1))
105 				boolValue = 1;
106 			else if (!strcasecmp(value, "false") || !strcasecmp(value, "f")
107 				|| !strcasecmp(value, "off") || !strcasecmp(value, "disabled")
108 				|| (isdigit(value[0]) && int64value == 0))
109 				boolValue = 0;
110 			else
111 				return B_BAD_VALUE;
112 
113 			return writeAttrValue<uint8>(fd, name, B_BOOL_TYPE, boolValue);
114 		}
115 
116 		case B_STRING_TYPE:
117 		case B_MIME_STRING_TYPE:
118 		default:
119 			// For string, mime-strings and any other type we just write the value
120 			// Note that the trailing NULL is added. If a length was given, we write
121 			// the value directly, though.
122 			ssize_t bytes = fs_write_attr(fd, name, type, 0, value,
123 				length ? length : strlen(value) + 1);
124 			if (bytes < 0)
125 				return errno;
126 
127 			return bytes;
128 	}
129 }
130 
131 
132 /**	Adds an attribute to a file for the given type, name and value
133  *	Converts the value accordingly in case of numeric or boolean types
134  *
135  *	On success, it returns B_OK, or else an appropriate error code.
136  */
137 
138 status_t
139 addAttr(const char *file, type_code type, const char *name,
140 	const char *value, size_t length, bool resolveLinks)
141 {
142 	int fd = open(file, O_RDONLY | (resolveLinks ? 0 : O_NOTRAVERSE));
143 	if (fd < 0)
144 		return errno;
145 
146 	fs_remove_attr(fd, name);
147 	ssize_t bytes = writeAttr(fd, type, name, value, length);
148 
149 	close(fd);
150 
151 	return bytes >= 0 ? B_OK : bytes;
152 }
153 
154