filesdb-hash.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /*
  2. * dpkg - main program for package management
  3. * filesdb-hash.c - management of database of files installed on system
  4. *
  5. * Copyright © 2012-2014 Guillem Jover <guillem@debian.org>
  6. *
  7. * This is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  19. */
  20. #include <config.h>
  21. #include <compat.h>
  22. #include <sys/stat.h>
  23. #include <errno.h>
  24. #include <string.h>
  25. #include <stdio.h>
  26. #include <fcntl.h>
  27. #include <unistd.h>
  28. #include <dpkg/i18n.h>
  29. #include <dpkg/dpkg.h>
  30. #include <dpkg/dpkg-db.h>
  31. #include <dpkg/debug.h>
  32. #include <dpkg/fdio.h>
  33. #include <dpkg/dir.h>
  34. #include "filesdb.h"
  35. #include "infodb.h"
  36. /*
  37. * If mask is nonzero, will not write any file whose filenamenode
  38. * has any flag bits set in mask.
  39. */
  40. void
  41. write_filehash_except(struct pkginfo *pkg, struct pkgbin *pkgbin,
  42. struct fileinlist *list, enum filenamenode_flags mask)
  43. {
  44. struct atomic_file *file;
  45. const char *hashfile;
  46. debug(dbg_general, "generating infodb hashfile");
  47. if (pkg_infodb_has_file(pkg, &pkg->available, HASHFILE))
  48. return;
  49. hashfile = pkg_infodb_get_file(pkg, pkgbin, HASHFILE);
  50. file = atomic_file_new(hashfile, 0);
  51. atomic_file_open(file);
  52. for (; list; list = list->next) {
  53. struct filenamenode *namenode = list->namenode;
  54. if (mask && (namenode->flags & mask))
  55. continue;
  56. if (strcmp(namenode->newhash, EMPTYHASHFLAG) == 0)
  57. continue;
  58. fprintf(file->fp, "%s %s\n",
  59. namenode->newhash, namenode->name + 1);
  60. }
  61. atomic_file_sync(file);
  62. atomic_file_close(file);
  63. atomic_file_commit(file);
  64. atomic_file_free(file);
  65. dir_sync_path(pkg_infodb_get_dir());
  66. }
  67. static void
  68. parse_filehash_buffer(char *buf, char *buf_end,
  69. struct pkginfo *pkg, struct pkgbin *pkgbin)
  70. {
  71. char *thisline, *nextline;
  72. const char *pkgname = pkg_name(pkg, pnaw_nonambig);
  73. for (thisline = buf; thisline < buf_end; thisline = nextline) {
  74. struct filenamenode *namenode;
  75. char *endline, *hash_end, *filename;
  76. endline = memchr(thisline, '\n', buf_end - thisline);
  77. if (endline == NULL)
  78. ohshit(_("control file '%s' for package '%s' is "
  79. "missing final newline"), HASHFILE, pkgname);
  80. /* The md5sum hash has a constant length. */
  81. hash_end = thisline + MD5HASHLEN;
  82. filename = hash_end + 2;
  83. if (filename + 1 > endline)
  84. ohshit(_("control file '%s' for package '%s' is "
  85. "missing value"), HASHFILE, pkgname);
  86. if (hash_end[0] != ' ' || hash_end[1] != ' ')
  87. ohshit(_("control file '%s' for package '%s' is "
  88. "missing value separator"), HASHFILE, pkgname);
  89. hash_end[0] = '\0';
  90. /* Where to start next time around. */
  91. nextline = endline + 1;
  92. /* Strip trailing ‘/’. */
  93. if (endline > thisline && endline[-1] == '/')
  94. endline--;
  95. *endline = '\0';
  96. if (endline == thisline)
  97. ohshit(_("control file '%s' for package '%s' "
  98. "contains empty filename"), HASHFILE, pkgname);
  99. debug(dbg_eachfiledetail, "load hash '%s' for filename '%s'",
  100. thisline, filename);
  101. /* Add the file to the list. */
  102. namenode = findnamenode(filename, fnn_nocopy);
  103. namenode->newhash = thisline;
  104. }
  105. }
  106. void
  107. parse_filehash(struct pkginfo *pkg, struct pkgbin *pkgbin)
  108. {
  109. static int fd;
  110. const char *hashfile;
  111. struct stat st;
  112. hashfile = pkg_infodb_get_file(pkg, pkgbin, HASHFILE);
  113. fd = open(hashfile, O_RDONLY);
  114. if (fd < 0) {
  115. if (errno == ENOENT)
  116. return;
  117. ohshite(_("cannot open control file '%s' for package '%s'"),
  118. HASHFILE, pkg_name(pkg, pnaw_nonambig));
  119. }
  120. if (fstat(fd, &st) < 0)
  121. ohshite(_("cannot stat control file '%s' for package '%s'"),
  122. HASHFILE, pkg_name(pkg, pnaw_nonambig));
  123. if (!S_ISREG(st.st_mode))
  124. ohshit(_("control file '%s' for package '%s' is not a regular file"),
  125. HASHFILE, pkg_name(pkg, pnaw_nonambig));
  126. if (st.st_size > 0) {
  127. char *buf, *buf_end;
  128. buf = nfmalloc(st.st_size);
  129. buf_end = buf + st.st_size;
  130. if (fd_read(fd, buf, st.st_size) < 0)
  131. ohshite(_("cannot read control file '%s' for package '%s'"),
  132. HASHFILE, pkg_name(pkg, pnaw_nonambig));
  133. parse_filehash_buffer(buf, buf_end, pkg, pkgbin);
  134. }
  135. if (close(fd))
  136. ohshite(_("cannot close control file '%s' for package '%s'"),
  137. HASHFILE, pkg_name(pkg, pnaw_nonambig));
  138. }