283 action =
strsep(&data,
",");
284 if (stat(data, &s)) {
292 snprintf(buf, len,
"%u", (
unsigned int) s.st_size);
295 snprintf(buf, len,
"%d", S_ISREG(s.st_mode) ? 1 : 0);
298 snprintf(buf, len,
"%d", S_ISDIR(s.st_mode) ? 1 : 0);
301 snprintf(buf, len,
"%d", (
int) s.st_mtime);
304 snprintf(buf, len,
"%d", (
int) s.st_mtime);
307 snprintf(buf, len,
"%d", (
int) s.st_ctime);
310 snprintf(buf, len,
"%o", (
unsigned int) s.st_mode);
331 if (!(ff = fopen(filename,
"r"))) {
336 while (fgets(fbuf,
sizeof(fbuf), ff)) {
337 char *next = fbuf, *first_cr =
NULL, *first_nl =
NULL;
343 first_cr = strchr(next,
'\r');
346 first_nl = strchr(next,
'\n');
350 if (!first_cr && !first_nl) {
355 if ((first_cr && !first_nl) || (first_cr && first_cr < first_nl)) {
356 if (first_nl && first_nl == first_cr + 1) {
358 }
else if (first_cr && first_cr == &fbuf[
sizeof(fbuf) - 2]) {
360 fseek(ff, -1, SEEK_CUR);
373 if (newline_format ==
FF_DOS) {
374 if (first_nl && first_cr && first_nl == first_cr + 1) {
377 }
else if (first_cr == &fbuf[
sizeof(fbuf) - 2]) {
379 fseek(ff, -1, SEEK_CUR);
382 }
else if (newline_format ==
FF_MAC) {
387 }
else if (newline_format ==
FF_UNIX) {
411 if (tolower(
args.format[0]) ==
'd') {
413 }
else if (tolower(
args.format[0]) ==
'm') {
415 }
else if (tolower(
args.format[0]) ==
'u') {
425 #define LINE_COUNTER(cptr, term, counter) \ 426 if (*cptr == '\n' && term == FF_UNIX) { \ 428 } else if (*cptr == '\n' && term == FF_DOS && dos_state == 0) { \ 430 } else if (*cptr == '\r' && term == FF_DOS && dos_state == 1) { \ 433 } else if (*cptr == '\r' && term == FF_MAC) { \ 435 } else if (term == FF_DOS) { \ 443 char *first_cr, *first_nl;
446 if (!(ff = fopen(filename,
"r"))) {
451 while (fgets(fbuf,
sizeof(fbuf), ff)) {
452 first_cr = strchr(fbuf,
'\r');
453 first_nl = strchr(fbuf,
'\n');
455 if (!first_cr && !first_nl) {
459 if ((first_cr && !first_nl) || (first_cr && first_cr < first_nl)) {
461 if (first_nl && first_nl == first_cr + 1) {
463 }
else if (first_cr && first_cr == &fbuf[
sizeof(fbuf) - 2]) {
465 fseek(ff, -1, SEEK_CUR);
476 return newline_format;
493 int64_t offset_offset = -1, length_offset = -1;
506 sscanf(
args.offset,
"%" SCNd64, &offset);
509 sscanf(
args.length,
"%" SCNd64, &length);
512 if (
args.argc < 4 || !strchr(
args.options,
'l')) {
516 if (!(ff = fopen(
args.filename,
"r"))) {
521 if (fseeko(ff, 0, SEEK_END) < 0) {
526 flength = ftello(ff);
529 fseeko(ff, offset, SEEK_END);
530 if ((offset = ftello(ff)) < 0) {
537 fseeko(ff, length, SEEK_END);
538 if ((length = ftello(ff)) - offset < 0) {
544 fseeko(ff, 0, SEEK_END);
550 fseeko(ff, offset, SEEK_SET);
551 for (off_i = ftello(ff); off_i < flength && off_i < offset + length; off_i +=
sizeof(fbuf)) {
553 size_t toappend =
sizeof(fbuf);
555 if (fread(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf) && !feof(ff)) {
561 if (off_i + toappend > offset + length) {
562 toappend =
MIN(offset + length - off_i, flength - off_i);
572 if (
args.argc == 5) {
573 if (tolower(
args.fileformat[0]) ==
'd') {
575 }
else if (tolower(
args.fileformat[0]) ==
'm') {
577 }
else if (tolower(
args.fileformat[0]) ==
'u') {
589 if (offset < 0 && length <= offset) {
592 }
else if (offset == 0) {
596 if (!(ff = fopen(
args.filename,
"r"))) {
601 if (fseek(ff, 0, SEEK_END)) {
607 flength = ftello(ff);
610 length_offset = flength;
614 if (offset < 0 || length < 0) {
618 for (i = (flength /
sizeof(fbuf)) *
sizeof(fbuf); i >= 0; i -=
sizeof(fbuf)) {
621 if (fseeko(ff, i, SEEK_SET)) {
624 end = fread(fbuf, 1,
sizeof(fbuf), ff);
625 for (pos = (end <
sizeof(fbuf) ? fbuf + end - 1 : fbuf +
sizeof(fbuf) - 1); pos >= fbuf; pos--) {
628 if (length < 0 && count * -1 == length) {
629 length_offset = i + (pos - fbuf);
630 }
else if (offset < 0 && count * -1 == (offset - 1)) {
633 offset_offset = i + (pos - fbuf) + 2;
635 offset_offset = i + (pos - fbuf) + 1;
640 if ((offset < 0 && offset_offset >= 0) || (offset >= 0 && length_offset >= 0)) {
645 if (offset < 0 && offset_offset < 0 && offset == count * -1) {
653 fseek(ff, 0, SEEK_SET);
654 for (i = 0; i < flength; i +=
sizeof(fbuf)) {
656 if (i +
sizeof(fbuf) <= flength) {
658 memset(fbuf, 0,
sizeof(fbuf));
660 if (fread(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf) && !feof(ff)) {
665 for (pos = fbuf; pos < fbuf +
sizeof(fbuf); pos++) {
668 if (count == offset) {
669 offset_offset = i + (pos - fbuf) + 1;
673 if (offset_offset >= 0) {
679 if (offset_offset < 0) {
686 if (fseeko(ff, offset_offset, SEEK_SET)) {
694 if (length_offset >= 0) {
695 ast_debug(3,
"offset=%" PRId64
", length=%" PRId64
", offset_offset=%" PRId64
", length_offset=%" PRId64
"\n", offset, length, offset_offset, length_offset);
696 for (i = offset_offset; i < length_offset; i +=
sizeof(fbuf)) {
697 if (fread(fbuf, 1, i +
sizeof(fbuf) > flength ? flength - i :
sizeof(fbuf), ff) < (i +
sizeof(fbuf) > flength ? flength - i :
sizeof(fbuf))) {
700 ast_debug(3,
"Appending first %" PRId64
" bytes of fbuf=%s\n", (int64_t)(i +
sizeof(fbuf) > length_offset ? length_offset - i :
sizeof(fbuf)), fbuf);
701 ast_str_append_substr(buf, len, fbuf, i +
sizeof(fbuf) > length_offset ? length_offset - i :
sizeof(fbuf));
703 }
else if (length == 0) {
707 int64_t current_length = 0;
709 ast_debug(3,
"offset=%" PRId64
", length=%" PRId64
", offset_offset=%" PRId64
", length_offset=%" PRId64
"\n", offset, length, offset_offset, length_offset);
710 for (i = offset_offset; i < flength; i +=
sizeof(fbuf)) {
713 if ((bytes_read = fread(fbuf, 1,
sizeof(fbuf), ff)) <
sizeof(fbuf) && !feof(ff)) {
718 for (pos = fbuf; pos < fbuf + bytes_read; pos++) {
721 if (current_length == length) {
722 length_offset = i + (pos - fbuf) + 1;
726 ast_debug(3,
"length_offset=%" PRId64
", length_offset - i=%" PRId64
"\n", length_offset, length_offset - i);
727 ast_str_append_substr(buf, len, fbuf, (length_offset >= 0) ? length_offset - i : (flength > i +
sizeof(fbuf)) ?
sizeof(fbuf) : flength - i);
729 if (length_offset >= 0) {
742 const char *term[] = {
"",
"\n",
"\r\n",
"\r" };
756 off_t flength, vlength;
763 sscanf(
args.offset,
"%" SCNd64, &offset);
766 sscanf(
args.length,
"%" SCNd64, &length);
769 vlength = strlen(value);
771 if (
args.argc < 4 || !strchr(
args.options,
'l')) {
774 if (
args.argc > 3 && strchr(
args.options,
'a')) {
776 if (!(ff = fopen(
args.filename,
"a"))) {
780 if (fwrite(value, 1, vlength, ff) < vlength) {
785 }
else if (offset == 0 && length ==
LLONG_MAX) {
786 if (!(ff = fopen(
args.filename,
"w"))) {
790 if (fwrite(value, 1, vlength, ff) < vlength) {
797 if (!(ff = fopen(
args.filename,
"r+"))) {
801 fseeko(ff, 0, SEEK_END);
802 flength = ftello(ff);
805 if (fseeko(ff, offset, SEEK_END)) {
810 if ((offset = ftello(ff)) < 0) {
818 length = flength - offset + length;
820 ast_log(
LOG_ERROR,
"Length '%s' exceeds the file length. No data will be written.\n",
args.length);
826 fseeko(ff, offset, SEEK_SET);
828 ast_debug(3,
"offset=%s/%" PRId64
", length=%s/%" PRId64
", vlength=%" PRId64
", flength=%" PRId64
"\n",
829 S_OR(
args.offset,
"(null)"), offset,
S_OR(
args.length,
"(null)"), length, vlength, flength);
831 if (length == vlength) {
833 if (fwrite(value, 1, vlength, ff) < vlength) {
839 if (fwrite(value, 1, vlength, ff) < vlength) {
843 if (truncate(
args.filename, offset + vlength)) {
846 }
else if (length > vlength) {
850 if (fwrite(value, 1, vlength, ff) < vlength) {
853 fseeko(ff, length - vlength, SEEK_CUR);
854 while ((cur = ftello(ff)) < flength) {
855 if (fread(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf) && !feof(ff)) {
858 fseeko(ff, cur + vlength - length, SEEK_SET);
859 if (fwrite(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf)) {
863 if (fseeko(ff, cur +
sizeof(fbuf), SEEK_SET) < 0) {
869 if (truncate(
args.filename, flength - (length - vlength))) {
875 off_t lastwritten = flength + vlength - length;
878 fseeko(ff, flength -
sizeof(fbuf), SEEK_SET);
879 while (offset < ftello(ff)) {
880 if (fread(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf)) {
888 fseeko(ff, vlength - length -
sizeof(fbuf), SEEK_CUR);
891 lastwritten = ftello(ff);
893 if (fwrite(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf)) {
899 if (lastwritten < offset +
sizeof(fbuf)) {
908 fseeko(ff, 2 *
sizeof(fbuf) + vlength - length, SEEK_CUR);
912 if (fseeko(ff, offset + length, SEEK_SET)) {
913 ast_log(
LOG_WARNING,
"Unable to seek to %" PRId64
" + %" PRId64
" != %" PRId64
"?)\n", offset, length, ftello(ff));
917 ast_debug(1,
"Reading at %" PRId64
"\n", ftello(ff));
918 if (fread(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf) && !feof(ff)) {
921 fseek(ff, offset, SEEK_SET);
923 if (fwrite(value, 1, vlength, ff) < vlength) {
926 off_t curpos = ftello(ff);
927 foplen = lastwritten - curpos;
928 if (fwrite(fbuf, 1, foplen, ff) < foplen) {
938 if (
args.argc == 5) {
939 if (tolower(
args.format[0]) ==
'u') {
941 }
else if (tolower(
args.format[0]) ==
'm') {
943 }
else if (tolower(
args.format[0]) ==
'd') {
952 if (strchr(
args.options,
'a')) {
954 if (!(ff = fopen(
args.filename,
"a"))) {
958 if (fwrite(value, 1, vlength, ff) < vlength) {
964 }
else if (offset == 0 && length ==
LLONG_MAX) {
967 if (!(ff = fopen(
args.filename,
"w"))) {
971 if (fwrite(value, 1, vlength, ff) < vlength) {
976 if ((truncsize = ftello(ff)) < 0) {
980 if (truncsize >= 0 && truncate(
args.filename, truncsize)) {
985 int64_t offset_offset = (offset == 0 ? 0 : -1), length_offset = -1, flength, i, current_length = 0;
986 char dos_state = 0, fbuf[4096];
988 if (offset < 0 && length < offset) {
990 ast_log(
LOG_ERROR,
"Length cannot specify a position prior to the offset\n");
994 if (!(ff = fopen(
args.filename,
"r+"))) {
999 if (fseek(ff, 0, SEEK_END)) {
1004 if ((flength = ftello(ff)) < 0) {
1011 if (offset < 0 || length < 0) {
1013 for (i = (flength /
sizeof(fbuf)) *
sizeof(fbuf); i >= 0; i -=
sizeof(fbuf)) {
1015 if (fseeko(ff, i, SEEK_SET)) {
1018 if (i +
sizeof(fbuf) >= flength) {
1019 memset(fbuf, 0,
sizeof(fbuf));
1021 if (fread(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf) && !feof(ff)) {
1026 for (pos = fbuf +
sizeof(fbuf) - 1; pos >= fbuf; pos--) {
1029 if (length < 0 && count * -1 == length) {
1030 length_offset = i + (pos - fbuf);
1031 }
else if (offset < 0 && count * -1 == (offset - 1)) {
1033 if (newline_format ==
FF_DOS) {
1034 offset_offset = i + (pos - fbuf) + 2;
1036 offset_offset = i + (pos - fbuf) + 1;
1041 if ((offset < 0 && offset_offset >= 0) || (offset >= 0 && length_offset >= 0)) {
1046 if (offset < 0 && offset_offset < 0 && offset == count * -1) {
1054 fseek(ff, 0, SEEK_SET);
1055 for (i = 0; i < flength; i +=
sizeof(fbuf)) {
1057 if (i +
sizeof(fbuf) >= flength) {
1058 memset(fbuf, 0,
sizeof(fbuf));
1060 if (fread(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf) && !feof(ff)) {
1065 for (pos = fbuf; pos < fbuf +
sizeof(fbuf); pos++) {
1068 if (count == offset) {
1069 offset_offset = i + (pos - fbuf) + 1;
1073 if (offset_offset >= 0) {
1079 if (offset_offset < 0) {
1086 length_offset = offset_offset;
1088 length_offset = flength;
1092 if (length_offset < 0) {
1093 fseeko(ff, offset_offset, SEEK_SET);
1094 for (i = offset_offset; i < flength; i +=
sizeof(fbuf)) {
1096 if (i +
sizeof(fbuf) >= flength) {
1097 memset(fbuf, 0,
sizeof(fbuf));
1099 if (fread(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf) && !feof(ff)) {
1104 for (pos = fbuf; pos < fbuf +
sizeof(fbuf); pos++) {
1107 if (current_length == length) {
1108 length_offset = i + (pos - fbuf) + 1;
1112 if (length_offset >= 0) {
1116 if (length_offset < 0) {
1118 ast_debug(3,
"Exceeds length of file? length=%" PRId64
", count=%" PRId64
", flength=%" PRId64
"\n", length, current_length, flength);
1119 length_offset = flength;
1124 if (length_offset - offset_offset == vlength + (strchr(
args.options,
'd') ? 0 : strlen(
format2term(newline_format)))) {
1126 fseeko(ff, offset_offset, SEEK_SET);
1127 if (fwrite(value, 1, vlength, ff) < vlength) {
1133 }
else if (length_offset - offset_offset > vlength + (strchr(
args.options,
'd') ? 0 : strlen(
format2term(newline_format)))) {
1136 int64_t length_length = length_offset - offset_offset;
1137 size_t vlen = vlength + (strchr(
args.options,
'd') ? 0 : strlen(
format2term(newline_format)));
1139 ast_debug(3,
"offset=%s/%" PRId64
", length=%s/%" PRId64
" (%" PRId64
"), vlength=%" PRId64
", flength=%" PRId64
"\n",
1140 args.offset, offset_offset,
args.length, length_offset, length_length, vlength, flength);
1142 fseeko(ff, offset_offset, SEEK_SET);
1143 if (fwrite(value, 1, vlength, ff) < vlength) {
1147 }
else if (!strchr(
args.options,
'd') && fwrite(
format2term(newline_format), 1, vlen - vlength, ff) < vlen - vlength) {
1152 while ((cur = ftello(ff)) < flength) {
1158 fseeko(ff, length_length - vlen, SEEK_CUR);
1159 if (fread(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf) && !feof(ff)) {
1165 fseeko(ff, cur, SEEK_SET);
1166 if (fwrite(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf)) {
1173 if (truncate(
args.filename, flength - (length_length - vlen))) {
1178 size_t vlen = vlength + (strchr(
args.options,
'd') ? 0 : strlen(
format2term(newline_format)));
1179 int64_t origlen = length_offset - offset_offset;
1180 off_t lastwritten = flength + vlen - origlen;
1182 ast_debug(3,
"offset=%s/%" PRId64
", length=%s/%" PRId64
", vlength=%" PRId64
", flength=%" PRId64
"\n",
1183 args.offset, offset_offset,
args.length, length_offset, vlength, flength);
1185 fseeko(ff, flength -
sizeof(fbuf), SEEK_SET);
1186 while (offset_offset +
sizeof(fbuf) < ftello(ff)) {
1187 if (fread(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf)) {
1192 fseeko(ff,
sizeof(fbuf) - vlen - origlen, SEEK_CUR);
1193 if (fwrite(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf)) {
1198 if ((lastwritten = ftello(ff) -
sizeof(fbuf)) < offset_offset +
sizeof(fbuf)) {
1201 fseeko(ff, 2 *
sizeof(fbuf) + vlen - origlen, SEEK_CUR);
1203 fseek(ff, length_offset, SEEK_SET);
1204 if (fread(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf) && !feof(ff)) {
1209 fseek(ff, offset_offset, SEEK_SET);
1210 if (fwrite(value, 1, vlength, ff) < vlength) {
1219 off_t curpos = ftello(ff);
1220 foplen = lastwritten - curpos;
1221 if (fwrite(fbuf, 1, foplen, ff) < foplen) {
1252 .
name =
"FILE_COUNT_LINE",
1258 .
name =
"FILE_FORMAT",
Main Channel structure associated with a channel.
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Asterisk main include file. File version handling, generic pbx functions.
static struct ast_custom_function file_function
static int file_count_line(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
static int file_read(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
const char * format2term(enum file_format f)
static struct ast_custom_function file_count_line_function
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
static enum file_format file2format(const char *filename)
static struct ast_custom_function file_format_function
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
#define ast_strlen_zero(foo)
static int unload_module(void)
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
#define ast_custom_function_register_escalating(acf, escalation)
Register a custom function which requires escalated privileges.
#define ast_debug(level,...)
Log a DEBUG message.
General Asterisk PBX channel definitions.
static int64_t count_lines(const char *filename, enum file_format newline_format)
char * ast_str_append_substr(struct ast_str **buf, ssize_t maxlen, const char *src, size_t maxsrc)
Append a non-NULL terminated substring to the end of a dynamic string.
Data structure associated with a custom dialplan function.
static int file_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
static int env_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Core PBX routines and definitions.
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
#define LINE_COUNTER(cptr, term, counter)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static int stat_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
static int load_module(void)
char * strsep(char **str, const char *delims)
static int env_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
int setenv(const char *name, const char *value, int overwrite)
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
static snd_pcm_format_t format
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
static struct ast_custom_function env_function
static struct ast_custom_function stat_function
#define ast_custom_function_register(acf)
Register a custom function.
int unsetenv(const char *name)
#define AST_APP_ARG(name)
Define an application argument.