392 action =
strsep(&data,
",");
393 if (stat(data, &s)) {
401 snprintf(
buf,
len,
"%u", (
unsigned int) s.st_size);
404 snprintf(
buf,
len,
"%d", S_ISREG(s.st_mode) ? 1 : 0);
407 snprintf(
buf,
len,
"%d", S_ISDIR(s.st_mode) ? 1 : 0);
410 snprintf(
buf,
len,
"%d", (
int) s.st_mtime);
413 snprintf(
buf,
len,
"%d", (
int) s.st_mtime);
416 snprintf(
buf,
len,
"%d", (
int) s.st_ctime);
419 snprintf(
buf,
len,
"%o", (
unsigned int) s.st_mode);
440 if (!(ff = fopen(filename,
"r"))) {
445 while (fgets(fbuf,
sizeof(fbuf), ff)) {
446 char *next = fbuf, *first_cr =
NULL, *first_nl =
NULL;
452 first_cr = strchr(next,
'\r');
455 first_nl = strchr(next,
'\n');
459 if (!first_cr && !first_nl) {
464 if ((first_cr && !first_nl) || (first_cr && first_cr < first_nl)) {
465 if (first_nl && first_nl == first_cr + 1) {
467 }
else if (first_cr && first_cr == &fbuf[
sizeof(fbuf) - 2]) {
469 fseek(ff, -1, SEEK_CUR);
482 if (newline_format ==
FF_DOS) {
483 if (first_nl && first_cr && first_nl == first_cr + 1) {
486 }
else if (first_cr == &fbuf[
sizeof(fbuf) - 2]) {
488 fseek(ff, -1, SEEK_CUR);
491 }
else if (newline_format ==
FF_MAC) {
496 }
else if (newline_format ==
FF_UNIX) {
520 if (tolower(
args.format[0]) ==
'd') {
522 }
else if (tolower(
args.format[0]) ==
'm') {
524 }
else if (tolower(
args.format[0]) ==
'u') {
534#define LINE_COUNTER(cptr, term, counter) \
535 if (*cptr == '\n' && term == FF_UNIX) { \
537 } else if (*cptr == '\n' && term == FF_DOS && dos_state == 0) { \
539 } else if (*cptr == '\r' && term == FF_DOS && dos_state == 1) { \
542 } else if (*cptr == '\r' && term == FF_MAC) { \
544 } else if (term == FF_DOS) { \
552 char *first_cr, *first_nl;
555 if (!(ff = fopen(filename,
"r"))) {
560 while (fgets(fbuf,
sizeof(fbuf), ff)) {
561 first_cr = strchr(fbuf,
'\r');
562 first_nl = strchr(fbuf,
'\n');
564 if (!first_cr && !first_nl) {
568 if ((first_cr && !first_nl) || (first_cr && first_cr < first_nl)) {
570 if (first_nl && first_nl == first_cr + 1) {
572 }
else if (first_cr && first_cr == &fbuf[
sizeof(fbuf) - 2]) {
574 fseek(ff, -1, SEEK_CUR);
585 return newline_format;
619 ret = basename(data);
636 int64_t offset_offset = -1, length_offset = -1;
649 sscanf(
args.offset,
"%" SCNd64, &offset);
652 sscanf(
args.length,
"%" SCNd64, &length);
655 if (
args.argc < 4 || !strchr(
args.options,
'l')) {
659 if (!(ff = fopen(
args.filename,
"r"))) {
664 if (fseeko(ff, 0, SEEK_END) < 0) {
669 flength = ftello(ff);
672 fseeko(ff, offset, SEEK_END);
673 if ((offset = ftello(ff)) < 0) {
680 fseeko(ff, length, SEEK_END);
681 if ((length = ftello(ff)) - offset < 0) {
687 fseeko(ff, 0, SEEK_END);
693 fseeko(ff, offset, SEEK_SET);
694 for (off_i = ftello(ff); off_i < flength && off_i < offset + length; off_i +=
sizeof(fbuf)) {
696 size_t toappend =
sizeof(fbuf);
698 if (fread(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf) && !feof(ff)) {
704 if (off_i + toappend > offset + length) {
705 toappend =
MIN(offset + length - off_i, flength - off_i);
715 if (
args.argc == 5) {
716 if (tolower(
args.fileformat[0]) ==
'd') {
718 }
else if (tolower(
args.fileformat[0]) ==
'm') {
720 }
else if (tolower(
args.fileformat[0]) ==
'u') {
732 if (offset < 0 && length <= offset) {
735 }
else if (offset == 0) {
739 if (!(ff = fopen(
args.filename,
"r"))) {
744 if (fseek(ff, 0, SEEK_END)) {
750 flength = ftello(ff);
753 length_offset = flength;
757 if (offset < 0 || length < 0) {
761 for (i = (flength /
sizeof(fbuf)) *
sizeof(fbuf); i >= 0; i -=
sizeof(fbuf)) {
764 if (fseeko(ff, i, SEEK_SET)) {
767 end = fread(fbuf, 1,
sizeof(fbuf), ff);
768 for (pos = (
end <
sizeof(fbuf) ? fbuf +
end - 1 : fbuf +
sizeof(fbuf) - 1); pos >= fbuf; pos--) {
771 if (length < 0 && count * -1 == length) {
772 length_offset = i + (pos - fbuf);
773 }
else if (offset < 0 && count * -1 == (offset - 1)) {
776 offset_offset = i + (pos - fbuf) + 2;
778 offset_offset = i + (pos - fbuf) + 1;
783 if ((offset < 0 && offset_offset >= 0) || (offset >= 0 && length_offset >= 0)) {
788 if (offset < 0 && offset_offset < 0 && offset == count * -1) {
796 fseek(ff, 0, SEEK_SET);
797 for (i = 0; i < flength; i +=
sizeof(fbuf)) {
799 if (i +
sizeof(fbuf) <= flength) {
801 memset(fbuf, 0,
sizeof(fbuf));
803 if (fread(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf) && !feof(ff)) {
808 for (pos = fbuf; pos < fbuf +
sizeof(fbuf); pos++) {
811 if (count == offset) {
812 offset_offset = i + (pos - fbuf) + 1;
816 if (offset_offset >= 0) {
822 if (offset_offset < 0) {
829 if (fseeko(ff, offset_offset, SEEK_SET)) {
837 if (length_offset >= 0) {
838 ast_debug(3,
"offset=%" PRId64
", length=%" PRId64
", offset_offset=%" PRId64
", length_offset=%" PRId64
"\n", offset, length, offset_offset, length_offset);
839 for (i = offset_offset; i < length_offset; i +=
sizeof(fbuf)) {
840 if (fread(fbuf, 1, i +
sizeof(fbuf) > flength ? flength - i :
sizeof(fbuf), ff) < (i +
sizeof(fbuf) > flength ? flength - i :
sizeof(fbuf))) {
843 ast_debug(3,
"Appending first %" PRId64
" bytes of fbuf=%s\n", (int64_t)(i +
sizeof(fbuf) > length_offset ? length_offset - i :
sizeof(fbuf)), fbuf);
846 }
else if (length == 0) {
850 int64_t current_length = 0;
852 ast_debug(3,
"offset=%" PRId64
", length=%" PRId64
", offset_offset=%" PRId64
", length_offset=%" PRId64
"\n", offset, length, offset_offset, length_offset);
853 for (i = offset_offset; i < flength; i +=
sizeof(fbuf)) {
856 if ((bytes_read = fread(fbuf, 1,
sizeof(fbuf), ff)) <
sizeof(fbuf) && !feof(ff)) {
861 for (pos = fbuf; pos < fbuf + bytes_read; pos++) {
864 if (current_length == length) {
865 length_offset = i + (pos - fbuf) + 1;
869 ast_debug(3,
"length_offset=%" PRId64
", length_offset - i=%" PRId64
"\n", length_offset, length_offset - i);
870 ast_str_append_substr(
buf,
len, fbuf, (length_offset >= 0) ? length_offset - i : (flength > i +
sizeof(fbuf)) ?
sizeof(fbuf) : flength - i);
872 if (length_offset >= 0) {
885 const char *term[] = {
"",
"\n",
"\r\n",
"\r" };
899 off_t flength, vlength;
906 sscanf(
args.offset,
"%" SCNd64, &offset);
909 sscanf(
args.length,
"%" SCNd64, &length);
912 vlength = strlen(
value);
914 if (
args.argc < 4 || !strchr(
args.options,
'l')) {
917 if (
args.argc > 3 && strchr(
args.options,
'a')) {
919 if (!(ff = fopen(
args.filename,
"a"))) {
923 if (fwrite(
value, 1, vlength, ff) < vlength) {
928 }
else if (offset == 0 && length ==
LLONG_MAX) {
929 if (!(ff = fopen(
args.filename,
"w"))) {
933 if (fwrite(
value, 1, vlength, ff) < vlength) {
940 if (!(ff = fopen(
args.filename,
"r+"))) {
944 fseeko(ff, 0, SEEK_END);
945 flength = ftello(ff);
948 if (fseeko(ff, offset, SEEK_END)) {
953 if ((offset = ftello(ff)) < 0) {
961 length = flength - offset + length;
963 ast_log(
LOG_ERROR,
"Length '%s' exceeds the file length. No data will be written.\n",
args.length);
969 fseeko(ff, offset, SEEK_SET);
971 ast_debug(3,
"offset=%s/%" PRId64
", length=%s/%" PRId64
", vlength=%" PRId64
", flength=%" PRId64
"\n",
972 S_OR(
args.offset,
"(null)"), offset,
S_OR(
args.length,
"(null)"), length, vlength, flength);
974 if (length == vlength) {
976 if (fwrite(
value, 1, vlength, ff) < vlength) {
982 if (fwrite(
value, 1, vlength, ff) < vlength) {
986 if (truncate(
args.filename, offset + vlength)) {
989 }
else if (length > vlength) {
993 if (fwrite(
value, 1, vlength, ff) < vlength) {
996 fseeko(ff, length - vlength, SEEK_CUR);
997 while ((cur = ftello(ff)) < flength) {
998 if (fread(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf) && !feof(ff)) {
1001 fseeko(ff, cur + vlength - length, SEEK_SET);
1002 if (fwrite(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf)) {
1006 if (fseeko(ff, cur +
sizeof(fbuf), SEEK_SET) < 0) {
1012 if (truncate(
args.filename, flength - (length - vlength))) {
1018 off_t lastwritten = flength + vlength - length;
1021 fseeko(ff, flength -
sizeof(fbuf), SEEK_SET);
1022 while (offset < ftello(ff)) {
1023 if (fread(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf)) {
1031 fseeko(ff, vlength - length -
sizeof(fbuf), SEEK_CUR);
1034 lastwritten = ftello(ff);
1036 if (fwrite(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf)) {
1042 if (lastwritten < offset +
sizeof(fbuf)) {
1051 fseeko(ff, 2 *
sizeof(fbuf) + vlength - length, SEEK_CUR);
1055 if (fseeko(ff, offset + length, SEEK_SET)) {
1056 ast_log(
LOG_WARNING,
"Unable to seek to %" PRId64
" + %" PRId64
" != %" PRId64
"?)\n", offset, length, ftello(ff));
1060 ast_debug(1,
"Reading at %" PRId64
"\n", ftello(ff));
1061 if (fread(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf) && !feof(ff)) {
1064 fseek(ff, offset, SEEK_SET);
1066 if (fwrite(
value, 1, vlength, ff) < vlength) {
1069 off_t curpos = ftello(ff);
1070 foplen = lastwritten - curpos;
1071 if (fwrite(fbuf, 1, foplen, ff) < foplen) {
1081 if (
args.argc == 5) {
1082 if (tolower(
args.format[0]) ==
'u') {
1084 }
else if (tolower(
args.format[0]) ==
'm') {
1086 }
else if (tolower(
args.format[0]) ==
'd') {
1095 if (strchr(
args.options,
'a')) {
1097 if (!(ff = fopen(
args.filename,
"a"))) {
1101 if (fwrite(
value, 1, vlength, ff) < vlength) {
1107 }
else if (offset == 0 && length ==
LLONG_MAX) {
1110 if (!(ff = fopen(
args.filename,
"w"))) {
1114 if (fwrite(
value, 1, vlength, ff) < vlength) {
1119 if ((truncsize = ftello(ff)) < 0) {
1123 if (truncsize >= 0 && truncate(
args.filename, truncsize)) {
1128 int64_t offset_offset = (offset == 0 ? 0 : -1), length_offset = -1, flength, i, current_length = 0;
1129 char dos_state = 0, fbuf[4096];
1131 if (offset < 0 && length < offset) {
1133 ast_log(
LOG_ERROR,
"Length cannot specify a position prior to the offset\n");
1137 if (!(ff = fopen(
args.filename,
"r+"))) {
1142 if (fseek(ff, 0, SEEK_END)) {
1147 if ((flength = ftello(ff)) < 0) {
1154 if (offset < 0 || length < 0) {
1156 for (i = (flength /
sizeof(fbuf)) *
sizeof(fbuf); i >= 0; i -=
sizeof(fbuf)) {
1158 if (fseeko(ff, i, SEEK_SET)) {
1161 if (i +
sizeof(fbuf) >= flength) {
1162 memset(fbuf, 0,
sizeof(fbuf));
1164 if (fread(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf) && !feof(ff)) {
1169 for (pos = fbuf +
sizeof(fbuf) - 1; pos >= fbuf; pos--) {
1172 if (length < 0 && count * -1 == length) {
1173 length_offset = i + (pos - fbuf);
1174 }
else if (offset < 0 && count * -1 == (offset - 1)) {
1176 if (newline_format ==
FF_DOS) {
1177 offset_offset = i + (pos - fbuf) + 2;
1179 offset_offset = i + (pos - fbuf) + 1;
1184 if ((offset < 0 && offset_offset >= 0) || (offset >= 0 && length_offset >= 0)) {
1189 if (offset < 0 && offset_offset < 0 && offset == count * -1) {
1197 fseek(ff, 0, SEEK_SET);
1198 for (i = 0; i < flength; i +=
sizeof(fbuf)) {
1200 if (i +
sizeof(fbuf) >= flength) {
1201 memset(fbuf, 0,
sizeof(fbuf));
1203 if (fread(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf) && !feof(ff)) {
1208 for (pos = fbuf; pos < fbuf +
sizeof(fbuf); pos++) {
1211 if (count == offset) {
1212 offset_offset = i + (pos - fbuf) + 1;
1216 if (offset_offset >= 0) {
1222 if (offset_offset < 0) {
1229 length_offset = offset_offset;
1231 length_offset = flength;
1235 if (length_offset < 0) {
1236 fseeko(ff, offset_offset, SEEK_SET);
1237 for (i = offset_offset; i < flength; i +=
sizeof(fbuf)) {
1239 if (i +
sizeof(fbuf) >= flength) {
1240 memset(fbuf, 0,
sizeof(fbuf));
1242 if (fread(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf) && !feof(ff)) {
1247 for (pos = fbuf; pos < fbuf +
sizeof(fbuf); pos++) {
1250 if (current_length == length) {
1251 length_offset = i + (pos - fbuf) + 1;
1255 if (length_offset >= 0) {
1259 if (length_offset < 0) {
1261 ast_debug(3,
"Exceeds length of file? length=%" PRId64
", count=%" PRId64
", flength=%" PRId64
"\n", length, current_length, flength);
1262 length_offset = flength;
1267 if (length_offset - offset_offset == vlength + (strchr(
args.options,
'd') ? 0 : strlen(
format2term(newline_format)))) {
1269 fseeko(ff, offset_offset, SEEK_SET);
1270 if (fwrite(
value, 1, vlength, ff) < vlength) {
1276 }
else if (length_offset - offset_offset > vlength + (strchr(
args.options,
'd') ? 0 : strlen(
format2term(newline_format)))) {
1279 int64_t length_length = length_offset - offset_offset;
1280 size_t vlen = vlength + (strchr(
args.options,
'd') ? 0 : strlen(
format2term(newline_format)));
1282 ast_debug(3,
"offset=%s/%" PRId64
", length=%s/%" PRId64
" (%" PRId64
"), vlength=%" PRId64
", flength=%" PRId64
"\n",
1283 args.offset, offset_offset,
args.length, length_offset, length_length, vlength, flength);
1285 fseeko(ff, offset_offset, SEEK_SET);
1286 if (fwrite(
value, 1, vlength, ff) < vlength) {
1290 }
else if (!strchr(
args.options,
'd') && fwrite(
format2term(newline_format), 1, vlen - vlength, ff) < vlen - vlength) {
1295 while ((cur = ftello(ff)) < flength) {
1301 fseeko(ff, length_length - vlen, SEEK_CUR);
1302 if (fread(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf) && !feof(ff)) {
1308 fseeko(ff, cur, SEEK_SET);
1309 if (fwrite(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf)) {
1316 if (truncate(
args.filename, flength - (length_length - vlen))) {
1321 size_t vlen = vlength + (strchr(
args.options,
'd') ? 0 : strlen(
format2term(newline_format)));
1322 int64_t origlen = length_offset - offset_offset;
1323 off_t lastwritten = flength + vlen - origlen;
1325 ast_debug(3,
"offset=%s/%" PRId64
", length=%s/%" PRId64
", vlength=%" PRId64
", flength=%" PRId64
"\n",
1326 args.offset, offset_offset,
args.length, length_offset, vlength, flength);
1328 fseeko(ff, flength -
sizeof(fbuf), SEEK_SET);
1329 while (offset_offset +
sizeof(fbuf) < ftello(ff)) {
1330 if (fread(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf)) {
1335 fseeko(ff,
sizeof(fbuf) - vlen - origlen, SEEK_CUR);
1336 if (fwrite(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf)) {
1341 if ((lastwritten = ftello(ff) -
sizeof(fbuf)) < offset_offset +
sizeof(fbuf)) {
1344 fseeko(ff, 2 *
sizeof(fbuf) + vlen - origlen, SEEK_CUR);
1346 fseek(ff, length_offset, SEEK_SET);
1347 if (fread(fbuf, 1,
sizeof(fbuf), ff) <
sizeof(fbuf) && !feof(ff)) {
1352 fseek(ff, offset_offset, SEEK_SET);
1353 if (fwrite(
value, 1, vlength, ff) < vlength) {
1362 off_t curpos = ftello(ff);
1363 foplen = lastwritten - curpos;
1364 if (fwrite(fbuf, 1, foplen, ff) < foplen) {
1395 .
name =
"FILE_COUNT_LINE",
1401 .
name =
"FILE_FORMAT",
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.
int unsetenv(const char *name)
int setenv(const char *name, const char *value, int overwrite)
char * strsep(char **str, const char *delims)
#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.