db-convert-attachments-to-files 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. #!/usr/bin/perl -w
  2. use strict;
  3. use DBI;
  4. my $L1 = 10;
  5. my $L2 = 20;
  6. sub do_error($) {
  7. exit(1);
  8. }
  9. sub readable {
  10. my $size = shift;
  11. my @add = qw( B KB MB GB TB );
  12. my $i ;
  13. for ($i = 0; $i < 5;$i++) {
  14. if ( int($size / 1024) > 0 ) {
  15. $size = $size / 1024;
  16. } else {
  17. $size = 0.01*int(0.5+ $size/0.01) . " " . $add[$i];
  18. last;
  19. }
  20. }
  21. return $size;
  22. }
  23. if(scalar(@ARGV) < 4) {
  24. print "Usage: $0 <mysqluser> <mysqlpass> <mysqldb> <destination path> [delete]\n";
  25. printf" if [delete] is given, attachments will be removed from the database, to free storage\n";
  26. exit(1);
  27. }
  28. my ($user,$pass,$dbname,$basepath,$delete) = @ARGV;
  29. my $db = DBI->connect("dbi:mysql:$dbname", $user, $pass);
  30. my $res;
  31. my $sth;
  32. my $rows;
  33. my @row;
  34. if (!defined($db)) {
  35. print "did not connect to mysql\n";
  36. exit(1);
  37. }
  38. $res = $db->do("set character_set_client=utf8;");
  39. if(!$res) {
  40. do_error(1);
  41. }
  42. $res = $db->do("set character_set_connection=utf8;");
  43. if(!$res) {
  44. do_error(1);
  45. }
  46. $res = $db->do("set character_set_results=utf8;");
  47. if(!$res) {
  48. do_error(1);
  49. }
  50. $res = $db->do("begin;");
  51. if(!$res) {
  52. do_error(1);
  53. }
  54. $sth = $db->prepare("SHOW TABLE STATUS WHERE name = 'lob'");
  55. $sth->execute() || die $DBI::errstr;
  56. if ($sth->rows == 0) {
  57. print "Can't get attachment size.\n";
  58. exit(0);
  59. }
  60. @row = $sth->fetchrow_array();
  61. if (! defined ( $row[0] ) ) {
  62. print "Table status failed.\n";
  63. exit(0);
  64. }
  65. my $dbsize = $row[6];
  66. print "The size of all attachments in the database is: ". $dbsize." Bytes (". readable($dbsize) . ")\n";
  67. my $free = `df -P -B1 $basepath | tail -1 | awk '{print \$4}'`;
  68. chomp($free);
  69. print "Available space is: " . $free . " Bytes (" . readable($free) . ")\n";
  70. if ( $dbsize >= $free ) {
  71. print "Not enough space left on device.\n";
  72. exit(0);
  73. }
  74. print "Finding all attachments...\n";
  75. $sth = $db->prepare("SELECT distinct(instanceid) FROM lob");
  76. $sth->execute() || die $DBI::errstr;;
  77. if ($sth->rows == 0) {
  78. print "No attachments found.\n";
  79. exit(0);
  80. }
  81. print "Processing ".$sth->rows." attachments\n";
  82. while(@row = $sth->fetchrow_array()) {
  83. my @data;
  84. my $path = $basepath."/".($row[0] % $L1)."/".(($row[0] / $L1) % $L2);
  85. my $filename = $path."/".$row[0];
  86. system("mkdir -p ".$path) == 0 or die("Unable to create attachment directories");
  87. if ( -s $filename ) {
  88. next;
  89. }
  90. open(AFILE, ">".$filename) or die("Unable to open new attachment file");
  91. my $sth2 = $db->prepare("SELECT val_binary FROM lob WHERE instanceid=".$row[0]." ORDER BY chunkid");
  92. $res = $sth2->execute();
  93. if(!$res) {
  94. print " Unable to extract attachment ".$row[0]."\n";
  95. next;
  96. }
  97. while (@data = $sth2->fetchrow_array()) {
  98. print AFILE $data[0] or die("Not all data could be retrieved from attachment ".$row[0]);
  99. }
  100. close(AFILE);
  101. }
  102. print "Done.\n";
  103. if (defined($delete) && $delete) {
  104. print "Deleting attachments from database...\n";
  105. $sth = $db->prepare("DELETE FROM lob");
  106. $sth->execute() || die $DBI::errstr;
  107. print "Done.\n";
  108. }
  109. print "Remember to correct the ownership of the files for kopano to access, when Kopano is not running as root\n";
  110. $db->do("commit;");