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