const char *end;
char *file;
int fd;
- ssize_t count;
+ ssize_t rc, count = 0;
if (!out_len)
goto err_out;
if (file == NULL)
goto err_out;
+#ifdef _WIN32
+ fd = open(file, O_RDONLY | O_BINARY);
+#else
fd = open(file, O_RDONLY);
+#endif
if (fd < 0)
goto err_free_out;
- count = read(fd, out, out_len);
- if (count == -1)
- goto err_free_close_out;
+ if (out) {
+ while (1) {
+ rc = read(fd, out, out_len - count);
+ if (rc == 0)
+ break;
+ if (rc == -1)
+ goto err_free_close_out;
+
+ count += rc;
+ out += rc;
+ }
+ } else {
+ count = lseek(fd, 0, SEEK_END);
+ if (count == -1)
+ goto err_free_close_out;
+ if (count >= out_len)
+ count = out_len;
+ }
*filled = count;
close(fd);
if (end - beg > out_len)
return NULL;
- memcpy(out, beg, end - beg);
+ if (out)
+ memcpy(out, beg, end - beg);
*filled = end - beg;
/* Catch up quote */
i = 0;
if (!lval) {
num = 0;
- out[i] = 0x00;
+ if (out)
+ out[i] = 0x00;
i = 1;
} else {
val = (unsigned int)lval;
for (; val && out_len; out_len--, i++, val >>= 8)
- out[i] = val & 0xff;
+ if (out)
+ out[i] = val & 0xff;
if (val)
return NULL;
}
const char *fmt;
fmt = (num & 1 ? "%1hhx" : "%2hhx");
- sscanf(beg, fmt, &out[i]);
+ if (out)
+ sscanf(beg, fmt, &out[i]);
if (num & 1) {
num++;
beg--;
* This function tries to find formats, e.g.:
* %o - offset of the block
*
- * In case of successfull parsing it fills the format param
+ * In case of successful parsing it fills the format param
* with proper offset and the size of the expected value, which
* should be pasted into buffer using the format 'func' callback.
*
if (f->desc->len > out_len)
return NULL;
- memset(out, '\0', f->desc->len);
+ if (out)
+ memset(out, '\0', f->desc->len);
*filled = f->desc->len;
return in + len;
* numbers and pattern formats.
* @in - string input
* @in_len - size of the input string
- * @out - output buffer where parsed result will be put
+ * @out - output buffer where parsed result will be put, may be NULL
+ * in which case this function just calculates the required
+ * length of the buffer
* @out_len - lengths of the output buffer
* @fmt_desc - array of pattern format descriptors [input]
* @fmt - array of pattern formats [output]
* @fmt_sz - pointer where the size of pattern formats array stored [input],
- * after successfull parsing this pointer will contain the number
+ * after successful parsing this pointer will contain the number
* of parsed formats if any [output].
*
* strings:
* NOTE: there is no way to escape quote, so "123\"abc" does not work.
*
* numbers:
- * hexidecimal - sequence of hex bytes starting from 0x or 0X prefix,
+ * hexadecimal - sequence of hex bytes starting from 0x or 0X prefix,
* e.g. 0xff12ceff1100ff
* decimal - decimal number in range [INT_MIN, INT_MAX]
*
*
* Returns number of bytes filled or err < 0 in case of failure.
*/
-int parse_and_fill_pattern(const char *in, unsigned int in_len,
- char *out, unsigned int out_len,
- const struct pattern_fmt_desc *fmt_desc,
- struct pattern_fmt *fmt,
- unsigned int *fmt_sz_out)
+static int parse_and_fill_pattern(const char *in, unsigned int in_len,
+ char *out, unsigned int out_len,
+ const struct pattern_fmt_desc *fmt_desc,
+ struct pattern_fmt *fmt,
+ unsigned int *fmt_sz_out)
{
const char *beg, *end, *out_beg = out;
unsigned int total = 0, fmt_rem = 0;
- if (!in || !in_len || !out || !out_len)
+ if (!in || !in_len || !out_len)
return -EINVAL;
if (fmt_sz_out)
fmt_rem = *fmt_sz_out;
assert(filled);
assert(filled <= out_len);
out_len -= filled;
- out += filled;
total += filled;
+ if (out)
+ out += filled;
} while (in_len);
return total;
}
+/**
+ * parse_and_fill_pattern_alloc() - Parses combined input, which consists of
+ * strings, numbers and pattern formats and
+ * allocates a buffer for the result.
+ *
+ * @in - string input
+ * @in_len - size of the input string
+ * @out - pointer to the output buffer pointer, this will be set to the newly
+ * allocated pattern buffer which must be freed by the caller
+ * @fmt_desc - array of pattern format descriptors [input]
+ * @fmt - array of pattern formats [output]
+ * @fmt_sz - pointer where the size of pattern formats array stored [input],
+ * after successful parsing this pointer will contain the number
+ * of parsed formats if any [output].
+ *
+ * See documentation on parse_and_fill_pattern() above for a description
+ * of the functionality.
+ *
+ * Returns number of bytes filled or err < 0 in case of failure.
+ */
+int parse_and_fill_pattern_alloc(const char *in, unsigned int in_len,
+ char **out, const struct pattern_fmt_desc *fmt_desc,
+ struct pattern_fmt *fmt, unsigned int *fmt_sz_out)
+{
+ int count;
+
+ count = parse_and_fill_pattern(in, in_len, NULL, MAX_PATTERN_SIZE,
+ fmt_desc, fmt, fmt_sz_out);
+ if (count < 0)
+ return count;
+
+ *out = malloc(count);
+ count = parse_and_fill_pattern(in, in_len, *out, count, fmt_desc,
+ fmt, fmt_sz_out);
+ if (count < 0) {
+ free(*out);
+ *out = NULL;
+ }
+
+ return count;
+}
+
/**
* dup_pattern() - Duplicates part of the pattern all over the buffer.
*