struct fs_dirent *vc_hostfs_readdir_r(void *dhandle, struct fs_dirent *result) { struct fs_dir *fsdir = (struct fs_dir *)dhandle; DEBUG_MINOR( "vc_hostfs_readdir_r(%p)", fsdir ); if (fsdir && result) { struct dirent *dent; while ((dent = readdir(fsdir->dhandle)) != NULL) { struct stat statbuf; int ret; /* Append the filename, and stat the resulting path */ fsdir->pathbuf[fsdir->pathlen] = '/'; strcpy(fsdir->pathbuf + fsdir->pathlen + 1, dent->d_name); ret = stat(fsdir->pathbuf, &statbuf); fsdir->pathbuf[fsdir->pathlen] = '\0'; if (ret == 0) { strncpy(result->d_name, dent->d_name, sizeof(result->d_name) - 1); result->d_name[sizeof(result->d_name) - 1] = '\0'; result->d_size = (statbuf.st_size <= 0xffffffff) ? (unsigned int)statbuf.st_size : 0xffffffff; result->d_attrib = ATTR_NORMAL; if ((statbuf.st_mode & S_IWUSR) == 0) result->d_attrib |= ATTR_RDONLY; if (statbuf.st_mode & S_IFDIR) result->d_attrib |= ATTR_DIRENT; result->d_creatime = statbuf.st_ctime; result->d_modtime = statbuf.st_mtime; DEBUG_MINOR( "vc_hostfs_readdir_r() = '%s', %x, %x", result->d_name, result->d_size, result->d_attrib ); break; } } if (!dent) { DEBUG_MINOR( "vc_hostfs_readdir_r() = NULL" ); rewinddir(fsdir->dhandle); result = NULL; } } else { result = NULL; } return result; }
int vc_hostfs_get_attr(const char *path, fattributes_t *attr) { struct stat sb; DEBUG_MINOR("vc_hostfs_get_attr: '%s'", path ); *attr = 0; if ( stat( path, &sb ) == 0 ) { if ( S_ISDIR( sb.st_mode )) { *attr |= ATTR_DIRENT; } if (( sb.st_mode & S_IWUSR ) == 0 ) { *attr |= ATTR_RDONLY; } return 0; } return -1; }
/****************************************************************************** NAME vc_hostfs_freespace SYNOPSIS int vc_hostfs_freespace(const char *path) FUNCTION Returns the amount of free space on the physical file system that contains path. RETURNS Successful completion: free space Otherwise: -1 ******************************************************************************/ int64_t vc_hostfs_freespace64(const char *inPath) { char *path = strdup( inPath ); int64_t ret; STRUCT_STATFS fsStat; // Replace all '\' with '/' backslash_to_slash( path ); ret = (int64_t) STATFS( path, &fsStat ); if (ret == 0) { ret = fsStat.f_bsize * fsStat.f_bavail; } else { ret = -1; } DEBUG_MINOR( "vc_hostfs_freespace64 for '%s' returning %" PRId64 "", path, ret ); free( path ); return ret; }
void vc_hostfs_init(void) { // This hostfs module is not thread safe - it allocaes a block // of memory and uses it without any kind of locking. // // It offers no advantage of stdio, and so most clients should // not use it. Arguably FILESYS should use it in order to get // the FIFO support. const char *thread_name = vcos_thread_get_name(vcos_thread_current()); if (strcmp(thread_name, "FILESYS") != 0 && strcmp(thread_name, "HFilesys") != 0) { fprintf(stderr,"%s: vc_hostfs is deprecated. Please use stdio\n", vcos_thread_get_name(vcos_thread_current())); } vcos_log_register("hostfs", &hostfs_log_cat); DEBUG_MINOR("init"); // Allocate memory for the file info table p_file_info_table = (file_info_t *)calloc( FILE_INFO_TABLE_CHUNK_LEN, sizeof( file_info_t ) ); assert( p_file_info_table != NULL ); if (p_file_info_table) { file_info_table_len = FILE_INFO_TABLE_CHUNK_LEN; } }
int64_t vc_hostfs_lseek64(int fildes, int64_t offset, int whence) { DEBUG_MINOR("vc_hostfs_lseek(%d,%" PRId64 ",%d)", fildes, offset, whence); if (fildes >= file_info_table_len) { // File descriptor not in table, so this is an error DEBUG_MAJOR("vc_hostfs_lseek: invalid fildes %d", fildes); return -1; } else { // There is entry in the file info table for this file descriptor, so go // ahead and handle the seek int64_t read_offset = p_file_info_table[fildes].read_offset; if (p_file_info_table[fildes].is_fifo) { // The Videocore is attempting to seek on a FIFO. FIFOs don't support seeking // but, for the benefit of certain Videocore "streaming" file handlers, we // will fake limited FIFO seek functionality by computing where a seek // would take us to if (whence == SEEK_SET) { read_offset = offset; } else if (whence == SEEK_CUR) { read_offset += offset; } else { // seeking to the end of FIFO makes no sense, so this is an error DEBUG_MAJOR("vc_hostfs_lseek(%d,%lld,%d): SEEK_END not supported on FIFO", fildes, (long long)offset, whence); return -1; } } else { // File is not a FIFO, so do the seek read_offset = lseek64(fildes, offset, whence); } p_file_info_table[fildes].read_offset = read_offset; DEBUG_MINOR("vc_hostfs_lseek returning %" PRId64 ")", read_offset); return read_offset; } }
int vc_hostfs_mkdir(const char *path) { DEBUG_MINOR( "vc_hostfs_mkdir: '%s'", path ); if ( mkdir( path, 0777 ) == 0 ) { return 0; } return -1; }
void *vc_hostfs_opendir(const char *dirname) { struct fs_dir *fsdir = NULL; DEBUG_MINOR( "vc_hostfs_opendir: '%s'", dirname ); if (dirname && dirname[0]) { fsdir = (struct fs_dir *)malloc(sizeof(struct fs_dir)); if (fsdir) { DIR *dhandle; int len = strlen(dirname); memcpy(fsdir->pathbuf, dirname, len); backslash_to_slash(fsdir->pathbuf); /* Remove any trailing slashes */ while (fsdir->pathbuf[len - 1] == '/') len--; fsdir->pathbuf[len] = '\0'; dhandle = opendir(fsdir->pathbuf); DEBUG_MINOR( "opendir: '%s' = %p", fsdir->pathbuf, dhandle ); if (dhandle) { fsdir->pathlen = len; fsdir->dhandle = dhandle; } else { free(fsdir); fsdir = NULL; } } } return fsdir; }
int vc_hostfs_remove(const char *path) { char *pathbuf = strdup(path); int ret = -1; DEBUG_MINOR( "vc_hostfs_remove: '%s'", path ); if (pathbuf) { backslash_to_slash(pathbuf); if ( unlink( pathbuf ) == 0 ) ret = 0; } return ret; }
int vc_hostfs_closedir(void *dhandle) { struct fs_dir *fsdir = (struct fs_dir *)dhandle; int ret = -1; DEBUG_MINOR( "vc_hostfs_closedir(%p)", dhandle ); if (dhandle && fsdir->dhandle) { (void)closedir(fsdir->dhandle); fsdir->dhandle = NULL; free(fsdir); ret = 0; } return ret; }
int vc_hostfs_read(int fildes, void *buf, unsigned int nbyte) { if (fildes >= file_info_table_len) { // File descriptor not in table, so this is an error DEBUG_MAJOR("vc_hostfs_read(%d,%p,%u): invalid fildes", fildes, buf, nbyte); return -1; } else { // There is entry in the file info table for this file descriptor, so go // ahead and handle the read int ret = (int) read(fildes, buf, nbyte); DEBUG_MINOR("vc_hostfs_read(%d,%p,%u) = %d", fildes, buf, nbyte, ret); if (ret > 0) { p_file_info_table[fildes].read_offset += (long) ret; } return ret; } }
int vc_hostfs_format(const char *path) { DEBUG_MINOR("vc_hostfs_format: '%s' not implemented", path); return -1; }
int vc_hostfs_write(int fildes, const void *buf, unsigned int nbyte) { int ret = (int) write(fildes, buf, nbyte); DEBUG_MINOR("vc_hostfs_write(%d,%p,%u) = %d", fildes, buf, nbyte, ret); return ret; }
int vc_hostfs_open(const char *inPath, int vc_oflag) { char *path = strdup( inPath ); //char *s; int flags = 0, ret=errno; struct stat fileStat; // Replace all '\' with '/' backslash_to_slash( path ); #if 0 s = path + strlen( path ); if (( s - path ) >= 4 ) { if ( strcasecmp( &s[ -4 ], ".vll" ) == 0 ) { // The Videocore is asking for a .vll file. Since it isn't consistent with // the case, we convert .vll files to all lowercase. "vc_hostfs_open: '%s'", path ; s--; // backup to the last character (*s is on the '\0') while (( s >= path ) && ( *s != '/' )) { *s = tolower( *s ); s--; } } } #endif DEBUG_MINOR("vc_hostfs_open: '%s'", path); flags = O_RDONLY; if (vc_oflag & VC_O_WRONLY) flags = O_WRONLY; if (vc_oflag & VC_O_RDWR) flags = O_RDWR; if (vc_oflag & VC_O_APPEND) flags |= O_APPEND; if (vc_oflag & VC_O_CREAT) flags |= O_CREAT; if (vc_oflag & VC_O_TRUNC) flags |= O_TRUNC; if (vc_oflag & VC_O_EXCL) flags |= O_EXCL; //while (*path == '\\') path++; // do not want initial '\' if (flags & O_CREAT) ret = open(path, flags, S_IRUSR | S_IWUSR ); else ret = open(path, flags ); if (ret < 0 ) { DEBUG_MINOR("vc_hostfs_open(%s,%d) = %d", path, vc_oflag, ret); } else { DEBUG_MINOR("vc_hostfs_open(%s,%d) = %d", path, vc_oflag, ret); } // If the file was successfully open then initialize its entry in // the file info table. If necessary, we expand the size of the table if (ret >= 0) { // File was successfully opened if (ret >= file_info_table_len) { file_info_t *p_new_file_info_table = p_file_info_table; int new_file_info_table_len = file_info_table_len; // try and allocate a bigger buffer for the file info table new_file_info_table_len += FILE_INFO_TABLE_CHUNK_LEN; p_new_file_info_table = calloc( (size_t)new_file_info_table_len, sizeof( file_info_t ) ); if (p_new_file_info_table == NULL) { // calloc failed DEBUG_MAJOR("vc_hostfs_open: file_info_table calloc failed"); assert( 0 ); } else { // calloc successful, so copy data from previous buffer to new buffer, // free previous buffer and update ptr and len info memcpy( p_new_file_info_table, p_file_info_table, sizeof( file_info_t ) * file_info_table_len ); free( p_file_info_table ); p_file_info_table = p_new_file_info_table; file_info_table_len = new_file_info_table_len; } } assert( ret < file_info_table_len ); { // initialize this file's entry in the file info table p_file_info_table[ret].is_fifo = 0; p_file_info_table[ret].read_offset = 0; } // Check whether the file is a FIFO. A FIFO does not support seeking // but we will fake, to the extent supported by the buffered file system // on the Videocore, limited FIFO seek functionality. This is for the benefit // of certain Videocore "streaming" file handlers. if (fstat( ret, &fileStat ) != 0) { DEBUG_MINOR("vc_hostfs_open: fstat failed: %s", strerror(errno)); } else if (S_ISFIFO( fileStat.st_mode )) { // file is a FIFO, so note its fildes for future reference p_file_info_table[ret].is_fifo = 1; DEBUG_MINOR("vc_hostfs_open: file with fildes %d is a FIFO", ret); } } free( path ); return ret; }
int vc_hostfs_close(int fildes) { DEBUG_MINOR("vc_hostfs_close(%d)", fildes); return close(fildes); }