Ext
 All Files Functions
write_to_file.h
Go to the documentation of this file.
1 
7 #ifndef EXT_FILESYSTEM_INTERFACE_WRITE_TO_FILE_H_
8 #define EXT_FILESYSTEM_INTERFACE_WRITE_TO_FILE_H_
9 
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <stdio.h>
13 #include <errno.h>
14 #include <string.h>
15 #include <fcntl.h>
16 #include "../core/superblock.h"
17 #include "../core/descriptors_table.h"
18 #include "../core/defines.h"
19 #include "../core/methods.h"
20 #include "utils.h"
21 #include "net_utils.h"
22 
32 void write_to_file(const char* path_to_fs_file,
33  uint16_t file_descriptor,
34  char* data,
35  uint32_t size, int output_fd) {
36  char* buffer = NULL;
37  size_t buffer_size = 0;
38  int fd = open(path_to_fs_file, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
39  if (fd == -1) {
40  fprintf(stderr, "Can't open file. Abort!\n");
41  exit(EXIT_FAILURE);
42  }
43 
44  struct superblock superblock;
45  read_super_block(fd, &superblock);
46  if (superblock.fs_info->magic != MAGIC) {
47  fprintf(stderr, "Magic does not match. Abort!\n");
48  destroy_super_block(&superblock);
49  close(fd);
50  exit(EXIT_FAILURE);
51  }
52 
53  if (!superblock.reserved_inodes_mask[ROOT_INODE_ID]) {
54  fprintf(stderr, "Root directory doesn't exist. Abort!\n");
55  destroy_super_block(&superblock);
56  close(fd);
57  exit(EXIT_FAILURE);
58  }
59 
60  if (size > get_max_data_size_of_all_blocks(&superblock)) {
61  size = get_max_data_size_of_all_blocks(&superblock);
62  }
63 
64  struct descriptors_table descriptors_table;
65  if (read_descriptors_table(fd, &descriptors_table, &superblock) == -1) {
66  fprintf(stderr, "Can't read descriptors_table. Abort!\n");
67  destroy_super_block(&superblock);
68  close(fd);
69  exit(EXIT_FAILURE);
70  }
71 
72  if (!descriptors_table.reserved_fd[file_descriptor]) {
73  buffered_write(&buffer, &buffer_size, "Trying to write to closed fd. Abort!\n", strlen("Trying to write to closed fd. Abort!\n"));
74  write_while(STDERR_FILENO, buffer, buffer_size);
75  send_data(output_fd, buffer, buffer_size);
76  free(buffer);
77  destruct_descriptors_table(&descriptors_table, &superblock);
78  destroy_super_block(&superblock);
79  close(fd);
80  return;
81  }
82 
83  uint32_t fd_position = descriptors_table.fd_to_position[file_descriptor];
84  uint16_t inode_id = descriptors_table.fd_to_inode[file_descriptor];
85 
86  struct inode inode;
87  if (read_inode(fd, &inode, inode_id, &superblock) == -1) {
88  fprintf(stderr, "Can't read inode. Abort!\n");
89  destruct_descriptors_table(&descriptors_table, &superblock);
90  destroy_super_block(&superblock);
91  close(fd);
92  exit(EXIT_FAILURE);
93  }
94 
95  uint32_t total_written = 0;
96  uint32_t need_to_write_size = size;
97  while (total_written != size) {
98  uint16_t block_to_write_pos =
99  (uint16_t) fd_position / get_max_data_in_block(&superblock);
100  struct block block;
101  if (block_to_write_pos < inode.inode_info->blocks_count) {
102  if (read_block(fd,
103  &block,
104  inode.block_ids[block_to_write_pos],
105  &superblock) == -1) {
106  fprintf(stderr, "Can't read block. Abort!\n");
107  destruct_descriptors_table(&descriptors_table, &superblock);
108  destroy_inode(&inode);
109  destroy_super_block(&superblock);
110  close(fd);
111  exit(EXIT_FAILURE);
112  }
113  } else {
114  uint16_t new_block_id = reserve_block(&superblock);
115  if (new_block_id == superblock.fs_info->blocks_count) {
116  buffered_write(&buffer, &buffer_size, "Can't create more blocks in FS. Abort!\n", strlen("Can't create more blocks in FS. Abort!\n"));
117  write_while(STDERR_FILENO, buffer, buffer_size);
118  send_data(output_fd, buffer, buffer_size);
119  free(buffer);
120 
121  descriptors_table.fd_to_position[file_descriptor] = fd_position;
122  if (write_descriptor_table(fd, &descriptors_table, &superblock) == -1) {
123  fprintf(stderr, "Can't write descriptor table. Abort!\n");
124  destruct_descriptors_table(&descriptors_table, &superblock);
125  destroy_inode(&inode);
126  destroy_super_block(&superblock);
127  close(fd);
128  exit(EXIT_FAILURE);
129  }
130  destruct_descriptors_table(&descriptors_table, &superblock);
131 
132  if (write_inode(fd, &inode, &superblock) == -1) {
133  fprintf(stderr, "Can't write inode. Abort!\n");
134  destroy_inode(&inode);
135  destroy_super_block(&superblock);
136  close(fd);
137  exit(EXIT_FAILURE);
138  }
139  destroy_inode(&inode);
140 
141  if (write_super_block(fd, &superblock) == -1) {
142  fprintf(stderr, "Can't write superblock. Abort!\n");
143  destroy_super_block(&superblock);
144  close(fd);
145  exit(EXIT_FAILURE);
146  }
147  destroy_super_block(&superblock);
148  close(fd);
149  break;
150  }
151 
152  if (inode.inode_info->blocks_count
153  == superblock.fs_info->blocks_count_in_inode) {
154  buffered_write(&buffer, &buffer_size, "Can't create more blocks in this inode. Abort!\n", strlen("Can't create more blocks in this inode. Abort!\n"));
155  write_while(STDERR_FILENO, buffer, buffer_size);
156  send_data(output_fd, buffer, buffer_size);
157  free(buffer);
158 
159  descriptors_table.fd_to_position[file_descriptor] = fd_position;
160  if (write_descriptor_table(fd, &descriptors_table, &superblock) == -1) {
161  fprintf(stderr, "Can't write descriptor table. Abort!\n");
162  destruct_descriptors_table(&descriptors_table, &superblock);
163  destroy_inode(&inode);
164  destroy_super_block(&superblock);
165  close(fd);
166  exit(EXIT_FAILURE);
167  }
168  destruct_descriptors_table(&descriptors_table, &superblock);
169 
170  if (write_inode(fd, &inode, &superblock) == -1) {
171  fprintf(stderr, "Can't write inode. Abort!\n");
172  destroy_inode(&inode);
173  destroy_super_block(&superblock);
174  close(fd);
175  exit(EXIT_FAILURE);
176  }
177  destroy_inode(&inode);
178 
179  if (write_super_block(fd, &superblock) == -1) {
180  fprintf(stderr, "Can't write superblock. Abort!\n");
181  destroy_super_block(&superblock);
182  close(fd);
183  exit(EXIT_FAILURE);
184  }
185  destroy_super_block(&superblock);
186  close(fd);
187  break;
188  }
189  init_block(&block, &superblock, new_block_id, inode_id);
190  block.data = (char*) calloc(superblock.fs_info->block_size, sizeof(char));
191  inode.block_ids[inode.inode_info->blocks_count] = new_block_id;
192  inode.inode_info->blocks_count += 1;
193  if (write_inode(fd, &inode, &superblock) == -1) {
194  fprintf(stderr, "Can't write inode. Abort!\n");
195  destruct_block(&block);
196  destroy_inode(&inode);
197  destroy_super_block(&superblock);
198  close(fd);
199  exit(EXIT_FAILURE);
200  }
201  }
202 
203  uint32_t position_in_block_data =
204  (uint32_t) fd_position % get_max_data_in_block(&superblock);
205  char* position_to_write = block.data + position_in_block_data;
206  uint32_t remain_size =
207  get_max_data_in_block(&superblock) - position_in_block_data;
208  uint32_t size_to_write = need_to_write_size < remain_size ? need_to_write_size : remain_size;
209  block.block_info->data_size = position_in_block_data;
210  memcpy(position_to_write, data, size_to_write);
211  block.block_info->data_size += size_to_write;
212  if (write_block(fd, &block, &superblock) == -1) {
213  fprintf(stderr, "Can't write block. Abort!\n");
214  destruct_block(&block);
215  destroy_inode(&inode);
216  destroy_super_block(&superblock);
217  close(fd);
218  exit(EXIT_FAILURE);
219  }
220  destruct_block(&block);
221 
222  fd_position += size_to_write;
223  data += size_to_write;
224  total_written += size_to_write;
225  need_to_write_size -= size_to_write;
226  }
227 
228  descriptors_table.fd_to_position[file_descriptor] = fd_position;
229  if (write_descriptor_table(fd, &descriptors_table, &superblock) == -1) {
230  fprintf(stderr, "Can't write descriptor table. Abort!\n");
231  destruct_descriptors_table(&descriptors_table, &superblock);
232  destroy_inode(&inode);
233  destroy_super_block(&superblock);
234  close(fd);
235  exit(EXIT_FAILURE);
236  }
237  destruct_descriptors_table(&descriptors_table, &superblock);
238 
239  if (write_inode(fd, &inode, &superblock) == -1) {
240  fprintf(stderr, "Can't write inode. Abort!\n");
241  destroy_inode(&inode);
242  destroy_super_block(&superblock);
243  close(fd);
244  exit(EXIT_FAILURE);
245  }
246  destroy_inode(&inode);
247 
248  if (write_super_block(fd, &superblock) == -1) {
249  fprintf(stderr, "Can't write superblock. Abort!\n");
250  destroy_super_block(&superblock);
251  close(fd);
252  exit(EXIT_FAILURE);
253  }
254  destroy_super_block(&superblock);
255  close(fd);
256 
257  char string_buffer[1024];
258  size_t string_size = sprintf(string_buffer, "Total written: %d\n", total_written);
259  buffered_write(&buffer, &buffer_size, string_buffer, strlen(string_buffer));
260  send_data(output_fd, buffer, buffer_size);
261  free(buffer);
262 }
263 
271 void write_to_file_from_file(const char* path_to_fs_file,
272  uint16_t file_descriptor, const char* path_to_file) {
273  ssize_t size = get_file_size(path_to_file);
274  if (size == -1) {
275  return;
276  }
277 
278  int descriptor = open(path_to_file, O_RDONLY);
279  if (descriptor == -1) {
280  fprintf(stderr, "Can't read file with data. Abort!\n");
281  return;
282  }
283 
284  char* buffer = (char*) calloc(size, sizeof(char));
285  size = read_while(descriptor, buffer, size);
286 
287  close(descriptor);
288 
289  if (size == -1) {
290  fprintf(stderr, "Can't read file with data. Abort!\n");
291  return;
292  }
293 
294  write_to_file(path_to_fs_file, file_descriptor, buffer, size, STDOUT_FILENO);
295 }
296 
297 #endif //EXT_FILESYSTEM_INTERFACE_WRITE_TO_FILE_H_
ssize_t write_descriptor_table(int fd, struct descriptors_table *descriptors_table, const struct superblock *superblock)
Write descriptors_table to memory.
ssize_t write_inode(int fd, struct inode *inode, const struct superblock *superblock)
Write inode from memory.
Definition: inode.c:83
void write_to_file_from_file(const char *path_to_fs_file, uint16_t file_descriptor, const char *path_to_file)
Write data to file Write data from path_to_file to file by file_descriptor.
ssize_t write_block(int fd, struct block *block, const struct superblock *superblock)
Write.
Definition: block.c:189
ssize_t write_super_block(int fd, struct superblock *superblock)
Write sb to memory.
Definition: superblock.c:85
void destroy_inode(struct inode *inode)
Destructor of inode.
Definition: inode.c:44
void destruct_descriptors_table(struct descriptors_table *descriptors_table, const struct superblock *superblock)
Destructor of superblock.
uint32_t get_max_data_size_of_all_blocks(const struct superblock *superblock)
Definition: block.c:250
void destroy_super_block(struct superblock *superblock)
Destructor of superblock.
Definition: superblock.c:41
ssize_t read_block(int fd, struct block *block, uint16_t block_id, const struct superblock *superblock)
Read block from memory.
Definition: block.c:133
ssize_t read_descriptors_table(int fd, struct descriptors_table *descriptors_table, const struct superblock *superblock)
Read descriptors_table from memory.
Contains some useful methods.
int read_while(int fd, char *buffer, size_t to_read)
Properly reading from memory.
Definition: utils.c:23
ssize_t read_super_block(int fd, struct superblock *superblock)
Read sb from memory.
Definition: superblock.c:47
int write_while(int fd, const char *buffer, size_t to_write)
Properly writing to memory.
Definition: utils.c:38
bool send_data(int sockd, char *data, size_t size)
Definition: net_utils.c:75
uint16_t reserve_block(const struct superblock *superblock)
Reserve block.
Definition: superblock.c:138
void destruct_block(struct block *block)
Destructor of block.
Definition: block.c:118
uint32_t get_max_data_in_block(const struct superblock *superblock)
Definition: block.c:246
ssize_t get_file_size(const char *path_to_file)
Get size of file.
Definition: utils.c:145
void write_to_file(const char *path_to_fs_file, uint16_t file_descriptor, char *data, uint32_t size, int output_fd)
Write data to file Write data from data to file by file_descriptor.
Definition: write_to_file.h:32
int buffered_write(char **buffer, size_t *buffer_size, char *data, size_t size)
Definition: utils.c:10
void init_block(struct block *block, const struct superblock *superblock, uint16_t block_id, uint16_t inode_id)
Constructor of block Init block and set its block_records array to nullptr.
Definition: block.c:94
ssize_t read_inode(int fd, struct inode *inode, uint16_t inode_id, const struct superblock *superblock)
Read inode from memory.
Definition: inode.c:49