A static site generator, written in C
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

cms_build.c 4.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. #include <sys/stat.h>
  2. #include <sys/types.h>
  3. #include <fcntl.h>
  4. #include <unistd.h>
  5. #include <dirent.h>
  6. #include <errno.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include "cms_build.h"
  10. #include "cms_template.h"
  11. #include "cms_err.h"
  12. #include "cms_files.h"
  13. #include "cms_util.h"
  14. #include "cms_page.h"
  15. #include "cms_post.h"
  16. #include <stdio.h>
  17. static char* make_post(cms_page* parent, cms_post post, char* rootpath)
  18. {
  19. char* fstr;
  20. char* fname;
  21. cms_template_args* args;
  22. cms_err* err;
  23. char* str;
  24. //Template index.html
  25. fname = cms_util_path_join(rootpath, CMS_FILE_THEME "/html/index.html");
  26. if (fname == NULL) return NULL;
  27. fstr = cms_util_file_read(fname);
  28. if (fstr == NULL) return NULL;
  29. args = cms_template_args_create();
  30. err = cms_template_args_append(args, "articles", post.html);
  31. if (err) return NULL;
  32. str = cms_templateify(fstr, args);
  33. if (str == NULL) return NULL;
  34. free(fstr);
  35. free(fname);
  36. free(args);
  37. free(err);
  38. return str;
  39. }
  40. cms_err* cms_build_write_files(cms_page* root, char* path, char* rootpath)
  41. {
  42. printf(
  43. "page: '%s', n posts: %i, n subs: %i\n",
  44. root->title,
  45. (int)root->numposts,
  46. (int)root->numsubs
  47. );
  48. char* dirpath = cms_util_path_join(path, root->slug);
  49. if (dirpath == NULL)
  50. return cms_err_create(CMS_ERR_ALLOC, NULL);
  51. if (mkdir(dirpath, 0777) == -1 && errno != EEXIST)
  52. return cms_err_from_std_err(errno, dirpath);
  53. //Go through each post in the page, writing it to disk
  54. size_t i;
  55. for (i = 0; i < (root->numposts); ++i)
  56. {
  57. cms_post post = root->posts[i];
  58. char* postdirpath = cms_util_path_join(dirpath, post.slug);
  59. if (postdirpath == NULL)
  60. return cms_err_create(CMS_ERR_ALLOC, NULL);
  61. if (mkdir(postdirpath, 0777) == -1 && errno != EEXIST)
  62. return cms_err_from_std_err(errno, postdirpath);
  63. char* filepath = cms_util_path_join(postdirpath, CMS_FILE_INDEX);
  64. if (postdirpath == NULL)
  65. return cms_err_create(CMS_ERR_ALLOC, NULL);
  66. int file = open(filepath, O_WRONLY | O_CREAT | O_TRUNC, 0777);
  67. if (file == -1)
  68. return cms_err_from_std_err(errno, NULL);
  69. //Create the HTML for the post
  70. char* html = make_post(root, post, rootpath);
  71. if (html == NULL)
  72. return cms_err_create(CMS_ERR_ALLOC, NULL);
  73. //Write post's HTML file
  74. ssize_t nbytes = write(file, html, strlen(html));
  75. if (nbytes == -1)
  76. return cms_err_from_std_err(errno, NULL);
  77. close(file);
  78. free(filepath);
  79. free(postdirpath);
  80. }
  81. //Go through each sub in the page recursively
  82. for (i = 0; i < root->numsubs; ++i)
  83. {
  84. cms_page sub = root->subs[i];
  85. char* subdirpath = cms_util_path_join(dirpath, sub.slug);
  86. if (subdirpath == NULL)
  87. return cms_err_create(CMS_ERR_ALLOC, NULL);
  88. if (mkdir(subdirpath, 0777) == -1 && errno != EEXIST)
  89. return cms_err_from_std_err(errno, subdirpath);
  90. cms_err* err = cms_build_write_files(&sub, subdirpath, rootpath);
  91. if (err)
  92. return err;
  93. free(subdirpath);
  94. }
  95. free(dirpath);
  96. return cms_err_create(CMS_ERR_NONE, NULL);
  97. }
  98. cms_err* cms_build_make_tree(cms_page* root, char* path, char* dirname)
  99. {
  100. struct dirent** namelist;
  101. int n = scandir(path, &namelist, 0, alphasort);
  102. if (n == -1)
  103. return cms_err_from_std_err(errno, NULL);
  104. struct dirent* ep;
  105. struct stat* st = malloc(sizeof(struct stat));
  106. if (st == NULL)
  107. return cms_err_create(CMS_ERR_ALLOC, NULL);
  108. for (int i = 0; i < n; ++i)
  109. {
  110. ep = namelist[i];
  111. if (ep->d_name[0] == '.')
  112. continue;
  113. char* entpath = cms_util_path_join(path, ep->d_name);
  114. stat(entpath, st);
  115. //Entry is directory, recurse
  116. if (S_ISDIR(st->st_mode))
  117. {
  118. cms_page* sub = cms_page_create();
  119. if (sub == NULL)
  120. return cms_err_create(CMS_ERR_ALLOC, NULL);
  121. cms_err* err;
  122. err = cms_build_make_tree(sub, entpath, ep->d_name);
  123. if (err)
  124. return err;
  125. err = cms_page_add_sub(root, sub);
  126. if (err)
  127. return err;
  128. }
  129. //Entry is the file which contains metadata
  130. //about a page, parse
  131. else if (strcmp(ep->d_name, CMS_FILE_PAGE) == 0)
  132. {
  133. char* content = cms_util_file_read(entpath);
  134. if (content == NULL)
  135. return cms_err_create(CMS_ERR_FILEREAD, entpath);
  136. cms_err* err = cms_page_parse(root, content, dirname);
  137. free(content);
  138. if (err)
  139. return err;
  140. }
  141. //Entry is a post, read it and add to page
  142. else
  143. {
  144. cms_post* post = cms_post_create();
  145. char* content = cms_util_file_read(entpath);
  146. if (content == NULL)
  147. return cms_err_create(CMS_ERR_FILEREAD, entpath);
  148. cms_err* err;
  149. err = cms_post_parse(post, content, ep->d_name);
  150. free(content);
  151. if (err)
  152. return err;
  153. err = cms_page_add_post(root, post);
  154. if (err)
  155. return err;
  156. }
  157. free(entpath);
  158. }
  159. free(st);
  160. free(namelist);
  161. return cms_err_create(CMS_ERR_NONE, NULL);
  162. }