405 action =
strsep(&data,
",");
406 if (stat(data, &s)) {
414 snprintf(
buf,
len,
"%u", (
unsigned int) s.st_size);
417 snprintf(
buf,
len,
"%d", S_ISREG(s.st_mode) ? 1 : 0);
420 snprintf(
buf,
len,
"%d", S_ISDIR(s.st_mode) ? 1 : 0);
423 snprintf(
buf,
len,
"%d", (
int) s.st_mtime);
426 snprintf(
buf,
len,
"%d", (
int) s.st_mtime);
429 snprintf(
buf,
len,
"%d", (
int) s.st_ctime);
432 snprintf(
buf,
len,
"%o", (
unsigned int) s.st_mode);
453 if (!(ff = fopen(filename,
"r"))) {
458 while (fgets(fbuf,
sizeof(fbuf), ff)) {
459 char *next = fbuf, *first_cr =
NULL, *first_nl =
NULL;
465 first_cr = strchr(next,
'\r');
468 first_nl = strchr(next,
'\n');
472 if (!first_cr && !first_nl) {
477 if ((first_cr && !first_nl) || (first_cr && first_cr < first_nl)) {
478 if (first_nl && first_nl == first_cr + 1) {
480 }
else if (first_cr && first_cr == &fbuf[
sizeof(fbuf) - 2]) {
482 fseek(ff, -1, SEEK_CUR);
495 if (newline_format ==
FF_DOS) {
496 if (first_nl && first_cr && first_nl == first_cr + 1) {
499 }
else if (first_cr == &fbuf[
sizeof(fbuf) - 2]) {
501 fseek(ff, -1, SEEK_CUR);
504 }
else if (newline_format ==
FF_MAC) {
509 }
else if (newline_format ==
FF_UNIX) {
533 if (tolower(
args.format[0]) ==
'd') {
535 }
else if (tolower(
args.format[0]) ==
'm') {
537 }
else if (tolower(
args.format[0]) ==
'u') {
547#define LINE_COUNTER(cptr, term, counter) \
548 if (*cptr == '\n' && term == FF_UNIX) { \
550 } else if (*cptr == '\n' && term == FF_DOS && dos_state == 0) { \
552 } else if (*cptr == '\r' && term == FF_DOS && dos_state == 1) { \
555 } else if (*cptr == '\r' && term == FF_MAC) { \
557 } else if (term == FF_DOS) { \
565 char *first_cr, *first_nl;
568 if (!(ff = fopen(filename,
"r"))) {
573 while (fgets(fbuf,
sizeof(fbuf), ff)) {
574 first_cr = strchr(fbuf,
'\r');
575 first_nl = strchr(fbuf,
'\n');
577 if (!first_cr && !first_nl) {
581 if ((first_cr && !first_nl) || (first_cr && first_cr < first_nl)) {
583 if (first_nl && first_nl == first_cr + 1) {
585 }
else if (first_cr && first_cr == &fbuf[
sizeof(fbuf) - 2]) {
587 fseek(ff, -1, SEEK_CUR);
598 return newline_format;
632 ret = basename(data);
649 int64_t offset_offset = -1, length_offset = -1;
662 sscanf(
args.offset,
"%" SCNd64, &offset);
665 sscanf(
args.length,
"%" SCNd64, &length);
668 if (
args.argc < 4 || !strchr(
args.options,
'l')) {
672 if (!(ff = fopen(
args.filename,
"r"))) {
677 if (fseeko(ff, 0, SEEK_END) < 0) {
682 flength = ftello(ff);
685 fseeko(ff, offset, SEEK_END);
686 if ((offset = ftello(ff)) < 0) {
693 fseeko(ff, length, SEEK_END);
694 if ((length = ftello(ff)) - offset < 0) {
700 fseeko(ff, 0, SEEK_END);
706 fseeko(ff, offset, SEEK_SET);
707 for (off_i = ftello(ff); off_i < flength && off_i < offset + length; off_i +=
sizeof(fbuf)) {
709 size_t toappend =
sizeof(fbuf);
711 if (fread(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf) && !feof(ff)) {
717 if (off_i + toappend > offset + length) {
718 toappend =
MIN(offset + length - off_i, flength - off_i);
728 if (
args.argc == 5) {
729 if (tolower(
args.fileformat[0]) ==
'd') {
731 }
else if (tolower(
args.fileformat[0]) ==
'm') {
733 }
else if (tolower(
args.fileformat[0]) ==
'u') {
745 if (offset < 0 && length <= offset) {
748 }
else if (offset == 0) {
752 if (!(ff = fopen(
args.filename,
"r"))) {
757 if (fseek(ff, 0, SEEK_END)) {
763 flength = ftello(ff);
766 length_offset = flength;
770 if (offset < 0 || length < 0) {
774 for (i = (flength /
sizeof(fbuf)) *
sizeof(fbuf); i >= 0; i -=
sizeof(fbuf)) {
777 if (fseeko(ff, i, SEEK_SET)) {
780 end = fread(fbuf, 1,
sizeof(fbuf), ff);
781 for (pos = (
end <
sizeof(fbuf) ? fbuf +
end - 1 : fbuf +
sizeof(fbuf) - 1); pos >= fbuf; pos--) {
784 if (length < 0 && count * -1 == length) {
785 length_offset = i + (pos - fbuf);
786 }
else if (offset < 0 && count * -1 == (offset - 1)) {
789 offset_offset = i + (pos - fbuf) + 2;
791 offset_offset = i + (pos - fbuf) + 1;
796 if ((offset < 0 && offset_offset >= 0) || (offset >= 0 && length_offset >= 0)) {
801 if (offset < 0 && offset_offset < 0 && offset == count * -1) {
809 fseek(ff, 0, SEEK_SET);
810 for (i = 0; i < flength; i +=
sizeof(fbuf)) {
812 if (i +
sizeof(fbuf) <= flength) {
814 memset(fbuf, 0,
sizeof(fbuf));
816 if (fread(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf) && !feof(ff)) {
821 for (pos = fbuf; pos < fbuf +
sizeof(fbuf); pos++) {
824 if (count == offset) {
825 offset_offset = i + (pos - fbuf) + 1;
829 if (offset_offset >= 0) {
835 if (offset_offset < 0) {
842 if (fseeko(ff, offset_offset, SEEK_SET)) {
850 if (length_offset >= 0) {
851 ast_debug(3,
"offset=%" PRId64
", length=%" PRId64
", offset_offset=%" PRId64
", length_offset=%" PRId64
"\n", offset, length, offset_offset, length_offset);
852 for (i = offset_offset; i < length_offset; i +=
sizeof(fbuf)) {
853 if (fread(fbuf, 1, i +
sizeof(fbuf) > flength ? flength - i :
sizeof(fbuf), ff) < (i +
sizeof(fbuf) > flength ? flength - i :
sizeof(fbuf))) {
856 ast_debug(3,
"Appending first %" PRId64
" bytes of fbuf=%s\n", (int64_t)(i +
sizeof(fbuf) > length_offset ? length_offset - i :
sizeof(fbuf)), fbuf);
859 }
else if (length == 0) {
863 int64_t current_length = 0;
865 ast_debug(3,
"offset=%" PRId64
", length=%" PRId64
", offset_offset=%" PRId64
", length_offset=%" PRId64
"\n", offset, length, offset_offset, length_offset);
866 for (i = offset_offset; i < flength; i +=
sizeof(fbuf)) {
869 if ((bytes_read = fread(fbuf, 1,
sizeof(fbuf), ff)) <
sizeof(fbuf) && !feof(ff)) {
874 for (pos = fbuf; pos < fbuf + bytes_read; pos++) {
877 if (current_length == length) {
878 length_offset = i + (pos - fbuf) + 1;
882 ast_debug(3,
"length_offset=%" PRId64
", length_offset - i=%" PRId64
"\n", length_offset, length_offset - i);
883 ast_str_append_substr(
buf,
len, fbuf, (length_offset >= 0) ? length_offset - i : (flength > i +
sizeof(fbuf)) ?
sizeof(fbuf) : flength - i);
885 if (length_offset >= 0) {
898 const char *term[] = {
"",
"\n",
"\r\n",
"\r" };
912 off_t flength, vlength;
919 sscanf(
args.offset,
"%" SCNd64, &offset);
922 sscanf(
args.length,
"%" SCNd64, &length);
925 vlength = strlen(
value);
927 if (
args.argc < 4 || !strchr(
args.options,
'l')) {
930 if (
args.argc > 3 && strchr(
args.options,
'a')) {
932 if (!(ff = fopen(
args.filename,
"a"))) {
936 if (fwrite(
value, 1, vlength, ff) < vlength) {
941 }
else if (offset == 0 && length ==
LLONG_MAX) {
942 if (!(ff = fopen(
args.filename,
"w"))) {
946 if (fwrite(
value, 1, vlength, ff) < vlength) {
953 if (!(ff = fopen(
args.filename,
"r+"))) {
957 fseeko(ff, 0, SEEK_END);
958 flength = ftello(ff);
961 if (fseeko(ff, offset, SEEK_END)) {
966 if ((offset = ftello(ff)) < 0) {
974 length = flength - offset + length;
976 ast_log(
LOG_ERROR,
"Length '%s' exceeds the file length. No data will be written.\n",
args.length);
982 fseeko(ff, offset, SEEK_SET);
984 ast_debug(3,
"offset=%s/%" PRId64
", length=%s/%" PRId64
", vlength=%" PRId64
", flength=%" PRId64
"\n",
985 S_OR(
args.offset,
"(null)"), offset,
S_OR(
args.length,
"(null)"), length, vlength, flength);
987 if (length == vlength) {
989 if (fwrite(
value, 1, vlength, ff) < vlength) {
995 if (fwrite(
value, 1, vlength, ff) < vlength) {
999 if (truncate(
args.filename, offset + vlength)) {
1002 }
else if (length > vlength) {
1006 if (fwrite(
value, 1, vlength, ff) < vlength) {
1009 fseeko(ff, length - vlength, SEEK_CUR);
1010 while ((cur = ftello(ff)) < flength) {
1011 if (fread(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf) && !feof(ff)) {
1014 fseeko(ff, cur + vlength - length, SEEK_SET);
1015 if (fwrite(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf)) {
1019 if (fseeko(ff, cur +
sizeof(fbuf), SEEK_SET) < 0) {
1025 if (truncate(
args.filename, flength - (length - vlength))) {
1031 off_t lastwritten = flength + vlength - length;
1034 fseeko(ff, flength -
sizeof(fbuf), SEEK_SET);
1035 while (offset < ftello(ff)) {
1036 if (fread(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf)) {
1044 fseeko(ff, vlength - length -
sizeof(fbuf), SEEK_CUR);
1047 lastwritten = ftello(ff);
1049 if (fwrite(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf)) {
1055 if (lastwritten < offset +
sizeof(fbuf)) {
1064 fseeko(ff, 2 *
sizeof(fbuf) + vlength - length, SEEK_CUR);
1068 if (fseeko(ff, offset + length, SEEK_SET)) {
1069 ast_log(
LOG_WARNING,
"Unable to seek to %" PRId64
" + %" PRId64
" != %" PRId64
"?)\n", offset, length, ftello(ff));
1073 ast_debug(1,
"Reading at %" PRId64
"\n", ftello(ff));
1074 if (fread(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf) && !feof(ff)) {
1077 fseek(ff, offset, SEEK_SET);
1079 if (fwrite(
value, 1, vlength, ff) < vlength) {
1082 off_t curpos = ftello(ff);
1083 foplen = lastwritten - curpos;
1084 if (fwrite(fbuf, 1, foplen, ff) < foplen) {
1094 if (
args.argc == 5) {
1095 if (tolower(
args.format[0]) ==
'u') {
1097 }
else if (tolower(
args.format[0]) ==
'm') {
1099 }
else if (tolower(
args.format[0]) ==
'd') {
1108 if (strchr(
args.options,
'a')) {
1110 if (!(ff = fopen(
args.filename,
"a"))) {
1114 if (fwrite(
value, 1, vlength, ff) < vlength) {
1120 }
else if (offset == 0 && length ==
LLONG_MAX) {
1123 if (!(ff = fopen(
args.filename,
"w"))) {
1127 if (fwrite(
value, 1, vlength, ff) < vlength) {
1132 if ((truncsize = ftello(ff)) < 0) {
1136 if (truncsize >= 0 && truncate(
args.filename, truncsize)) {
1141 int64_t offset_offset = (offset == 0 ? 0 : -1), length_offset = -1, flength, i, current_length = 0;
1142 char dos_state = 0, fbuf[4096];
1144 if (offset < 0 && length < offset) {
1146 ast_log(
LOG_ERROR,
"Length cannot specify a position prior to the offset\n");
1150 if (!(ff = fopen(
args.filename,
"r+"))) {
1155 if (fseek(ff, 0, SEEK_END)) {
1160 if ((flength = ftello(ff)) < 0) {
1167 if (offset < 0 || length < 0) {
1169 for (i = (flength /
sizeof(fbuf)) *
sizeof(fbuf); i >= 0; i -=
sizeof(fbuf)) {
1171 if (fseeko(ff, i, SEEK_SET)) {
1174 if (i +
sizeof(fbuf) >= flength) {
1175 memset(fbuf, 0,
sizeof(fbuf));
1177 if (fread(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf) && !feof(ff)) {
1182 for (pos = fbuf +
sizeof(fbuf) - 1; pos >= fbuf; pos--) {
1185 if (length < 0 && count * -1 == length) {
1186 length_offset = i + (pos - fbuf);
1187 }
else if (offset < 0 && count * -1 == (offset - 1)) {
1189 if (newline_format ==
FF_DOS) {
1190 offset_offset = i + (pos - fbuf) + 2;
1192 offset_offset = i + (pos - fbuf) + 1;
1197 if ((offset < 0 && offset_offset >= 0) || (offset >= 0 && length_offset >= 0)) {
1202 if (offset < 0 && offset_offset < 0 && offset == count * -1) {
1210 fseek(ff, 0, SEEK_SET);
1211 for (i = 0; i < flength; i +=
sizeof(fbuf)) {
1213 if (i +
sizeof(fbuf) >= flength) {
1214 memset(fbuf, 0,
sizeof(fbuf));
1216 if (fread(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf) && !feof(ff)) {
1221 for (pos = fbuf; pos < fbuf +
sizeof(fbuf); pos++) {
1224 if (count == offset) {
1225 offset_offset = i + (pos - fbuf) + 1;
1229 if (offset_offset >= 0) {
1235 if (offset_offset < 0) {
1242 length_offset = offset_offset;
1244 length_offset = flength;
1248 if (length_offset < 0) {
1249 fseeko(ff, offset_offset, SEEK_SET);
1250 for (i = offset_offset; i < flength; i +=
sizeof(fbuf)) {
1252 if (i +
sizeof(fbuf) >= flength) {
1253 memset(fbuf, 0,
sizeof(fbuf));
1255 if (fread(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf) && !feof(ff)) {
1260 for (pos = fbuf; pos < fbuf +
sizeof(fbuf); pos++) {
1263 if (current_length == length) {
1264 length_offset = i + (pos - fbuf) + 1;
1268 if (length_offset >= 0) {
1272 if (length_offset < 0) {
1274 ast_debug(3,
"Exceeds length of file? length=%" PRId64
", count=%" PRId64
", flength=%" PRId64
"\n", length, current_length, flength);
1275 length_offset = flength;
1280 if (length_offset - offset_offset == vlength + (strchr(
args.options,
'd') ? 0 : strlen(
format2term(newline_format)))) {
1282 fseeko(ff, offset_offset, SEEK_SET);
1283 if (fwrite(
value, 1, vlength, ff) < vlength) {
1289 }
else if (length_offset - offset_offset > vlength + (strchr(
args.options,
'd') ? 0 : strlen(
format2term(newline_format)))) {
1292 int64_t length_length = length_offset - offset_offset;
1293 size_t vlen = vlength + (strchr(
args.options,
'd') ? 0 : strlen(
format2term(newline_format)));
1295 ast_debug(3,
"offset=%s/%" PRId64
", length=%s/%" PRId64
" (%" PRId64
"), vlength=%" PRId64
", flength=%" PRId64
"\n",
1296 args.offset, offset_offset,
args.length, length_offset, length_length, vlength, flength);
1298 fseeko(ff, offset_offset, SEEK_SET);
1299 if (fwrite(
value, 1, vlength, ff) < vlength) {
1303 }
else if (!strchr(
args.options,
'd') && fwrite(
format2term(newline_format), 1, vlen - vlength, ff) < vlen - vlength) {
1308 while ((cur = ftello(ff)) < flength) {
1314 fseeko(ff, length_length - vlen, SEEK_CUR);
1315 if (fread(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf) && !feof(ff)) {
1321 fseeko(ff, cur, SEEK_SET);
1322 if (fwrite(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf)) {
1329 if (truncate(
args.filename, flength - (length_length - vlen))) {
1334 size_t vlen = vlength + (strchr(
args.options,
'd') ? 0 : strlen(
format2term(newline_format)));
1335 int64_t origlen = length_offset - offset_offset;
1336 off_t lastwritten = flength + vlen - origlen;
1338 ast_debug(3,
"offset=%s/%" PRId64
", length=%s/%" PRId64
", vlength=%" PRId64
", flength=%" PRId64
"\n",
1339 args.offset, offset_offset,
args.length, length_offset, vlength, flength);
1341 fseeko(ff, flength -
sizeof(fbuf), SEEK_SET);
1342 while (offset_offset +
sizeof(fbuf) < ftello(ff)) {
1343 if (fread(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf)) {
1348 fseeko(ff,
sizeof(fbuf) - vlen - origlen, SEEK_CUR);
1349 if (fwrite(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf)) {
1354 if ((lastwritten = ftello(ff) -
sizeof(fbuf)) < offset_offset +
sizeof(fbuf)) {
1357 fseeko(ff, 2 *
sizeof(fbuf) + vlen - origlen, SEEK_CUR);
1359 fseek(ff, length_offset, SEEK_SET);
1360 if (fread(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf) && !feof(ff)) {
1365 fseek(ff, offset_offset, SEEK_SET);
1366 if (fwrite(
value, 1, vlength, ff) < vlength) {
1375 off_t curpos = ftello(ff);
1376 foplen = lastwritten - curpos;
1377 if (fwrite(fbuf, 1, foplen, ff) < foplen) {
1408 .
name =
"FILE_COUNT_LINE",
1414 .
name =
"FILE_FORMAT",
int unsetenv(const char *name)
int setenv(const char *name, const char *value, int overwrite)
char * strsep(char **str, const char *delims)
Asterisk main include file. File version handling, generic pbx functions.
General Asterisk PBX channel definitions.
Generic File Format Support. Should be included by clients of the file handling routines....
static int env_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
static struct ast_custom_function file_format_function
static int file_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
static struct ast_custom_function file_count_line_function
static int64_t count_lines(const char *filename, enum file_format newline_format)
static enum file_format file2format(const char *filename)
static int env_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static struct ast_custom_function env_function
static int file_count_line(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
const char * format2term(enum file_format f)
static int stat_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static struct ast_custom_function file_function
static struct ast_custom_function file_basename_function
static int file_basename(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static struct ast_custom_function stat_function
static int load_module(void)
static int unload_module(void)
#define LINE_COUNTER(cptr, term, counter)
static int file_read(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
static struct ast_custom_function file_dirname_function
static int file_dirname(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
#define ast_debug(level,...)
Log a DEBUG message.
Asterisk module definitions.
#define AST_MODULE_INFO_STANDARD(keystr, desc)
#define ASTERISK_GPL_KEY
The text the key() function should return.
Core PBX routines and definitions.
#define ast_custom_function_register_escalating(acf, escalation)
Register a custom function which requires escalated privileges.
#define ast_custom_function_register(acf)
Register a custom function.
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
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.
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Main Channel structure associated with a channel.
Data structure associated with a custom dialplan function.
Support for dynamic strings.