common.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. #include "common.h"
  3. #define BUFLEN 128
  4. int
  5. read_uint_from_file(char *dirname, char *filename, unsigned int *i)
  6. {
  7. FILE *f;
  8. char fname[BUFLEN];
  9. int ret = -1;
  10. snprintf(fname, sizeof(fname), "%s/%s", dirname, filename);
  11. f = fopen(fname, "r");
  12. if (!f)
  13. return ret;
  14. if (fscanf(f, "%u", i) == 1)
  15. ret = 0;
  16. fclose(f);
  17. return ret;
  18. }
  19. char
  20. *read_string_from_file(const char *dirname, const char *filename, char *buf, size_t bufsz)
  21. {
  22. FILE *f;
  23. char fname[BUFLEN];
  24. int i;
  25. snprintf(fname, sizeof(fname), "%s/%s", dirname, filename);
  26. f = fopen(fname, "r");
  27. if (!f)
  28. return NULL;
  29. if (fgets(buf, bufsz, f) == NULL) {
  30. fclose(f);
  31. return NULL;
  32. }
  33. fclose(f);
  34. /* make sure the string is \0 terminated */
  35. buf[bufsz - 1] = '\0';
  36. /* remove trailing whitespace */
  37. i = strlen(buf) - 1;
  38. while (i > 0 && buf[i] <= ' ')
  39. buf[i--] = '\0';
  40. return buf;
  41. }
  42. int block_file_identify(FILE *f, uint64_t offset)
  43. {
  44. uint32_t magic = 0;
  45. size_t n;
  46. if (fseeko(f, offset, SEEK_SET) < 0)
  47. return -1;
  48. n = fread(&magic, sizeof(magic), 1, f);
  49. if (magic == cpu_to_le32(0x88b1f))
  50. return FS_TARGZ;
  51. if (magic == cpu_to_be32(0xdeadc0de))
  52. return FS_DEADCODE;
  53. if (fseeko(f, offset + 0x400, SEEK_SET) < 0)
  54. return -1;
  55. n = fread(&magic, sizeof(magic), 1, f);
  56. if (n != 1)
  57. return -1;
  58. if (magic == cpu_to_le32(0xF2F52010))
  59. return FS_F2FS;
  60. magic = 0;
  61. if (fseeko(f, offset + 0x438, SEEK_SET) < 0)
  62. return -1;
  63. n = fread(&magic, sizeof(magic), 1, f);
  64. if (n != 1)
  65. return -1;
  66. if ((le32_to_cpu(magic) & 0xffff) == 0xef53)
  67. return FS_EXT4;
  68. return FS_NONE;
  69. }
  70. static bool use_f2fs(struct volume *v, uint64_t offset, const char *bdev)
  71. {
  72. uint64_t size = 0;
  73. bool ret = false;
  74. int fd;
  75. fd = open(bdev, O_RDONLY);
  76. if (fd < 0)
  77. return false;
  78. if (ioctl(fd, BLKGETSIZE64, &size) == 0)
  79. ret = size - offset > F2FS_MINSIZE;
  80. close(fd);
  81. return ret;
  82. }
  83. int block_volume_format(struct volume *v, uint64_t offset, const char *bdev)
  84. {
  85. int ret = 0;
  86. char str[128];
  87. unsigned int skip_blocks = 0;
  88. int fd;
  89. __u32 deadc0de;
  90. size_t sz;
  91. switch (volume_identify(v)) {
  92. case FS_DEADCODE:
  93. /* skip padding */
  94. fd = open(v->blk, O_RDONLY);
  95. if (fd < 0) {
  96. ret = EIO;
  97. break;
  98. }
  99. do {
  100. if (lseek(fd, (skip_blocks + 1) * 512, SEEK_SET) == (off_t) -1) {
  101. ret = EIO;
  102. break;
  103. }
  104. sz = read(fd, &deadc0de, sizeof(deadc0de));
  105. if (sz != sizeof(deadc0de)) {
  106. ret = EIO;
  107. break;
  108. }
  109. } while(++skip_blocks <= 512 &&
  110. (deadc0de == cpu_to_be32(0xdeadc0de) || deadc0de == 0xffffffff));
  111. close(fd);
  112. if (ret)
  113. break;
  114. /* only try extracting in case gzip header is present */
  115. if (deadc0de != cpu_to_le32(0x88b1f))
  116. goto do_format;
  117. /* fall-through */
  118. case FS_TARGZ:
  119. snprintf(str, sizeof(str),
  120. "dd if=%s bs=512 skip=%u 2>/dev/null | gzip -cd > /tmp/sysupgrade.tar 2>/dev/null",
  121. v->blk, skip_blocks);
  122. ret = system(str);
  123. if (ret < 0) {
  124. ULOG_ERR("failed extracting config backup from %s\n", v->blk);
  125. break;
  126. }
  127. /* fall-through */
  128. case FS_NONE:
  129. do_format:
  130. ULOG_INFO("overlay filesystem in %s has not been formatted yet\n", v->blk);
  131. if (use_f2fs(v, offset, bdev))
  132. snprintf(str, sizeof(str), "mkfs.f2fs -q -f -l rootfs_data %s", v->blk);
  133. else
  134. snprintf(str, sizeof(str), "mkfs.ext4 -q -F -L rootfs_data %s", v->blk);
  135. ret = system(str);
  136. break;
  137. default:
  138. break;
  139. }
  140. return ret;
  141. }