117049c45SAxel Dörfler /*
206732c7cSAxel Dörfler * Copyright 2004-2015, Axel Dörfler, axeld@pinc-software.de.
317049c45SAxel Dörfler * Copyright 2002, Sebastian Nozzi.
417049c45SAxel Dörfler *
517049c45SAxel Dörfler * Distributed under the terms of the MIT license.
617049c45SAxel Dörfler */
717049c45SAxel Dörfler
817049c45SAxel Dörfler
917049c45SAxel Dörfler #include "addAttr.h"
1017049c45SAxel Dörfler
1117049c45SAxel Dörfler #include <TypeConstants.h>
1217049c45SAxel Dörfler #include <Mime.h>
1317049c45SAxel Dörfler
1417049c45SAxel Dörfler #include <fs_attr.h>
15*24bb6e13SAxel Dörfler #ifdef __HAIKU__
1678c9dabdSAxel Dörfler # include <parsedate.h>
17*24bb6e13SAxel Dörfler #endif
1817049c45SAxel Dörfler
19c8fa948bSStephan Aßmus #include <ctype.h>
20c8fa948bSStephan Aßmus #include <errno.h>
2117049c45SAxel Dörfler #include <stdlib.h>
2217049c45SAxel Dörfler #include <string.h>
233aeed660SJérôme Duval #include <strings.h>
24c8fa948bSStephan Aßmus #include <unistd.h>
2517049c45SAxel Dörfler
2617049c45SAxel Dörfler
2717049c45SAxel Dörfler template<class Type>
2817049c45SAxel Dörfler ssize_t
writeAttrValue(int fd,const char * name,type_code type,Type value)2917049c45SAxel Dörfler writeAttrValue(int fd, const char* name, type_code type, Type value)
3017049c45SAxel Dörfler {
3117049c45SAxel Dörfler ssize_t bytes = fs_write_attr(fd, name, type, 0, &value, sizeof(Type));
3217049c45SAxel Dörfler if (bytes < 0)
3317049c45SAxel Dörfler return errno;
3417049c45SAxel Dörfler
3517049c45SAxel Dörfler return bytes;
3617049c45SAxel Dörfler }
3717049c45SAxel Dörfler
3817049c45SAxel Dörfler
3906732c7cSAxel Dörfler /*! Writes an attribute to a node, taking the type into account and
4006732c7cSAxel Dörfler converting the value accordingly
4117049c45SAxel Dörfler
4206732c7cSAxel Dörfler On success it will return the amount of bytes written
4306732c7cSAxel Dörfler On failure it returns an error code (negative number)
4406732c7cSAxel Dörfler */
4517049c45SAxel Dörfler static ssize_t
writeAttr(int fd,type_code type,const char * name,const char * value,size_t length)46fcdd9a92SAxel Dörfler writeAttr(int fd, type_code type, const char* name, const char* value, size_t length)
4717049c45SAxel Dörfler {
4817049c45SAxel Dörfler uint64 uint64value = 0;
4917049c45SAxel Dörfler int64 int64value = 0;
5017049c45SAxel Dörfler double floatValue = 0.0;
5117049c45SAxel Dörfler
5217049c45SAxel Dörfler // parse number input at once
5317049c45SAxel Dörfler
5417049c45SAxel Dörfler switch (type) {
5517049c45SAxel Dörfler case B_BOOL_TYPE:
5617049c45SAxel Dörfler case B_INT8_TYPE:
5717049c45SAxel Dörfler case B_INT16_TYPE:
5817049c45SAxel Dörfler case B_INT32_TYPE:
5917049c45SAxel Dörfler case B_INT64_TYPE:
6017049c45SAxel Dörfler int64value = strtoll(value, NULL, 0);
6117049c45SAxel Dörfler break;
6217049c45SAxel Dörfler
6317049c45SAxel Dörfler case B_UINT8_TYPE:
6417049c45SAxel Dörfler case B_UINT16_TYPE:
6517049c45SAxel Dörfler case B_UINT32_TYPE:
6617049c45SAxel Dörfler case B_UINT64_TYPE:
6717049c45SAxel Dörfler uint64value = strtoull(value, NULL, 0);
6817049c45SAxel Dörfler break;
6917049c45SAxel Dörfler
7017049c45SAxel Dörfler case B_FLOAT_TYPE:
7117049c45SAxel Dörfler case B_DOUBLE_TYPE:
7217049c45SAxel Dörfler floatValue = strtod(value, NULL);
7317049c45SAxel Dörfler break;
7417049c45SAxel Dörfler }
7517049c45SAxel Dörfler
7617049c45SAxel Dörfler switch (type) {
7717049c45SAxel Dörfler case B_INT8_TYPE:
7817049c45SAxel Dörfler return writeAttrValue<int8>(fd, name, type, (int8)int64value);
7917049c45SAxel Dörfler case B_INT16_TYPE:
8017049c45SAxel Dörfler return writeAttrValue<int16>(fd, name, type, (int16)int64value);
8117049c45SAxel Dörfler case B_INT32_TYPE:
8217049c45SAxel Dörfler return writeAttrValue<int32>(fd, name, type, (int32)int64value);
8317049c45SAxel Dörfler case B_INT64_TYPE:
8417049c45SAxel Dörfler return writeAttrValue<int64>(fd, name, type, int64value);
8517049c45SAxel Dörfler
8617049c45SAxel Dörfler case B_UINT8_TYPE:
8717049c45SAxel Dörfler return writeAttrValue<uint8>(fd, name, type, (uint8)uint64value);
8817049c45SAxel Dörfler case B_UINT16_TYPE:
8917049c45SAxel Dörfler return writeAttrValue<uint16>(fd, name, type, (uint16)uint64value);
9017049c45SAxel Dörfler case B_UINT32_TYPE:
9117049c45SAxel Dörfler return writeAttrValue<uint32>(fd, name, type, (uint32)uint64value);
9217049c45SAxel Dörfler case B_UINT64_TYPE:
9317049c45SAxel Dörfler return writeAttrValue<uint64>(fd, name, type, uint64value);
9417049c45SAxel Dörfler
9517049c45SAxel Dörfler case B_FLOAT_TYPE:
9617049c45SAxel Dörfler return writeAttrValue<float>(fd, name, type, (float)floatValue);
9717049c45SAxel Dörfler case B_DOUBLE_TYPE:
9817049c45SAxel Dörfler return writeAttrValue<double>(fd, name, type, (double)floatValue);
9917049c45SAxel Dörfler
10017049c45SAxel Dörfler case B_BOOL_TYPE:
10117049c45SAxel Dörfler {
10217049c45SAxel Dörfler uint8 boolValue = 0;
10317049c45SAxel Dörfler
10417049c45SAxel Dörfler if (!strcasecmp(value, "true") || !strcasecmp(value, "t")
10517049c45SAxel Dörfler || !strcasecmp(value, "on") || !strcasecmp(value, "enabled")
10617049c45SAxel Dörfler || (isdigit(value[0]) && int64value == 1))
10717049c45SAxel Dörfler boolValue = 1;
10817049c45SAxel Dörfler else if (!strcasecmp(value, "false") || !strcasecmp(value, "f")
10917049c45SAxel Dörfler || !strcasecmp(value, "off") || !strcasecmp(value, "disabled")
11017049c45SAxel Dörfler || (isdigit(value[0]) && int64value == 0))
11117049c45SAxel Dörfler boolValue = 0;
11217049c45SAxel Dörfler else
11317049c45SAxel Dörfler return B_BAD_VALUE;
11417049c45SAxel Dörfler
11517049c45SAxel Dörfler return writeAttrValue<uint8>(fd, name, B_BOOL_TYPE, boolValue);
11617049c45SAxel Dörfler }
11717049c45SAxel Dörfler
118*24bb6e13SAxel Dörfler #ifdef __HAIKU__
11978c9dabdSAxel Dörfler case B_TIME_TYPE:
12078c9dabdSAxel Dörfler {
12178c9dabdSAxel Dörfler time_t timeValue = parsedate(value, time(NULL));
12278c9dabdSAxel Dörfler if (timeValue < 0)
12378c9dabdSAxel Dörfler return B_BAD_VALUE;
12478c9dabdSAxel Dörfler
12578c9dabdSAxel Dörfler return writeAttrValue<time_t>(fd, name, B_TIME_TYPE, timeValue);
12678c9dabdSAxel Dörfler }
127*24bb6e13SAxel Dörfler #endif
12878c9dabdSAxel Dörfler
12917049c45SAxel Dörfler case B_STRING_TYPE:
13017049c45SAxel Dörfler case B_MIME_STRING_TYPE:
13117049c45SAxel Dörfler default:
13217049c45SAxel Dörfler // For string, mime-strings and any other type we just write the value
133fcdd9a92SAxel Dörfler // Note that the trailing NULL is added. If a length was given, we write
134fcdd9a92SAxel Dörfler // the value directly, though.
135fcdd9a92SAxel Dörfler ssize_t bytes = fs_write_attr(fd, name, type, 0, value,
136fcdd9a92SAxel Dörfler length ? length : strlen(value) + 1);
13717049c45SAxel Dörfler if (bytes < 0)
13817049c45SAxel Dörfler return errno;
139fcdd9a92SAxel Dörfler
14017049c45SAxel Dörfler return bytes;
14117049c45SAxel Dörfler }
14217049c45SAxel Dörfler }
14317049c45SAxel Dörfler
14417049c45SAxel Dörfler
14506732c7cSAxel Dörfler /*! Adds an attribute to a file for the given type, name and value
14606732c7cSAxel Dörfler Converts the value accordingly in case of numeric or boolean types
14717049c45SAxel Dörfler
14806732c7cSAxel Dörfler On success, it returns B_OK, or else an appropriate error code.
14906732c7cSAxel Dörfler */
15017049c45SAxel Dörfler status_t
addAttr(const char * file,type_code type,const char * name,const char * value,size_t length,bool resolveLinks)151fcdd9a92SAxel Dörfler addAttr(const char* file, type_code type, const char* name,
1528b20dbc8SJérôme Duval const char* value, size_t length, bool resolveLinks)
15317049c45SAxel Dörfler {
1548b20dbc8SJérôme Duval int fd = open(file, O_RDONLY | (resolveLinks ? 0 : O_NOTRAVERSE));
15517049c45SAxel Dörfler if (fd < 0)
15617049c45SAxel Dörfler return errno;
15717049c45SAxel Dörfler
15817049c45SAxel Dörfler fs_remove_attr(fd, name);
159fcdd9a92SAxel Dörfler ssize_t bytes = writeAttr(fd, type, name, value, length);
16017049c45SAxel Dörfler
1618e619472SStephan Aßmus close(fd);
1628e619472SStephan Aßmus
16317049c45SAxel Dörfler return bytes >= 0 ? B_OK : bytes;
16417049c45SAxel Dörfler }
16517049c45SAxel Dörfler
166