903{
910 );
912 off_t flength, vlength;
913 size_t foplen = 0;
914 FILE *ff;
915
917
919 sscanf(
args.offset,
"%" SCNd64, &offset);
920 }
922 sscanf(
args.length,
"%" SCNd64, &length);
923 }
924
925 vlength = strlen(
value);
926
927 if (
args.argc < 4 || !strchr(
args.options,
'l')) {
928
929
930 if (
args.argc > 3 && strchr(
args.options,
'a')) {
931
932 if (!(ff = fopen(
args.filename,
"a"))) {
934 return 0;
935 }
936 if (fwrite(
value, 1, vlength, ff) < vlength) {
938 }
939 fclose(ff);
940 return 0;
941 }
else if (offset == 0 && length ==
LLONG_MAX) {
942 if (!(ff = fopen(
args.filename,
"w"))) {
944 return 0;
945 }
946 if (fwrite(
value, 1, vlength, ff) < vlength) {
948 }
949 fclose(ff);
950 return 0;
951 }
952
953 if (!(ff = fopen(
args.filename,
"r+"))) {
955 return 0;
956 }
957 fseeko(ff, 0, SEEK_END);
958 flength = ftello(ff);
959
960 if (offset < 0) {
961 if (fseeko(ff, offset, SEEK_END)) {
963 fclose(ff);
964 return -1;
965 }
966 if ((offset = ftello(ff)) < 0) {
968 fclose(ff);
969 return -1;
970 }
971 }
972
973 if (length < 0) {
974 length = flength - offset + length;
975 if (length < 0) {
976 ast_log(
LOG_ERROR,
"Length '%s' exceeds the file length. No data will be written.\n",
args.length);
977 fclose(ff);
978 return -1;
979 }
980 }
981
982 fseeko(ff, offset, SEEK_SET);
983
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);
986
987 if (length == vlength) {
988
989 if (fwrite(
value, 1, vlength, ff) < vlength) {
991 }
992 fclose(ff);
994
995 if (fwrite(
value, 1, vlength, ff) < vlength) {
997 }
998 fclose(ff);
999 if (truncate(
args.filename, offset + vlength)) {
1001 }
1002 } else if (length > vlength) {
1003
1004 char fbuf[4096];
1005 off_t cur;
1006 if (fwrite(
value, 1, vlength, ff) < vlength) {
1008 }
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)) {
1013 }
1014 fseeko(ff, cur + vlength - length, SEEK_SET);
1015 if (fwrite(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf)) {
1017 }
1018
1019 if (fseeko(ff, cur + sizeof(fbuf), SEEK_SET) < 0) {
1020
1021 break;
1022 }
1023 }
1024 fclose(ff);
1025 if (truncate(
args.filename, flength - (length - vlength))) {
1027 }
1028 } else {
1029
1030 char fbuf[4096];
1031 off_t lastwritten = flength + vlength - length;
1032
1033
1034 fseeko(ff, flength - sizeof(fbuf), SEEK_SET);
1035 while (offset < ftello(ff)) {
1036 if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf)) {
1038 fclose(ff);
1039 return -1;
1040 }
1041
1042
1043
1044 fseeko(ff, vlength - length - sizeof(fbuf), SEEK_CUR);
1045
1046
1047 lastwritten = ftello(ff);
1048
1049 if (fwrite(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf)) {
1051 fclose(ff);
1052 return -1;
1053 }
1054
1055 if (lastwritten < offset + sizeof(fbuf)) {
1056 break;
1057 }
1058
1059
1060
1061
1062
1063
1064 fseeko(ff, 2 * sizeof(fbuf) + vlength - length, SEEK_CUR);
1065 }
1066
1067
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));
1070 }
1071
1072
1073 ast_debug(1,
"Reading at %" PRId64
"\n", ftello(ff));
1074 if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
1076 }
1077 fseek(ff, offset, SEEK_SET);
1078
1079 if (fwrite(
value, 1, vlength, ff) < vlength) {
1081 } else {
1082 off_t curpos = ftello(ff);
1083 foplen = lastwritten - curpos;
1084 if (fwrite(fbuf, 1, foplen, ff) < foplen) {
1086 }
1087 }
1088 fclose(ff);
1089 }
1090 } else {
1092
1093
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') {
1101 }
1102 }
1105 return -1;
1106 }
1107
1108 if (strchr(
args.options,
'a')) {
1109
1110 if (!(ff = fopen(
args.filename,
"a"))) {
1112 return -1;
1113 }
1114 if (fwrite(
value, 1, vlength, ff) < vlength) {
1118 }
1119 fclose(ff);
1120 }
else if (offset == 0 && length ==
LLONG_MAX) {
1121
1122 off_t truncsize;
1123 if (!(ff = fopen(
args.filename,
"w"))) {
1125 return -1;
1126 }
1127 if (fwrite(
value, 1, vlength, ff) < vlength) {
1131 }
1132 if ((truncsize = ftello(ff)) < 0) {
1134 }
1135 fclose(ff);
1136 if (truncsize >= 0 && truncate(
args.filename, truncsize)) {
1138 return -1;
1139 }
1140 } else {
1141 int64_t offset_offset = (offset == 0 ? 0 : -1), length_offset = -1, flength, i, current_length = 0;
1142 char dos_state = 0, fbuf[4096];
1143
1144 if (offset < 0 && length < offset) {
1145
1146 ast_log(
LOG_ERROR,
"Length cannot specify a position prior to the offset\n");
1147 return -1;
1148 }
1149
1150 if (!(ff = fopen(
args.filename,
"r+"))) {
1152 return -1;
1153 }
1154
1155 if (fseek(ff, 0, SEEK_END)) {
1157 fclose(ff);
1158 return -1;
1159 }
1160 if ((flength = ftello(ff)) < 0) {
1162 fclose(ff);
1163 return -1;
1164 }
1165
1166
1167 if (offset < 0 || length < 0) {
1168 int64_t count = 0;
1169 for (i = (flength / sizeof(fbuf)) * sizeof(fbuf); i >= 0; i -= sizeof(fbuf)) {
1170 char *pos;
1171 if (fseeko(ff, i, SEEK_SET)) {
1173 }
1174 if (i + sizeof(fbuf) >= flength) {
1175 memset(fbuf, 0, sizeof(fbuf));
1176 }
1177 if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
1179 fclose(ff);
1180 return -1;
1181 }
1182 for (pos = fbuf + sizeof(fbuf) - 1; pos >= fbuf; pos--) {
1184
1185 if (length < 0 && count * -1 == length) {
1186 length_offset = i + (pos - fbuf);
1187 } else if (offset < 0 && count * -1 == (offset - 1)) {
1188
1189 if (newline_format ==
FF_DOS) {
1190 offset_offset = i + (pos - fbuf) + 2;
1191 } else {
1192 offset_offset = i + (pos - fbuf) + 1;
1193 }
1194 break;
1195 }
1196 }
1197 if ((offset < 0 && offset_offset >= 0) || (offset >= 0 && length_offset >= 0)) {
1198 break;
1199 }
1200 }
1201
1202 if (offset < 0 && offset_offset < 0 && offset == count * -1) {
1203 offset_offset = 0;
1204 }
1205 }
1206
1207
1208 if (offset > 0) {
1209 int64_t count = 0;
1210 fseek(ff, 0, SEEK_SET);
1211 for (i = 0; i < flength; i += sizeof(fbuf)) {
1212 char *pos;
1213 if (i + sizeof(fbuf) >= flength) {
1214 memset(fbuf, 0, sizeof(fbuf));
1215 }
1216 if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
1218 fclose(ff);
1219 return -1;
1220 }
1221 for (pos = fbuf; pos < fbuf + sizeof(fbuf); pos++) {
1223
1224 if (count == offset) {
1225 offset_offset = i + (pos - fbuf) + 1;
1226 break;
1227 }
1228 }
1229 if (offset_offset >= 0) {
1230 break;
1231 }
1232 }
1233 }
1234
1235 if (offset_offset < 0) {
1237 fclose(ff);
1238 return -1;
1239 }
1240
1241 if (length == 0) {
1242 length_offset = offset_offset;
1244 length_offset = flength;
1245 }
1246
1247
1248 if (length_offset < 0) {
1249 fseeko(ff, offset_offset, SEEK_SET);
1250 for (i = offset_offset; i < flength; i += sizeof(fbuf)) {
1251 char *pos;
1252 if (i + sizeof(fbuf) >= flength) {
1253 memset(fbuf, 0, sizeof(fbuf));
1254 }
1255 if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
1257 fclose(ff);
1258 return -1;
1259 }
1260 for (pos = fbuf; pos < fbuf + sizeof(fbuf); pos++) {
1262
1263 if (current_length == length) {
1264 length_offset = i + (pos - fbuf) + 1;
1265 break;
1266 }
1267 }
1268 if (length_offset >= 0) {
1269 break;
1270 }
1271 }
1272 if (length_offset < 0) {
1273
1274 ast_debug(3,
"Exceeds length of file? length=%" PRId64
", count=%" PRId64
", flength=%" PRId64
"\n", length, current_length, flength);
1275 length_offset = flength;
1276 }
1277 }
1278
1279
1280 if (length_offset - offset_offset == vlength + (strchr(
args.options,
'd') ? 0 : strlen(
format2term(newline_format)))) {
1281
1282 fseeko(ff, offset_offset, SEEK_SET);
1283 if (fwrite(
value, 1, vlength, ff) < vlength) {
1287 }
1288 fclose(ff);
1289 }
else if (length_offset - offset_offset > vlength + (strchr(
args.options,
'd') ? 0 : strlen(
format2term(newline_format)))) {
1290
1291 off_t cur;
1292 int64_t length_length = length_offset - offset_offset;
1293 size_t vlen = vlength + (strchr(
args.options,
'd') ? 0 : strlen(
format2term(newline_format)));
1294
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);
1297
1298 fseeko(ff, offset_offset, SEEK_SET);
1299 if (fwrite(
value, 1, vlength, ff) < vlength) {
1301 fclose(ff);
1302 return -1;
1303 }
else if (!strchr(
args.options,
'd') && fwrite(
format2term(newline_format), 1, vlen - vlength, ff) < vlen - vlength) {
1305 fclose(ff);
1306 return -1;
1307 }
1308 while ((cur = ftello(ff)) < flength) {
1309 if (cur < 0) {
1311 fclose(ff);
1312 return -1;
1313 }
1314 fseeko(ff, length_length - vlen, SEEK_CUR);
1315 if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
1317 fclose(ff);
1318 return -1;
1319 }
1320
1321 fseeko(ff, cur, SEEK_SET);
1322 if (fwrite(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf)) {
1324 fclose(ff);
1325 return -1;
1326 }
1327 }
1328 fclose(ff);
1329 if (truncate(
args.filename, flength - (length_length - vlen))) {
1331 }
1332 } else {
1333
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;
1337
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);
1340
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)) {
1345 fclose(ff);
1346 return -1;
1347 }
1348 fseeko(ff, sizeof(fbuf) - vlen - origlen, SEEK_CUR);
1349 if (fwrite(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf)) {
1351 fclose(ff);
1352 return -1;
1353 }
1354 if ((lastwritten = ftello(ff) - sizeof(fbuf)) < offset_offset + sizeof(fbuf)) {
1355 break;
1356 }
1357 fseeko(ff, 2 * sizeof(fbuf) + vlen - origlen, SEEK_CUR);
1358 }
1359 fseek(ff, length_offset, SEEK_SET);
1360 if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
1362 fclose(ff);
1363 return -1;
1364 }
1365 fseek(ff, offset_offset, SEEK_SET);
1366 if (fwrite(
value, 1, vlength, ff) < vlength) {
1368 fclose(ff);
1369 return -1;
1372 fclose(ff);
1373 return -1;
1374 } else {
1375 off_t curpos = ftello(ff);
1376 foplen = lastwritten - curpos;
1377 if (fwrite(fbuf, 1, foplen, ff) < foplen) {
1379 }
1380 }
1381 fclose(ff);
1382 }
1383 }
1384 }
1385
1386 return 0;
1387}
const char * format2term(enum file_format f)
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.