890{
897 );
899 off_t flength, vlength;
900 size_t foplen = 0;
901 FILE *ff;
902
904
906 sscanf(
args.offset,
"%" SCNd64, &offset);
907 }
909 sscanf(
args.length,
"%" SCNd64, &length);
910 }
911
912 vlength = strlen(
value);
913
914 if (
args.argc < 4 || !strchr(
args.options,
'l')) {
915
916
917 if (
args.argc > 3 && strchr(
args.options,
'a')) {
918
919 if (!(ff = fopen(
args.filename,
"a"))) {
921 return 0;
922 }
923 if (fwrite(
value, 1, vlength, ff) < vlength) {
925 }
926 fclose(ff);
927 return 0;
928 }
else if (offset == 0 && length ==
LLONG_MAX) {
929 if (!(ff = fopen(
args.filename,
"w"))) {
931 return 0;
932 }
933 if (fwrite(
value, 1, vlength, ff) < vlength) {
935 }
936 fclose(ff);
937 return 0;
938 }
939
940 if (!(ff = fopen(
args.filename,
"r+"))) {
942 return 0;
943 }
944 fseeko(ff, 0, SEEK_END);
945 flength = ftello(ff);
946
947 if (offset < 0) {
948 if (fseeko(ff, offset, SEEK_END)) {
950 fclose(ff);
951 return -1;
952 }
953 if ((offset = ftello(ff)) < 0) {
955 fclose(ff);
956 return -1;
957 }
958 }
959
960 if (length < 0) {
961 length = flength - offset + length;
962 if (length < 0) {
963 ast_log(
LOG_ERROR,
"Length '%s' exceeds the file length. No data will be written.\n",
args.length);
964 fclose(ff);
965 return -1;
966 }
967 }
968
969 fseeko(ff, offset, SEEK_SET);
970
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);
973
974 if (length == vlength) {
975
976 if (fwrite(
value, 1, vlength, ff) < vlength) {
978 }
979 fclose(ff);
981
982 if (fwrite(
value, 1, vlength, ff) < vlength) {
984 }
985 fclose(ff);
986 if (truncate(
args.filename, offset + vlength)) {
988 }
989 } else if (length > vlength) {
990
991 char fbuf[4096];
992 off_t cur;
993 if (fwrite(
value, 1, vlength, ff) < vlength) {
995 }
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)) {
1000 }
1001 fseeko(ff, cur + vlength - length, SEEK_SET);
1002 if (fwrite(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf)) {
1004 }
1005
1006 if (fseeko(ff, cur + sizeof(fbuf), SEEK_SET) < 0) {
1007
1008 break;
1009 }
1010 }
1011 fclose(ff);
1012 if (truncate(
args.filename, flength - (length - vlength))) {
1014 }
1015 } else {
1016
1017 char fbuf[4096];
1018 off_t lastwritten = flength + vlength - length;
1019
1020
1021 fseeko(ff, flength - sizeof(fbuf), SEEK_SET);
1022 while (offset < ftello(ff)) {
1023 if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf)) {
1025 fclose(ff);
1026 return -1;
1027 }
1028
1029
1030
1031 fseeko(ff, vlength - length - sizeof(fbuf), SEEK_CUR);
1032
1033
1034 lastwritten = ftello(ff);
1035
1036 if (fwrite(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf)) {
1038 fclose(ff);
1039 return -1;
1040 }
1041
1042 if (lastwritten < offset + sizeof(fbuf)) {
1043 break;
1044 }
1045
1046
1047
1048
1049
1050
1051 fseeko(ff, 2 * sizeof(fbuf) + vlength - length, SEEK_CUR);
1052 }
1053
1054
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));
1057 }
1058
1059
1060 ast_debug(1,
"Reading at %" PRId64
"\n", ftello(ff));
1061 if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
1063 }
1064 fseek(ff, offset, SEEK_SET);
1065
1066 if (fwrite(
value, 1, vlength, ff) < vlength) {
1068 } else {
1069 off_t curpos = ftello(ff);
1070 foplen = lastwritten - curpos;
1071 if (fwrite(fbuf, 1, foplen, ff) < foplen) {
1073 }
1074 }
1075 fclose(ff);
1076 }
1077 } else {
1079
1080
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') {
1088 }
1089 }
1092 return -1;
1093 }
1094
1095 if (strchr(
args.options,
'a')) {
1096
1097 if (!(ff = fopen(
args.filename,
"a"))) {
1099 return -1;
1100 }
1101 if (fwrite(
value, 1, vlength, ff) < vlength) {
1105 }
1106 fclose(ff);
1107 }
else if (offset == 0 && length ==
LLONG_MAX) {
1108
1109 off_t truncsize;
1110 if (!(ff = fopen(
args.filename,
"w"))) {
1112 return -1;
1113 }
1114 if (fwrite(
value, 1, vlength, ff) < vlength) {
1118 }
1119 if ((truncsize = ftello(ff)) < 0) {
1121 }
1122 fclose(ff);
1123 if (truncsize >= 0 && truncate(
args.filename, truncsize)) {
1125 return -1;
1126 }
1127 } else {
1128 int64_t offset_offset = (offset == 0 ? 0 : -1), length_offset = -1, flength, i, current_length = 0;
1129 char dos_state = 0, fbuf[4096];
1130
1131 if (offset < 0 && length < offset) {
1132
1133 ast_log(
LOG_ERROR,
"Length cannot specify a position prior to the offset\n");
1134 return -1;
1135 }
1136
1137 if (!(ff = fopen(
args.filename,
"r+"))) {
1139 return -1;
1140 }
1141
1142 if (fseek(ff, 0, SEEK_END)) {
1144 fclose(ff);
1145 return -1;
1146 }
1147 if ((flength = ftello(ff)) < 0) {
1149 fclose(ff);
1150 return -1;
1151 }
1152
1153
1154 if (offset < 0 || length < 0) {
1155 int64_t count = 0;
1156 for (i = (flength / sizeof(fbuf)) * sizeof(fbuf); i >= 0; i -= sizeof(fbuf)) {
1157 char *pos;
1158 if (fseeko(ff, i, SEEK_SET)) {
1160 }
1161 if (i + sizeof(fbuf) >= flength) {
1162 memset(fbuf, 0, sizeof(fbuf));
1163 }
1164 if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
1166 fclose(ff);
1167 return -1;
1168 }
1169 for (pos = fbuf + sizeof(fbuf) - 1; pos >= fbuf; pos--) {
1171
1172 if (length < 0 && count * -1 == length) {
1173 length_offset = i + (pos - fbuf);
1174 } else if (offset < 0 && count * -1 == (offset - 1)) {
1175
1176 if (newline_format ==
FF_DOS) {
1177 offset_offset = i + (pos - fbuf) + 2;
1178 } else {
1179 offset_offset = i + (pos - fbuf) + 1;
1180 }
1181 break;
1182 }
1183 }
1184 if ((offset < 0 && offset_offset >= 0) || (offset >= 0 && length_offset >= 0)) {
1185 break;
1186 }
1187 }
1188
1189 if (offset < 0 && offset_offset < 0 && offset == count * -1) {
1190 offset_offset = 0;
1191 }
1192 }
1193
1194
1195 if (offset > 0) {
1196 int64_t count = 0;
1197 fseek(ff, 0, SEEK_SET);
1198 for (i = 0; i < flength; i += sizeof(fbuf)) {
1199 char *pos;
1200 if (i + sizeof(fbuf) >= flength) {
1201 memset(fbuf, 0, sizeof(fbuf));
1202 }
1203 if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
1205 fclose(ff);
1206 return -1;
1207 }
1208 for (pos = fbuf; pos < fbuf + sizeof(fbuf); pos++) {
1210
1211 if (count == offset) {
1212 offset_offset = i + (pos - fbuf) + 1;
1213 break;
1214 }
1215 }
1216 if (offset_offset >= 0) {
1217 break;
1218 }
1219 }
1220 }
1221
1222 if (offset_offset < 0) {
1224 fclose(ff);
1225 return -1;
1226 }
1227
1228 if (length == 0) {
1229 length_offset = offset_offset;
1231 length_offset = flength;
1232 }
1233
1234
1235 if (length_offset < 0) {
1236 fseeko(ff, offset_offset, SEEK_SET);
1237 for (i = offset_offset; i < flength; i += sizeof(fbuf)) {
1238 char *pos;
1239 if (i + sizeof(fbuf) >= flength) {
1240 memset(fbuf, 0, sizeof(fbuf));
1241 }
1242 if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
1244 fclose(ff);
1245 return -1;
1246 }
1247 for (pos = fbuf; pos < fbuf + sizeof(fbuf); pos++) {
1249
1250 if (current_length == length) {
1251 length_offset = i + (pos - fbuf) + 1;
1252 break;
1253 }
1254 }
1255 if (length_offset >= 0) {
1256 break;
1257 }
1258 }
1259 if (length_offset < 0) {
1260
1261 ast_debug(3,
"Exceeds length of file? length=%" PRId64
", count=%" PRId64
", flength=%" PRId64
"\n", length, current_length, flength);
1262 length_offset = flength;
1263 }
1264 }
1265
1266
1267 if (length_offset - offset_offset == vlength + (strchr(
args.options,
'd') ? 0 : strlen(
format2term(newline_format)))) {
1268
1269 fseeko(ff, offset_offset, SEEK_SET);
1270 if (fwrite(
value, 1, vlength, ff) < vlength) {
1274 }
1275 fclose(ff);
1276 }
else if (length_offset - offset_offset > vlength + (strchr(
args.options,
'd') ? 0 : strlen(
format2term(newline_format)))) {
1277
1278 off_t cur;
1279 int64_t length_length = length_offset - offset_offset;
1280 size_t vlen = vlength + (strchr(
args.options,
'd') ? 0 : strlen(
format2term(newline_format)));
1281
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);
1284
1285 fseeko(ff, offset_offset, SEEK_SET);
1286 if (fwrite(
value, 1, vlength, ff) < vlength) {
1288 fclose(ff);
1289 return -1;
1290 }
else if (!strchr(
args.options,
'd') && fwrite(
format2term(newline_format), 1, vlen - vlength, ff) < vlen - vlength) {
1292 fclose(ff);
1293 return -1;
1294 }
1295 while ((cur = ftello(ff)) < flength) {
1296 if (cur < 0) {
1298 fclose(ff);
1299 return -1;
1300 }
1301 fseeko(ff, length_length - vlen, SEEK_CUR);
1302 if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
1304 fclose(ff);
1305 return -1;
1306 }
1307
1308 fseeko(ff, cur, SEEK_SET);
1309 if (fwrite(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf)) {
1311 fclose(ff);
1312 return -1;
1313 }
1314 }
1315 fclose(ff);
1316 if (truncate(
args.filename, flength - (length_length - vlen))) {
1318 }
1319 } else {
1320
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;
1324
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);
1327
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)) {
1332 fclose(ff);
1333 return -1;
1334 }
1335 fseeko(ff, sizeof(fbuf) - vlen - origlen, SEEK_CUR);
1336 if (fwrite(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf)) {
1338 fclose(ff);
1339 return -1;
1340 }
1341 if ((lastwritten = ftello(ff) - sizeof(fbuf)) < offset_offset + sizeof(fbuf)) {
1342 break;
1343 }
1344 fseeko(ff, 2 * sizeof(fbuf) + vlen - origlen, SEEK_CUR);
1345 }
1346 fseek(ff, length_offset, SEEK_SET);
1347 if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
1349 fclose(ff);
1350 return -1;
1351 }
1352 fseek(ff, offset_offset, SEEK_SET);
1353 if (fwrite(
value, 1, vlength, ff) < vlength) {
1355 fclose(ff);
1356 return -1;
1359 fclose(ff);
1360 return -1;
1361 } else {
1362 off_t curpos = ftello(ff);
1363 foplen = lastwritten - curpos;
1364 if (fwrite(fbuf, 1, foplen, ff) < foplen) {
1366 }
1367 }
1368 fclose(ff);
1369 }
1370 }
1371 }
1372
1373 return 0;
1374}
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.