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

ref: 6d04f117ff2c9817e2234397518c227a6855aaef CTU-FEE-B0B35APO-Semestral-project/file-browser/src/file_open.c -rw-r--r-- 3.4 KiB
6d04f117 — František Boháček feat: add stderr dialog for executing file 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