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