summaryrefslogtreecommitdiff
path: root/lib.c
blob: aa0ff0be8241ace1e15aa4c2c679b79429cdc392 (plain)
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
/*----------------------------------------------------------------------------*/
/*lib.h*/
/*----------------------------------------------------------------------------*/
/*Basic routines for filesystem manipulations*/
/*----------------------------------------------------------------------------*/
/*Based on the code of unionfs translator.*/
/*----------------------------------------------------------------------------*/
/*Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc.
  Written by Sergiu Ivanov <unlimitedscolobb@gmail.com>.

  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License as
  published by the Free Software Foundation; either version 2 of the
  License, or * (at your option) any later version.

  This program is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  USA.*/
/*----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------*/
#define _GNU_SOURCE 1
/*----------------------------------------------------------------------------*/
#include <sys/mman.h>
/*----------------------------------------------------------------------------*/
#include "lib.h"
#include "debug.h"
/*----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------*/
/*--------Functions-----------------------------------------------------------*/
/*Fetches directory entries for `dir`*/
error_t
dir_entries_get
	(
	file_t dir,
	char ** dirent_data,					/*the list of directory entries as returned
																	by dir_readdir*/
	size_t * dirent_data_size,		/*the size of `dirent_data`*/
	struct dirent *** dirent_list /*the array of pointers to beginnings of
																	dirents in dirent_data*/
	)
	{
	error_t err = 0;
	
	/*The data (array of dirents(?)) returned by dir_readdir*/
	char * data;
	
	/*The size of `data`*/
	size_t data_size;
	
	/*The number of entries in `data`*/
	int entries_num;
	
	/*Try to read the contents of the specified directory*/
	err = dir_readdir(dir, &data, &data_size, 0, -1, 0, &entries_num);
	if(err)
		return err;
		
	/*Create a new list of dirents*/
	struct dirent ** list;
	
	/*Allocate the memory for the list of dirents and for the
		finalizing element*/
	list = malloc(sizeof(struct dirent *) * (entries_num + 1));
	
	/*If memory allocation has failed*/
	if(!list)
		{
		/*free the result of dir_readdir*/
		munmap(data, data_size);
		
		/*return the corresponding error*/
		return ENOMEM;
		}
		
	/*The current directory entry*/
	struct dirent * dp;

	int i;
	
	/*Go through every element of the list of dirents*/
	for
		(
		i = 0, dp = (struct dirent *)data;
		i < entries_num;
		++i, dp = (struct dirent *)((char *)dp + dp->d_reclen))
		/*copy the current value into the list*/
		*(list + i) = dp;
	
	/*Nullify the last element of the list*/
	*(list + i) = NULL;
	
	/*Copy the required values in the parameters*/
	*dirent_data 			= data;
	*dirent_data_size	= data_size;
	*dirent_list 			= list;
	
	/*Return success*/
	return err;
	}/*dir_entries_get*/
/*----------------------------------------------------------------------------*/
/*Lookup `name` under `dir` (or cwd, if `dir` is invalid)*/
error_t
file_lookup
	(
	file_t dir,
	char * name,
	int flags0,					/*try to open with these flags first*/
	int flags1,					/*try to open with these flags, if `flags0` fail*/
	int mode,						/*if the file is to be created, create it with this mode*/
	file_t * port,			/*store the port to the looked up file here*/
	io_statbuf_t * stat	/*store the stat information here*/
	)
	{
	error_t err = 0;
	
	/*The port to the looked up file*/
	file_t p;
	
	/*The stat information about the looked up file*/
	io_statbuf_t s;
	
	/*Performs a lookup under 'dir' or in cwd, if `dir` is invalid*/
	file_t
	do_file_lookup
		(
		file_t dir,
		char * name,	/*lookup this file*/
		int flags,		/*lookup the file with these flags*/
		int mode			/*if a new file is to be created, create it with this mode*/
		)
		{
		/*The result of lookup*/
		file_t p;
	
		/*If `dir` is a valid port*/
		if(dir != MACH_PORT_NULL)
			/*try to lookup `name` under `dir`*/
			p = file_name_lookup_under(dir, name, flags, mode);
		else
			/*lookup `name` under current cwd*/
			p = file_name_lookup(name, flags, mode);
		
		/*Return the result of the lookup*/
		return p;
		}/*do_file_lookup*/
		
	/*Lookup `name` under the suggested `dir`*/
	p = do_file_lookup(dir, name, flags0, mode);
	
	/*If the lookup failed*/
	if(p == MACH_PORT_NULL)
		/*try to lookup for `name` using alternative flags `flags1`*/
		p = do_file_lookup(dir, name, flags1, mode);
	
	/*If the port is valid*/
	if(p != MACH_PORT_NULL)
		{
		/*If stat information is required*/
		if(stat)
			{
			/*obtain stat information for `p`*/
			err = io_stat(p, &s);
			if(err)
				PORT_DEALLOC(p);
			}
		}
	else
		/*copy `errno` into `err`*/
		err = errno;

	/*If no errors have happened during lookup*/
	if(!err)
		{
		/*copy the resulting port into *`port`*/
		*port = p;
		
		/*fill in the receiver for stat information, if requried*/
		if(stat)
			*stat = s;
		}
	
	/*Return the result of performing operations*/
	return err;
	}/*file_lookup*/
/*----------------------------------------------------------------------------*/