static rtems_filesystem_location_info_t * eval_path_start( rtems_filesystem_eval_path_context_t *ctx, const char *path, size_t pathlen, int eval_flags, rtems_filesystem_global_location_t *const *global_root_ptr, rtems_filesystem_global_location_t *const *global_current_ptr ) { memset(ctx, 0, sizeof(*ctx)); ctx->path = path; ctx->pathlen = pathlen; ctx->flags = eval_flags; set_startloc(ctx, global_root_ptr, global_current_ptr); rtems_filesystem_instance_lock(&ctx->startloc->location); rtems_filesystem_location_clone( &ctx->currentloc, &ctx->startloc->location ); rtems_filesystem_eval_path_continue(ctx); return &ctx->currentloc; }
static int duplicate_iop( rtems_libio_t *iop ) { int rv = 0; rtems_libio_t *diop = rtems_libio_allocate(); if (diop != NULL) { int oflag = rtems_libio_to_fcntl_flags( iop->flags ); oflag &= ~O_CREAT; diop->flags |= rtems_libio_fcntl_flags( oflag ); rtems_filesystem_instance_lock( &iop->pathinfo ); rtems_filesystem_location_clone( &diop->pathinfo, &iop->pathinfo ); rtems_filesystem_instance_unlock( &iop->pathinfo ); /* * XXX: We call the open handler here to have a proper open and close pair. * * FIXME: What to do with the path? */ rv = (*diop->pathinfo.handlers->open_h)( diop, NULL, oflag, 0 ); if ( rv == 0 ) { rv = rtems_libio_iop_to_descriptor( diop ); } else { rtems_libio_free( diop ); } } else { rv = -1; } return rv; }
void rtems_filesystem_eval_path_restart( rtems_filesystem_eval_path_context_t *ctx, rtems_filesystem_global_location_t **newstartloc_ptr ) { free_location(&ctx->currentloc); rtems_filesystem_instance_unlock(&ctx->startloc->location); rtems_filesystem_global_location_assign( &ctx->startloc, rtems_filesystem_global_location_obtain(newstartloc_ptr) ); rtems_filesystem_instance_lock(&ctx->startloc->location); rtems_filesystem_location_clone(&ctx->currentloc, &ctx->startloc->location); }
rtems_filesystem_location_info_t * rtems_filesystem_eval_path_start_with_parent( rtems_filesystem_eval_path_context_t *ctx, const char *path, int eval_flags, rtems_filesystem_location_info_t *parentloc, int parent_eval_flags ) { size_t pathlen = strlen(path); const char *parentpath = path; size_t parentpathlen = get_parentpathlen(path, pathlen); const char *name = NULL; size_t namelen = 0; const rtems_filesystem_location_info_t *currentloc = NULL; if (pathlen > 0) { if (parentpathlen == 0) { parentpath = "."; parentpathlen = 1; name = path; namelen = pathlen; } else { name = path + parentpathlen; namelen = pathlen - parentpathlen; } } currentloc = eval_path_start( ctx, parentpath, parentpathlen, parent_eval_flags, &rtems_filesystem_root, &rtems_filesystem_current ); rtems_filesystem_location_clone(parentloc, currentloc); ctx->path = name; ctx->pathlen = namelen; ctx->flags = eval_flags; rtems_filesystem_eval_path_continue(ctx); return &ctx->currentloc; }
int fchdir( int fd ) { int rv = 0; rtems_libio_t *iop; struct stat st; rtems_filesystem_location_info_t loc; st.st_mode = 0; st.st_uid = 0; st.st_gid = 0; rtems_libio_check_fd( fd ); iop = rtems_libio_iop( fd ); rtems_libio_check_is_open( iop ); rtems_filesystem_instance_lock( &iop->pathinfo ); rv = (*iop->pathinfo.handlers->fstat_h)( &iop->pathinfo, &st ); if ( rv == 0 ) { bool access_ok = rtems_filesystem_check_access( RTEMS_FS_PERMS_EXEC, st.st_mode, st.st_uid, st.st_gid ); if ( access_ok ) { rtems_filesystem_location_clone( &loc, &iop->pathinfo ); } else { errno = EACCES; rv = -1; } } rtems_filesystem_instance_unlock( &iop->pathinfo ); if ( rv == 0 ) { rv = rtems_filesystem_chdir( &loc ); } return rv; }
static int duplicate2_iop( rtems_libio_t *iop, int fd2 ) { rtems_libio_t *iop2; int rv = 0; rtems_libio_check_fd( fd2 ); iop2 = rtems_libio_iop( fd2 ); if (iop != iop2) { int oflag; if ((iop2->flags & LIBIO_FLAGS_OPEN) != 0) { rv = (*iop2->pathinfo.handlers->close_h)( iop2 ); } if (rv == 0) { oflag = rtems_libio_to_fcntl_flags( iop->flags ); oflag &= ~O_CREAT; iop2->flags |= rtems_libio_fcntl_flags( oflag ); rtems_filesystem_instance_lock( &iop->pathinfo ); rtems_filesystem_location_clone( &iop2->pathinfo, &iop->pathinfo ); rtems_filesystem_instance_unlock( &iop->pathinfo ); /* * XXX: We call the open handler here to have a proper open and close * pair. * * FIXME: What to do with the path? */ rv = (*iop2->pathinfo.handlers->open_h)( iop2, NULL, oflag, 0 ); if ( rv == 0 ) { rv = fd2; } } } return rv; }
int rtems_tarfs_load( const char *mountpoint, uint8_t *tar_image, size_t tar_size ) { const char *hdr_ptr; char filename[100]; char full_filename[256]; int hdr_chksum; unsigned char linkflag; unsigned long file_size; unsigned long file_mode; int offset; unsigned long nblocks; int rv = 0; int eval_flags = RTEMS_FS_FOLLOW_LINK; rtems_filesystem_eval_path_context_t ctx; rtems_filesystem_location_info_t rootloc; rtems_filesystem_location_info_t *currentloc = rtems_filesystem_eval_path_start( &ctx, mountpoint, eval_flags ); rtems_filesystem_eval_path_extract_currentloc( &ctx, &rootloc ); rtems_filesystem_eval_path_set_flags( &ctx, RTEMS_FS_MAKE | RTEMS_FS_EXCLUSIVE ); if ( !IMFS_is_imfs_instance( &rootloc ) ) { rv = -1; } /* * Create an IMFS node structure pointing to tar image memory. */ offset = 0; while ( rv == 0 ) { if (offset + 512 > tar_size) break; /* * Read a header. */ hdr_ptr = (char *) &tar_image[offset]; offset += 512; if (strncmp(&hdr_ptr[257], "ustar", 5)) break; strncpy(filename, hdr_ptr, MAX_NAME_FIELD_SIZE); filename[MAX_NAME_FIELD_SIZE] = '\0'; linkflag = hdr_ptr[156]; file_mode = _rtems_octal2ulong(&hdr_ptr[100], 8); file_size = _rtems_octal2ulong(&hdr_ptr[124], 12); hdr_chksum = _rtems_octal2ulong(&hdr_ptr[148], 8); if (_rtems_tar_header_checksum(hdr_ptr) != hdr_chksum) break; /* * Generate an IMFS node depending on the file type. * - For directories, just create directories as usual. IMFS * will take care of the rest. * - For symbolic links, create as usual * - For files, create a file node with special tarfs properties. */ if (linkflag == DIRTYPE) { int len; strncpy(full_filename, mountpoint, 255); if (full_filename[(len=strlen(full_filename))-1] != '/') strcat(full_filename, "/"); ++len; strncat(full_filename, filename, 256-len-1); if ( mkdir(full_filename, S_IRWXU | S_IRWXG | S_IRWXO) != 0 ) { if (errno == EEXIST) { struct stat stat_buf; if ( stat(full_filename, &stat_buf) == 0 ) { if ( S_ISDIR(stat_buf.st_mode) ) { continue; } else { if ( unlink(full_filename) != -1 ) { if ( mkdir(full_filename, S_IRWXU | S_IRWXG | S_IRWXO) == 0 ) continue; } } } } rv = -1; } } /* * Create a LINEAR_FILE node */ else if (linkflag == REGTYPE) { rtems_filesystem_location_free( currentloc ); rtems_filesystem_location_clone( currentloc, &rootloc ); rtems_filesystem_eval_path_set_path( &ctx, filename, strlen( filename ) ); rtems_filesystem_eval_path_continue( &ctx ); if ( !rtems_filesystem_location_is_null( currentloc ) ) { IMFS_linearfile_t *linfile = (IMFS_linearfile_t *) IMFS_create_node( currentloc, &IMFS_node_control_linfile, sizeof( IMFS_file_t ), rtems_filesystem_eval_path_get_token( &ctx ), rtems_filesystem_eval_path_get_tokenlen( &ctx ), (file_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFREG, NULL ); if ( linfile != NULL ) { linfile->File.size = file_size; linfile->direct = &tar_image[offset]; } } nblocks = (((file_size) + 511) & ~511) / 512; offset += 512 * nblocks; } /* * Create a symbolic link */ else if (linkflag == SYMTYPE) { const char *linkto = hdr_ptr + 157; int len; strncpy(full_filename, mountpoint, 255); if (full_filename[(len=strlen(full_filename))-1] != '/') strcat(full_filename, "/"); ++len; strncat(full_filename, filename, 256-len-1); rv = symlink(linkto, full_filename); } } rtems_filesystem_location_free( &rootloc ); rtems_filesystem_eval_path_cleanup( &ctx ); return rv; }
int rtems_tarfs_load( const char *mountpoint, uint8_t *tar_image, size_t tar_size ) { const char *hdr_ptr; char filename[100]; char full_filename[256]; int hdr_chksum; unsigned char linkflag; unsigned long file_size; unsigned long file_mode; int offset; unsigned long nblocks; IMFS_jnode_t *node; int rv = 0; int eval_flags = RTEMS_FS_FOLLOW_LINK; rtems_filesystem_eval_path_context_t ctx; rtems_filesystem_location_info_t rootloc; rtems_filesystem_location_info_t *currentloc = rtems_filesystem_eval_path_start( &ctx, mountpoint, eval_flags ); rtems_filesystem_eval_path_extract_currentloc( &ctx, &rootloc ); rtems_filesystem_eval_path_set_flags( &ctx, RTEMS_FS_MAKE | RTEMS_FS_EXCLUSIVE ); if ( rootloc.mt_entry->ops != &IMFS_ops && rootloc.mt_entry->ops != &fifoIMFS_ops ) { rv = -1; } /* * Create an IMFS node structure pointing to tar image memory. */ offset = 0; while ( rv == 0 ) { if (offset + 512 > tar_size) break; /* * Read a header. */ hdr_ptr = (char *) &tar_image[offset]; offset += 512; if (strncmp(&hdr_ptr[257], "ustar", 5)) break; strncpy(filename, hdr_ptr, MAX_NAME_FIELD_SIZE); filename[MAX_NAME_FIELD_SIZE] = '\0'; linkflag = hdr_ptr[156]; file_mode = _rtems_octal2ulong(&hdr_ptr[100], 8); file_size = _rtems_octal2ulong(&hdr_ptr[124], 12); hdr_chksum = _rtems_octal2ulong(&hdr_ptr[148], 8); if (_rtems_tar_header_checksum(hdr_ptr) != hdr_chksum) break; /* * Generate an IMFS node depending on the file type. * - For directories, just create directories as usual. IMFS * will take care of the rest. * - For files, create a file node with special tarfs properties. */ if (linkflag == DIRTYPE) { strcpy(full_filename, mountpoint); if (full_filename[strlen(full_filename)-1] != '/') strcat(full_filename, "/"); strcat(full_filename, filename); mkdir(full_filename, S_IRWXU | S_IRWXG | S_IRWXO); } /* * Create a LINEAR_FILE node */ else if (linkflag == REGTYPE) { rtems_filesystem_location_free( currentloc ); rtems_filesystem_location_clone( currentloc, &rootloc ); rtems_filesystem_eval_path_set_path( &ctx, filename, strlen( filename ) ); rtems_filesystem_eval_path_continue( &ctx ); if ( !rtems_filesystem_location_is_null( currentloc ) ) { node = IMFS_create_node( currentloc, IMFS_LINEAR_FILE, rtems_filesystem_eval_path_get_token( &ctx ), rtems_filesystem_eval_path_get_tokenlen( &ctx ), (file_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFREG, NULL ); node->info.linearfile.size = file_size; node->info.linearfile.direct = &tar_image[offset]; } nblocks = (((file_size) + 511) & ~511) / 512; offset += 512 * nblocks; } } rtems_filesystem_location_free( &rootloc ); rtems_filesystem_eval_path_cleanup( &ctx ); return rv; }