906{
913 );
915 off_t flength, vlength;
916 size_t foplen = 0;
917 FILE *ff;
918
920
922 sscanf(
args.offset,
"%" SCNd64, &offset);
923 }
925 sscanf(
args.length,
"%" SCNd64, &length);
926 }
927
928 vlength = strlen(
value);
929
930 if (
args.argc < 4 || !strchr(
args.options,
'l')) {
931
932
933 if (
args.argc > 3 && strchr(
args.options,
'a')) {
934
935 if (!(ff = fopen(
args.filename,
"a"))) {
937 return 0;
938 }
939 if (fwrite(
value, 1, vlength, ff) < vlength) {
941 }
942 fclose(ff);
943 return 0;
944 }
else if (offset == 0 && length ==
LLONG_MAX) {
945 if (!(ff = fopen(
args.filename,
"w"))) {
947 return 0;
948 }
949 if (fwrite(
value, 1, vlength, ff) < vlength) {
951 }
952 fclose(ff);
953 return 0;
954 }
955
956 if (!(ff = fopen(
args.filename,
"r+"))) {
958 return 0;
959 }
960 fseeko(ff, 0, SEEK_END);
961 flength = ftello(ff);
962
963 if (offset < 0) {
964 if (fseeko(ff, offset, SEEK_END)) {
966 fclose(ff);
967 return -1;
968 }
969 if ((offset = ftello(ff)) < 0) {
971 fclose(ff);
972 return -1;
973 }
974 }
975
976 if (length < 0) {
977 length = flength - offset + length;
978 if (length < 0) {
979 ast_log(
LOG_ERROR,
"Length '%s' exceeds the file length. No data will be written.\n",
args.length);
980 fclose(ff);
981 return -1;
982 }
983 }
984
985 fseeko(ff, offset, SEEK_SET);
986
987 ast_debug(3,
"offset=%s/%" PRId64
", length=%s/%" PRId64
", vlength=%" PRId64
", flength=%" PRId64
"\n",
988 S_OR(
args.offset,
"(null)"), offset,
S_OR(
args.length,
"(null)"), length, vlength, flength);
989
990 if (length == vlength) {
991
992 if (fwrite(
value, 1, vlength, ff) < vlength) {
994 }
995 fclose(ff);
997
998 if (fwrite(
value, 1, vlength, ff) < vlength) {
1000 }
1001 fclose(ff);
1002 if (truncate(
args.filename, offset + vlength)) {
1004 }
1005 } else if (length > vlength) {
1006
1007 char fbuf[4096];
1008 off_t cur;
1009 if (fwrite(
value, 1, vlength, ff) < vlength) {
1011 }
1012 fseeko(ff, length - vlength, SEEK_CUR);
1013 while ((cur = ftello(ff)) < flength) {
1014 if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
1016 }
1017 fseeko(ff, cur + vlength - length, SEEK_SET);
1018 if (fwrite(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf)) {
1020 }
1021
1022 if (fseeko(ff, cur + sizeof(fbuf), SEEK_SET) < 0) {
1023
1024 break;
1025 }
1026 }
1027 fclose(ff);
1028 if (truncate(
args.filename, flength - (length - vlength))) {
1030 }
1031 } else {
1032
1033 char fbuf[4096];
1034 off_t lastwritten = flength + vlength - length;
1035
1036
1037 fseeko(ff, flength - sizeof(fbuf), SEEK_SET);
1038 while (offset < ftello(ff)) {
1039 if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf)) {
1041 fclose(ff);
1042 return -1;
1043 }
1044
1045
1046
1047 fseeko(ff, vlength - length - sizeof(fbuf), SEEK_CUR);
1048
1049
1050 lastwritten = ftello(ff);
1051
1052 if (fwrite(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf)) {
1054 fclose(ff);
1055 return -1;
1056 }
1057
1058 if (lastwritten < offset + sizeof(fbuf)) {
1059 break;
1060 }
1061
1062
1063
1064
1065
1066
1067 fseeko(ff, 2 * sizeof(fbuf) + vlength - length, SEEK_CUR);
1068 }
1069
1070
1071 if (fseeko(ff, offset + length, SEEK_SET)) {
1072 ast_log(
LOG_WARNING,
"Unable to seek to %" PRId64
" + %" PRId64
" != %" PRId64
"?)\n", offset, length, ftello(ff));
1073 }
1074
1075
1076 ast_debug(1,
"Reading at %" PRId64
"\n", ftello(ff));
1077 if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
1079 }
1080 fseek(ff, offset, SEEK_SET);
1081
1082 if (fwrite(
value, 1, vlength, ff) < vlength) {
1084 } else {
1085 off_t curpos = ftello(ff);
1086 foplen = lastwritten - curpos;
1087 if (fwrite(fbuf, 1, foplen, ff) < foplen) {
1089 }
1090 }
1091 fclose(ff);
1092 }
1093 } else {
1095
1096
1097 if (
args.argc == 5) {
1098 if (tolower(
args.format[0]) ==
'u') {
1100 }
else if (tolower(
args.format[0]) ==
'm') {
1102 }
else if (tolower(
args.format[0]) ==
'd') {
1104 }
1105 }
1108 return -1;
1109 }
1110
1111 if (strchr(
args.options,
'a')) {
1112
1113 if (!(ff = fopen(
args.filename,
"a"))) {
1115 return -1;
1116 }
1117 if (fwrite(
value, 1, vlength, ff) < vlength) {
1121 }
1122 fclose(ff);
1123 }
else if (offset == 0 && length ==
LLONG_MAX) {
1124
1125 off_t truncsize;
1126 if (!(ff = fopen(
args.filename,
"w"))) {
1128 return -1;
1129 }
1130 if (fwrite(
value, 1, vlength, ff) < vlength) {
1134 }
1135 if ((truncsize = ftello(ff)) < 0) {
1137 }
1138 fclose(ff);
1139 if (truncsize >= 0 && truncate(
args.filename, truncsize)) {
1141 return -1;
1142 }
1143 } else {
1144 int64_t offset_offset = (offset == 0 ? 0 : -1), length_offset = -1, flength, i, current_length = 0;
1145 char dos_state = 0, fbuf[4096];
1146
1147 if (offset < 0 && length < offset) {
1148
1149 ast_log(
LOG_ERROR,
"Length cannot specify a position prior to the offset\n");
1150 return -1;
1151 }
1152
1153 if (!(ff = fopen(
args.filename,
"r+"))) {
1155 return -1;
1156 }
1157
1158 if (fseek(ff, 0, SEEK_END)) {
1160 fclose(ff);
1161 return -1;
1162 }
1163 if ((flength = ftello(ff)) < 0) {
1165 fclose(ff);
1166 return -1;
1167 }
1168
1169
1170 if (offset < 0 || length < 0) {
1171 int64_t count = 0;
1172 for (i = (flength / sizeof(fbuf)) * sizeof(fbuf); i >= 0; i -= sizeof(fbuf)) {
1173 char *pos;
1174 if (fseeko(ff, i, SEEK_SET)) {
1176 }
1177 if (i + sizeof(fbuf) >= flength) {
1178 memset(fbuf, 0, sizeof(fbuf));
1179 }
1180 if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
1182 fclose(ff);
1183 return -1;
1184 }
1185 for (pos = fbuf + sizeof(fbuf) - 1; pos >= fbuf; pos--) {
1187
1188 if (length < 0 && count * -1 == length) {
1189 length_offset = i + (pos - fbuf);
1190 } else if (offset < 0 && count * -1 == (offset - 1)) {
1191
1192 if (newline_format ==
FF_DOS) {
1193 offset_offset = i + (pos - fbuf) + 2;
1194 } else {
1195 offset_offset = i + (pos - fbuf) + 1;
1196 }
1197 break;
1198 }
1199 }
1200 if ((offset < 0 && offset_offset >= 0) || (offset >= 0 && length_offset >= 0)) {
1201 break;
1202 }
1203 }
1204
1205 if (offset < 0 && offset_offset < 0 && offset == count * -1) {
1206 offset_offset = 0;
1207 }
1208 }
1209
1210
1211 if (offset > 0) {
1212 int64_t count = 0;
1213 fseek(ff, 0, SEEK_SET);
1214 for (i = 0; i < flength; i += sizeof(fbuf)) {
1215 char *pos;
1216 if (i + sizeof(fbuf) >= flength) {
1217 memset(fbuf, 0, sizeof(fbuf));
1218 }
1219 if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
1221 fclose(ff);
1222 return -1;
1223 }
1224 for (pos = fbuf; pos < fbuf + sizeof(fbuf); pos++) {
1226
1227 if (count == offset) {
1228 offset_offset = i + (pos - fbuf) + 1;
1229 break;
1230 }
1231 }
1232 if (offset_offset >= 0) {
1233 break;
1234 }
1235 }
1236 }
1237
1238 if (offset_offset < 0) {
1240 fclose(ff);
1241 return -1;
1242 }
1243
1244 if (length == 0) {
1245 length_offset = offset_offset;
1247 length_offset = flength;
1248 }
1249
1250
1251 if (length_offset < 0) {
1252 fseeko(ff, offset_offset, SEEK_SET);
1253 for (i = offset_offset; i < flength; i += sizeof(fbuf)) {
1254 char *pos;
1255 if (i + sizeof(fbuf) >= flength) {
1256 memset(fbuf, 0, sizeof(fbuf));
1257 }
1258 if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
1260 fclose(ff);
1261 return -1;
1262 }
1263 for (pos = fbuf; pos < fbuf + sizeof(fbuf); pos++) {
1265
1266 if (current_length == length) {
1267 length_offset = i + (pos - fbuf) + 1;
1268 break;
1269 }
1270 }
1271 if (length_offset >= 0) {
1272 break;
1273 }
1274 }
1275 if (length_offset < 0) {
1276
1277 ast_debug(3,
"Exceeds length of file? length=%" PRId64
", count=%" PRId64
", flength=%" PRId64
"\n", length, current_length, flength);
1278 length_offset = flength;
1279 }
1280 }
1281
1282
1283 if (length_offset - offset_offset == vlength + (strchr(
args.options,
'd') ? 0 : strlen(
format2term(newline_format)))) {
1284
1285 fseeko(ff, offset_offset, SEEK_SET);
1286 if (fwrite(
value, 1, vlength, ff) < vlength) {
1290 }
1291 fclose(ff);
1292 }
else if (length_offset - offset_offset > vlength + (strchr(
args.options,
'd') ? 0 : strlen(
format2term(newline_format)))) {
1293
1294 off_t cur;
1295 int64_t length_length = length_offset - offset_offset;
1296 size_t vlen = vlength + (strchr(
args.options,
'd') ? 0 : strlen(
format2term(newline_format)));
1297
1298 ast_debug(3,
"offset=%s/%" PRId64
", length=%s/%" PRId64
" (%" PRId64
"), vlength=%" PRId64
", flength=%" PRId64
"\n",
1299 args.offset, offset_offset,
args.length, length_offset, length_length, vlength, flength);
1300
1301 fseeko(ff, offset_offset, SEEK_SET);
1302 if (fwrite(
value, 1, vlength, ff) < vlength) {
1304 fclose(ff);
1305 return -1;
1306 }
else if (!strchr(
args.options,
'd') && fwrite(
format2term(newline_format), 1, vlen - vlength, ff) < vlen - vlength) {
1308 fclose(ff);
1309 return -1;
1310 }
1311 while ((cur = ftello(ff)) < flength) {
1312 if (cur < 0) {
1314 fclose(ff);
1315 return -1;
1316 }
1317 fseeko(ff, length_length - vlen, SEEK_CUR);
1318 if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
1320 fclose(ff);
1321 return -1;
1322 }
1323
1324 fseeko(ff, cur, SEEK_SET);
1325 if (fwrite(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf)) {
1327 fclose(ff);
1328 return -1;
1329 }
1330 }
1331 fclose(ff);
1332 if (truncate(
args.filename, flength - (length_length - vlen))) {
1334 }
1335 } else {
1336
1337 size_t vlen = vlength + (strchr(
args.options,
'd') ? 0 : strlen(
format2term(newline_format)));
1338 int64_t origlen = length_offset - offset_offset;
1339 off_t lastwritten = flength + vlen - origlen;
1340
1341 ast_debug(3,
"offset=%s/%" PRId64
", length=%s/%" PRId64
", vlength=%" PRId64
", flength=%" PRId64
"\n",
1342 args.offset, offset_offset,
args.length, length_offset, vlength, flength);
1343
1344 fseeko(ff, flength - sizeof(fbuf), SEEK_SET);
1345 while (offset_offset + sizeof(fbuf) < ftello(ff)) {
1346 if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf)) {
1348 fclose(ff);
1349 return -1;
1350 }
1351 fseeko(ff, sizeof(fbuf) - vlen - origlen, SEEK_CUR);
1352 if (fwrite(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf)) {
1354 fclose(ff);
1355 return -1;
1356 }
1357 if ((lastwritten = ftello(ff) - sizeof(fbuf)) < offset_offset + sizeof(fbuf)) {
1358 break;
1359 }
1360 fseeko(ff, 2 * sizeof(fbuf) + vlen - origlen, SEEK_CUR);
1361 }
1362 fseek(ff, length_offset, SEEK_SET);
1363 if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
1365 fclose(ff);
1366 return -1;
1367 }
1368 fseek(ff, offset_offset, SEEK_SET);
1369 if (fwrite(
value, 1, vlength, ff) < vlength) {
1371 fclose(ff);
1372 return -1;
1375 fclose(ff);
1376 return -1;
1377 } else {
1378 off_t curpos = ftello(ff);
1379 foplen = lastwritten - curpos;
1380 if (fwrite(fbuf, 1, foplen, ff) < foplen) {
1382 }
1383 }
1384 fclose(ff);
1385 }
1386 }
1387 }
1388
1389 return 0;
1390}
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.