~ruther/CTU-FEE-B0B35APO-Semestral-project

ref: 47ee5b137cd9ca1d308dd09c90e07cc96b2fe150 CTU-FEE-B0B35APO-Semestral-project/file-browser/src/file_open.c -rw-r--r-- 3.4 KiB
47ee5b13 — František Boháček fix: macro long types 3 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#include "file_open.h"
#include "file_access.h"
#include <linux/limits.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "nonblocking_io.h"
#include "serialize_lock.h"

static opened_file_state_t opened_file_create() {
  opened_file_state_t state = {
    .error = FILOPER_SUCCESS,
    .ended_with_error = false,
    .executed = false,
    .type = 0,
  };

  return state;
}

static void file_prepare_before_open() {
  serialize_unlock();
}

static void file_prepare_after_close() {
  struct termios old;
  file_set_nonblocking(STDIN_FILENO, &old);

  if (serialize_lock(1) <= 0) {
      serialize_lock(0);
  }
}

static opened_file_state_t file_execute(executing_file_t *executing, opened_type_t type) {
  executing_file_wait(executing);
  file_prepare_after_close();

  opened_file_state_t opened = opened_file_create();
  opened.type = type;
  opened.executed = true;
  opened.executing_file = *executing;
  opened.ended_with_error = executing->output_signal != 0;

  return opened;
}

static opened_file_state_t file_open_mime(file_t *file, exec_options_t *options,
                           fileaccess_state_t state, char *base_mime) {
  opened_file_state_t opened = opened_file_create();

  if (options == NULL) {
    return opened;
  }

  char mime[256];
  if (base_mime != NULL) {
    strcpy(mime, base_mime);
  } else {
    opened.error = fileaccess_file_get_mimetype(state, file, mime);

    if (opened.error != FILOPER_SUCCESS) {
      return opened;
    }
  }

  char *program = exec_options_get_program(options, mime);
  if (program == NULL) {
    return opened;
  }

  char local_path[PATH_MAX];
  opened.error =
      fileaccess_file_get_local_path(state, file, local_path);

  if (opened.error != FILOPER_SUCCESS) {
    return opened;
  }

  file_prepare_before_open();
  executing_file_error_t executing_or_error =
      executing_file_execute(program, local_path);

  if (executing_or_error.error != FILOPER_SUCCESS) {
    opened.error = executing_or_error.error;
    return opened;
  }

  return file_execute(&executing_or_error.file, base_mime != NULL ? OPENED_TEXT : OPENED_MIME);
}

static opened_file_state_t file_open_text(file_t *file, exec_options_t *options,
                           fileaccess_state_t state) {
  return file_open_mime(file, options, state, "text");
}

static opened_file_state_t file_open_executable(file_t *file, exec_options_t *options,
                                 fileaccess_state_t state) {
  opened_file_state_t opened = opened_file_create();
  
  if (file->permissions & S_IEXEC) {
    // executable
    file_prepare_before_open();
    executing_file_or_error_t executing_or_error =
        fileaccess_file_execute(state, file, "");
    if (executing_or_error.error) {
      opened.error = executing_or_error.error;
      return opened;
    }

    return file_execute(&executing_or_error.payload.file, OPENED_EXEC);
  }

  return opened;
}

opened_file_state_t file_open(file_t *file, exec_options_t *options, fileaccess_state_t state) {
  opened_file_state_t opened;

  // 1. try mime
  opened = file_open_mime(file, options, state, NULL);

  if (opened.executed || opened.error != FILOPER_SUCCESS) {
    return opened;
  }
  // 2. is executable? execute it
  opened = file_open_executable(file, options, state);

  if (opened.executed || opened.error != FILOPER_SUCCESS) {
    return opened;
  }
  // 3. text mime
  return file_open_text(file, options, state);
}
Do not follow this link