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