utils.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <math.h>
  4. #include <stdbool.h>
  5. #include <ctype.h>
  6. #include <libavutil/avutil.h>
  7. #include "utils.h"
  8. #include "ffs.h"
  9. size_t strlcpy(char *dest, const char *src, size_t maxlen) {
  10. memset(dest, '\0', maxlen);
  11. int charnum;
  12. for(charnum = 0; charnum < maxlen && src[charnum] != '\0'; ++charnum) {
  13. dest[charnum] = src[charnum];
  14. }
  15. dest[maxlen - 1] = '\0';
  16. return(strlen(dest));
  17. }
  18. bool is_base10(const char* number_string) {
  19. size_t ndigits = strlen(number_string);
  20. int charnum;
  21. for(charnum = 0; charnum < ndigits && number_string[charnum] != '\0'; ++charnum) {
  22. if(!isdigit(number_string[charnum])) {
  23. return false;
  24. }
  25. }
  26. return true;
  27. }
  28. void itos10(char* dest, const int src) {
  29. /// An itoa-like wrapper to snprintf for converting integers to strings (base-10).
  30. ///
  31. /// The caller should make sure space has been allocated in dest.
  32. /// This function assumes dest has size at least equal to FFS_MAX_INT_LEN.
  33. memset(dest, '\0', FFS_MAX_INT_LEN);
  34. snprintf(dest, FFS_MAX_INT_LEN, "%d", src);
  35. dest[FFS_MAX_INT_LEN] = '\0';
  36. }
  37. AVCodecParameters* get_stream_codec_parameters(const int stream) {
  38. return(av_fmt_context->streams[stream]->codecpar);
  39. }
  40. int get_path_stream_id(const char* path) {
  41. if(strlen(path) < 2) {
  42. return -1;
  43. }
  44. char *filename = (char*)malloc(strlen(path));
  45. if(!filename) {
  46. fprintf(ffs_log, "Error allocating memory in %s.\n", __func__);
  47. stop_logging();
  48. exit(1);
  49. }
  50. strlcpy(filename, path + 1, strlen(path));
  51. char* filename_rem = filename;
  52. char* stream_base10 = strsep(&filename_rem, ".");
  53. if(!stream_base10) {
  54. return -1;
  55. }
  56. if(!is_base10(stream_base10)) {
  57. return -1;
  58. }
  59. int s = atoi(stream_base10);
  60. if(filename) {
  61. free(filename);
  62. filename = NULL;
  63. }
  64. return s;
  65. }
  66. void get_stream_codec_type(char* type_name, const int stream) {
  67. enum AVMediaType type_id = get_stream_codec_parameters(stream)->codec_type;
  68. strlcpy(type_name, av_get_media_type_string(type_id), FFS_MAX_TYPE_LEN);
  69. }
  70. void get_stream_codec_name(char* codec_name, const int stream) {
  71. enum AVCodecID cid = get_stream_codec_parameters(stream)->codec_id;
  72. strlcpy(codec_name, avcodec_get_name(cid), FFS_MAX_CODEC_LEN);
  73. }
  74. void build_stream_descriptor(char* codec, const int stream) {
  75. char* stream_base10 = (char*)malloc(FFS_MAX_INT_LEN);
  76. if(!stream_base10) goto descriptor_string_malloc_err;
  77. itos10(stream_base10, stream);
  78. char* codec_type = (char*)malloc(FFS_MAX_TYPE_LEN);
  79. if(!codec_type) goto descriptor_string_malloc_err;
  80. get_stream_codec_type(codec_type, stream);
  81. char* codec_name = (char*)malloc(FFS_MAX_CODEC_LEN);
  82. if(!codec_name) goto descriptor_string_malloc_err;
  83. get_stream_codec_name(codec_name, stream);
  84. snprintf(codec, FFS_MAX_DESCRIPTOR_LEN, "%s.%s.%s", stream_base10, codec_type, codec_name);
  85. codec[FFS_MAX_DESCRIPTOR_LEN] = '\0';
  86. if(stream_base10 != NULL) {
  87. free(stream_base10);
  88. stream_base10 = NULL;
  89. }
  90. if(codec_type != NULL) {
  91. free(codec_type);
  92. codec_type = NULL;
  93. }
  94. if(codec_name != NULL) {
  95. free(codec_name);
  96. codec_name = NULL;
  97. }
  98. return;
  99. descriptor_string_malloc_err:
  100. fprintf(ffs_log, "Memory allocation error in %s(..., stream = %d).\n", __func__, stream);
  101. stop_logging();
  102. exit(1);
  103. }
  104. bool valid_stream_descriptor(const char* path) {
  105. bool valid_stream_number = true;
  106. int s = get_path_stream_id(path);
  107. if(s < 0 || s >= av_fmt_context->nb_streams) {
  108. valid_stream_number = false;
  109. }
  110. char *filename_orig = (char*)malloc(strlen(path));
  111. if(!filename_orig) {
  112. fprintf(ffs_log, "Error allocating memory in %s.\n", __func__);
  113. stop_logging();
  114. exit(1);
  115. }
  116. strlcpy(filename_orig, path + 1, strlen(path));
  117. char* filename_rem = filename_orig;
  118. bool valid_codec_type = true;
  119. char* stream_base10 = strsep(&filename_rem, ".");
  120. char* path_codec_type = strsep(&filename_rem, ".");
  121. if(path_codec_type) {
  122. char* true_codec_type = (char*)malloc(FFS_MAX_TYPE_LEN);
  123. if(!true_codec_type) {
  124. fprintf(ffs_log, "Error allocating memory in %s.\n", __func__);
  125. stop_logging();
  126. exit(1);
  127. }
  128. get_stream_codec_type(true_codec_type, s);
  129. if(strncmp(path_codec_type, true_codec_type, FFS_MAX_TYPE_LEN) != 0) {
  130. valid_codec_type = false;
  131. }
  132. if(true_codec_type) {
  133. free(true_codec_type);
  134. true_codec_type = NULL;
  135. }
  136. } else {
  137. valid_codec_type = false;
  138. }
  139. bool valid_codec_name = true;
  140. char* path_codec_name = strsep(&filename_rem, ".");
  141. if(path_codec_name) {
  142. char* true_codec_name = (char*)malloc(FFS_MAX_CODEC_LEN);
  143. if(!true_codec_name) {
  144. fprintf(ffs_log, "Error allocating memory in %s.\n", __func__);
  145. stop_logging();
  146. exit(1);
  147. }
  148. get_stream_codec_name(true_codec_name, s);
  149. if(strncmp(path_codec_name, true_codec_name, FFS_MAX_CODEC_LEN) != 0) {
  150. valid_codec_name = false;
  151. }
  152. if(true_codec_name != NULL) {
  153. free(true_codec_name);
  154. true_codec_name = NULL;
  155. }
  156. } else {
  157. valid_codec_name = false;
  158. }
  159. if(filename_orig) {
  160. free(filename_orig);
  161. filename_orig = NULL;
  162. }
  163. return valid_stream_number && valid_codec_type && valid_codec_name;
  164. }
  165. bool valid_path(const char* path) {
  166. if (strcmp(path, "/") == 0) {
  167. return true;
  168. }
  169. char* trash_prefix = "/.Trash";
  170. if(strncmp(path, trash_prefix, strlen(trash_prefix)) == 0) {
  171. return true;
  172. }
  173. return valid_stream_descriptor(path);
  174. }