[io, osx] Reorganize to first compute flags/do checks etc., then enter next path element at a single callsite
This commit is contained in:
parent
d363c8b607
commit
ec53cd5416
|
@ -124,25 +124,21 @@ io_open_restrict_result io_open_restrict(io_file_desc dirFd, str8 path, file_acc
|
||||||
for_list(&pathElements.list, elt, str8_elt, listElt)
|
for_list(&pathElements.list, elt, str8_elt, listElt)
|
||||||
{
|
{
|
||||||
str8 name = elt->string;
|
str8 name = elt->string;
|
||||||
|
file_access_rights eltAccessRights = FILE_ACCESS_READ;
|
||||||
|
file_open_flags eltOpenFlags = 0;
|
||||||
|
|
||||||
/*TODO:
|
bool atLastElement = (&elt->listElt == list_last(&pathElements.list));
|
||||||
The last element should be treated a bit differently:
|
if(atLastElement)
|
||||||
|
|
||||||
- if it doesn't exists, and FILE_OPEN_CREATE is set, we can create it
|
|
||||||
- it must be opened with the correct flags
|
|
||||||
*/
|
|
||||||
|
|
||||||
if(!str8_cmp(name, STR8(".")))
|
|
||||||
{
|
{
|
||||||
if(&elt->listElt == list_last(&pathElements.list))
|
eltAccessRights = accessRights;
|
||||||
{
|
eltOpenFlags = openFlags;
|
||||||
//NOTE: if we're at the last element, re-enter current directory with correct flags
|
|
||||||
io_open_restrict_enter(&context, name, accessRights, openFlags);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if( !str8_cmp(name, STR8("."))
|
||||||
|
&& !atLastElement)
|
||||||
{
|
{
|
||||||
//NOTE: else we can just skip the element
|
//NOTE: if we're not at the last element we can just skip '.' elements
|
||||||
}
|
continue;
|
||||||
}
|
}
|
||||||
else if(!str8_cmp(name, STR8("..")))
|
else if(!str8_cmp(name, STR8("..")))
|
||||||
{
|
{
|
||||||
|
@ -158,28 +154,13 @@ io_open_restrict_result io_open_restrict(io_file_desc dirFd, str8 path, file_acc
|
||||||
context.error = IO_ERR_WALKOUT;
|
context.error = IO_ERR_WALKOUT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if(&elt->listElt == list_last(&pathElements.list))
|
|
||||||
{
|
|
||||||
//NOTE: if we're at the last element, enter parent directory with correct flags
|
|
||||||
io_open_restrict_enter(&context, name, accessRights, openFlags);
|
|
||||||
}
|
}
|
||||||
else
|
else if(!io_raw_file_exists_at(context.fd, name, FILE_OPEN_SYMLINK))
|
||||||
{
|
|
||||||
io_open_restrict_enter(&context, name, FILE_ACCESS_READ, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(!io_raw_file_exists_at(context.fd, name, FILE_OPEN_SYMLINK))
|
|
||||||
{
|
{
|
||||||
//NOTE: if the file doesn't exists, but we're at the last element and FILE_OPEN_CREATE
|
//NOTE: if the file doesn't exists, but we're at the last element and FILE_OPEN_CREATE
|
||||||
// is set, we create the file. Otherwise it is a IO_ERROR_NO_ENTRY error.
|
// is set, we create the file. Otherwise it is a IO_ERROR_NO_ENTRY error.
|
||||||
if( (&elt->listElt == list_last(&pathElements.list))
|
if( !atLastElement
|
||||||
&&(openFlags & FILE_OPEN_CREATE))
|
|| !(openFlags & FILE_OPEN_CREATE))
|
||||||
{
|
|
||||||
io_open_restrict_enter(&context, name, accessRights, openFlags);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
context.error = IO_ERR_NO_ENTRY;
|
context.error = IO_ERR_NO_ENTRY;
|
||||||
break;
|
break;
|
||||||
|
@ -195,17 +176,21 @@ io_open_restrict_result io_open_restrict(io_file_desc dirFd, str8 path, file_acc
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(status.type == MP_FILE_SYMLINK)
|
if(status.type == MP_FILE_REGULAR)
|
||||||
|
{
|
||||||
|
if(!atLastElement)
|
||||||
|
{
|
||||||
|
context.error = IO_ERR_NOT_DIR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(status.type == MP_FILE_SYMLINK)
|
||||||
{
|
{
|
||||||
//TODO - do we need a FILE_OPEN_NO_FOLLOW that fails if last element is a symlink?
|
//TODO - do we need a FILE_OPEN_NO_FOLLOW that fails if last element is a symlink?
|
||||||
// - do we need a FILE_OPEN_NO_SYMLINKS that fails if _any_ element is a symlink?
|
// - do we need a FILE_OPEN_NO_SYMLINKS that fails if _any_ element is a symlink?
|
||||||
|
|
||||||
if( (&elt->listElt == list_last(&pathElements.list))
|
if( !atLastElement
|
||||||
&&(openFlags & FILE_OPEN_SYMLINK))
|
|| !(openFlags & FILE_OPEN_SYMLINK))
|
||||||
{
|
|
||||||
io_open_restrict_enter(&context, name, accessRights, openFlags);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
io_raw_read_link_result link = io_raw_read_link_at(scratch.arena, context.fd, name);
|
io_raw_read_link_result link = io_raw_read_link_at(scratch.arena, context.fd, name);
|
||||||
if(link.error)
|
if(link.error)
|
||||||
|
@ -213,19 +198,16 @@ io_open_restrict_result io_open_restrict(io_file_desc dirFd, str8 path, file_acc
|
||||||
context.error = link.error;
|
context.error = link.error;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(path_is_absolute(link.target))
|
|
||||||
{
|
|
||||||
context.error = IO_ERR_WALKOUT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(link.target.len == 0)
|
if(link.target.len == 0)
|
||||||
{
|
{
|
||||||
//NOTE: treat an empty target as a '.'
|
//NOTE: treat an empty target as a '.'
|
||||||
link.target = STR8(".");
|
link.target = STR8(".");
|
||||||
}
|
}
|
||||||
|
else if(path_is_absolute(link.target))
|
||||||
|
{
|
||||||
|
context.error = IO_ERR_WALKOUT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
str8_list linkElements = str8_split(scratch.arena, link.target, sep);
|
str8_list linkElements = str8_split(scratch.arena, link.target, sep);
|
||||||
if(!list_empty(&linkElements.list))
|
if(!list_empty(&linkElements.list))
|
||||||
|
@ -239,49 +221,29 @@ io_open_restrict_result io_open_restrict(io_file_desc dirFd, str8 path, file_acc
|
||||||
pathElements.list.last = linkElements.list.last;
|
pathElements.list.last = linkElements.list.last;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
else if(status.type != MP_FILE_DIRECTORY)
|
||||||
else if(status.type == MP_FILE_DIRECTORY)
|
|
||||||
{
|
|
||||||
//NOTE: descend in directory
|
|
||||||
if(&elt->listElt == list_last(&pathElements.list))
|
|
||||||
{
|
|
||||||
io_open_restrict_enter(&context, name, accessRights, openFlags);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
io_open_restrict_enter(&context, name, FILE_ACCESS_READ, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(status.type == MP_FILE_REGULAR)
|
|
||||||
{
|
|
||||||
//NOTE: check that we're at the end of path and open that file
|
|
||||||
if(&elt->listElt != list_last(&pathElements.list))
|
|
||||||
{
|
{
|
||||||
context.error = IO_ERR_NOT_DIR;
|
context.error = IO_ERR_NOT_DIR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
io_open_restrict_enter(&context, name, accessRights, openFlags);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
context.error = IO_ERR_NO_ENTRY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(context.error)
|
//NOTE: if we arrive here, we have no errors and the correct flags are set,
|
||||||
|
// so we can enter the element
|
||||||
|
DEBUG_ASSERT(context.error == IO_OK);
|
||||||
|
io_open_restrict_enter(&context, name, eltAccessRights, eltOpenFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(context.error && !io_file_desc_is_nil(context.fd))
|
||||||
{
|
{
|
||||||
if(context.fd != context.rootFd)
|
if(context.fd != context.rootFd)
|
||||||
{
|
{
|
||||||
io_raw_close(context.fd);
|
io_raw_close(context.fd);
|
||||||
context.fd = io_file_desc_nil();
|
|
||||||
}
|
}
|
||||||
|
context.fd = io_file_desc_nil();
|
||||||
}
|
}
|
||||||
|
|
||||||
io_open_restrict_result result = {
|
io_open_restrict_result result = {
|
||||||
|
@ -306,7 +268,6 @@ io_cmp io_open_at(file_slot* atSlot, io_req* req, file_table* table)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
slot->fd = -1;
|
slot->fd = -1;
|
||||||
|
|
||||||
cmp.handle = file_handle_from_slot(table, slot);
|
cmp.handle = file_handle_from_slot(table, slot);
|
||||||
|
|
||||||
slot->rights = req->open.rights;
|
slot->rights = req->open.rights;
|
||||||
|
@ -325,32 +286,27 @@ io_cmp io_open_at(file_slot* atSlot, io_req* req, file_table* table)
|
||||||
str8 path = str8_from_buffer(req->size, req->buffer);
|
str8 path = str8_from_buffer(req->size, req->buffer);
|
||||||
|
|
||||||
io_file_desc dirFd = atSlot ? atSlot->fd : io_file_desc_nil();
|
io_file_desc dirFd = atSlot ? atSlot->fd : io_file_desc_nil();
|
||||||
slot->fd = -1;
|
|
||||||
|
|
||||||
if(req->open.flags & FILE_OPEN_RESTRICT)
|
if(req->open.flags & FILE_OPEN_RESTRICT)
|
||||||
{
|
{
|
||||||
io_open_restrict_result res = io_open_restrict(dirFd, path, slot->rights, req->open.flags);
|
io_open_restrict_result res = io_open_restrict(dirFd, path, slot->rights, req->open.flags);
|
||||||
if(res.error == IO_OK)
|
slot->error = res.error;
|
||||||
{
|
|
||||||
slot->fd = res.fd;
|
slot->fd = res.fd;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
slot->fatal = true;
|
|
||||||
slot->error = res.error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
slot->fd = io_raw_open_at(dirFd, path, slot->rights, req->open.flags);
|
slot->fd = io_raw_open_at(dirFd, path, slot->rights, req->open.flags);
|
||||||
if(slot->fd < 0)
|
if(io_file_desc_is_nil(slot->fd))
|
||||||
{
|
{
|
||||||
slot->fatal = true;
|
|
||||||
slot->error = io_raw_last_error();
|
slot->error = io_raw_last_error();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(slot->error)
|
||||||
|
{
|
||||||
|
slot->fatal = true;
|
||||||
cmp.error = slot->error;
|
cmp.error = slot->error;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return(cmp);
|
return(cmp);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue