/*
* Copyright (c) 2007 Konopa-Jelen-Majer
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/** @addtogroup FSDemo
* @{
*/
/**
* @file cat.c
* @brief A file system demonstration task - raw IPC version
*/
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <async.h>
#include <align.h>
#include <as.h>
#include <ipc/ipc.h>
#include <ipc/services.h>
#include <sys/mman.h>
#include "../fs/fs.h"
#include "../share/shared_proto.h"
#include "../console/console.h"
#include "../fs/stat.h"
#define CON_FS_ATTEMPTS 1000
#define LINE_LENGTH 30
#define EOL 10
#define SPACE_BAR 32
#define CONSOLE_WIDTH 60
#define CONSOLE_HEIGHT 20
static int fs_phone;
/**
* Reads one line from input (returns after receiving line feed or after reading max_line_length characters)
* @param max_line_length Maximum line length allowed
* @return Pointer to read string (null when max_line_length < 0).
*/
static char* input_read(int max_line_length)
{
if (max_line_length < 0) return NULL;
char * input
= malloc(max_line_length
+1);
int c,i;
char * cpy = input;
i = 0;
{
if (++i>max_line_length) break;
}
//adds terminating zero
return input;
}
/**
* Reads input and returns after receiving continue_string
* @param continue_sign Returns after receiving this character.
*/
static void wait_for_char(char continue_sign)
{
while (getchar() != continue_sign
) {}
}
/**
* Writes input string into the console.
* @param align_size Max width of the output line.
* @param line_count After printing line_count lines, wait_for_char is called
* @param reset 1 - resets procedure counters
*/
static void little_more4(char * input, int align_size, int line_count, int reset)
{
static int lines = 0;
static int chars = 0;
if (reset)
lines = chars = 0;
if ((align_size <= 0) || (line_count <=0)) return;
while(*input != '\0')
{
if (*(input++) == EOL)
{
chars = 0;
++lines;
}
else
{
++chars;
if (chars >= align_size)
{
chars = 0;
++lines;
}
}
if (lines >= line_count)
{
lines = chars = 0;
wait_for_char(SPACE_BAR);
}
}
}
/**
* Calls little_more(char * input, int align_size, int line_count, int reset) with default values and no reset.
*/
static void little_more(char * input)
{
little_more4(input, CONSOLE_WIDTH, CONSOLE_HEIGHT, 0);
}
/**
* Calls little_more(char * input, int align_size, int line_count, int reset) with default values.
*/
static void little_more2(char * input, int reset)
{
little_more4(input, CONSOLE_WIDTH, CONSOLE_HEIGHT, reset);
}
static int fopen(char * filename
)
{
return -1;
}
{
return -1;
}
static int fread(void* ptr
, int size
, int nbmem
, int fd
)
{
return 0;
}
/**
* Simple atoi function (converts the string into an integer)
* @param str string to convert
* @return 0 - if error, else converted number
*/
static int my_atoi(char * str)
{
if (str == NULL) return 0;
int minus = 0;
if (str[0] == '-')
{
minus = 1;
++str;
};
int res = 0;
while (*(str) != '\0')
{
res = res*10;
switch (*(str++))
{
case '0':
break;
case '1':
++res;
break;
case '2':
res = res + 2;
break;
case '3':
res = res + 3;
break;
case '4':
res = res + 4;
break;
case '5':
res = res + 5;
break;
case '6':
res = res + 6;
break;
case '7':
res = res + 7;
break;
case '8':
res = res + 8;
break;
case '9':
res = res + 9;
break;
default: return 0;
}
}
if (minus)
{
return -res;
}
else
{
return res;
};
}
/**
* Simple use of fopen function with some I/O
*/
static void open_file()
{
printf("\n\nEnter the file name:\n? ");
char * filename = input_read(LINE_LENGTH);
int fd
= fopen(filename
);
if (fd < 0)
{
}
else
{
printf("\nReturned file descriptor: %d\n", fd
);
}
}
/**
* Simple use of fclose function with some I/O
*/
static void close_file()
{
printf("\n\nEnter the file descriptor:\n? ");
char * fd_str = input_read(2);
int fd = my_atoi(fd_str);
{
}
else
{
printf("\nFile successfully closed.\n");
}
}
/**
* Simple use of fread function with some I/O
*/
static void read_file()
{
printf("\n\nEnter the file descriptor:\n? ");
char * buf = input_read(2);
int fd = my_atoi(buf);
printf("Enter the no. of elements you want to read:\n? ");
buf = input_read(5);
int e_no = my_atoi(buf);
printf("Enter the element size (bytes):\n? ");
buf = input_read(5);
int e_size = my_atoi(buf);
//printf("\nEntered values:\n - fd: %d\n- ec: %d\n- es: %d\n",fd,e_no,e_size);
void * ptr
= malloc(e_no
*e_size
+1);
memset(ptr
,'\0',e_no
*e_size
+1);
int res
= fread(ptr
, e_no
, e_size
, fd
);
printf ("\nNo. of elements read: %d\n",res
);
printf("Returned data:\n------------\n");
little_more2(ptr,1);
}
int main(int argc, char *argv[])
{
char fname[30];
unsigned int file_handle;
int retval, flags, entry;
unsigned short entries_num, inode_num;
size_t size;
void *share = NULL;
little_more2("Cat task\n",1);
little_more("Connecting to the SERVICE_FS...");
if (!connect_to_fs(&fs_phone, CON_FS_ATTEMPTS)) {
little_more("Connection to SERVICE_FS was refused\n");
return -1;
}
little_more("OK\n");
little_more("Creating address space area...");
size = ALIGN_UP(BLOCK_SIZE * sizeof(char), PAGE_SIZE);
share = mmap(share, size, AS_AREA_READ | AS_AREA_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0);
if ((int)share < 0){
little_more("As_area_create error: ");
little_more("\n");
return -1;
}
little_more("Connecting the task to FS...");
retval = async_req_2(fs_phone, FS_NEW_CONSUMER, task_get_id(), 0, NULL, NULL);
if (retval < 0) {
little_more("\n");
return -1;
}
little_more("OK\n");
little_more("Sending memory to FS_SERVICE...");
flags = 0;
flags = AS_AREA_READ | AS_AREA_WRITE;
retval = async_req_3(fs_phone, IPC_M_AS_AREA_SEND, (uintptr_t)share, size, flags, NULL, NULL, NULL);
if (retval < 0) {
little_more("\n");
return -1;
}
little_more("OK\n");
/* Allocating structure for extended message. */
message_params_t *params;
params
= malloc(sizeof(message_params_t
));
memset((void*)params
, 0, sizeof(message_params_t
));
/* We want lookup our work directory. */
little_more("Request for get number of entries...");
retval = send_request(fs_phone, FS_DSUM, params, share);
if (retval < 0) {
little_more("\n");
return -1;
}
little_more("OK\n");
little_more("Total number of entries: ");
little_more("\n");
entries_num = retval;
/* File list in working directory. */
little_more("File list:\n");
for (entry = 0; entry < entries_num; entry++) {
params->entry_number = entry;
retval = send_request(fs_phone, FS_READENTRY, params, share);
if (retval < 0) {
little_more("\n");
return -1;
}
/*
if (retval < sizeof(unsigned short))
continue;
*/
memcpy(&inode_num
, share
, sizeof(unsigned short));
memcpy(fname
, (void *)(share
+sizeof(unsigned short)), retval
-sizeof(unsigned short));
/* Do not show empty entries. */
if (!inode_num)
continue;
little_more("Inode number: ");
little_more("\t\t");
little_more("File name: ");
little_more(fname);
little_more("\n");
}
little_more("OK\n");
/* We want to change working directory */
memcpy(fname
, "uspace/fs", 10);
memcpy(params
->fname
, fname
, 10);
little_more("Request for changing actual directory to ");
little_more(fname);
little_more("...");
retval = send_request(fs_phone, FS_CHDIR, params, share);
if (retval < 0) {
little_more("\n");
return -1;
}
little_more("OK\n");
/* We want to work with specified file. */
memcpy(params
->fname
, fname
, 10);
little_more("Request for opening file ");
little_more(fname);
little_more("...");
retval = send_request(fs_phone, FS_OPEN, params, share);
if (retval < 0) {
little_more("\n");
return -1;
}
little_more("OK\n");
file_handle = retval;
little_more("Returned file handle...");
little_more("\n");
memcpy(params
->fname
, fname
, 10);
params->fd = file_handle;
little_more("Request for getting info about file ");
little_more(fname);
little_more("[FSTAT called]...");
retval = send_request(fs_phone, FS_FSTAT, params, share);
if (retval < 0) {
little_more("\n");
return -1;
}
little_more("OK\n");
params->fd = file_handle;
params->offset = 100;
params->whence = 1; /* from actual position in the file */
little_more("Request for seeking after ");
little_more(" bytes inside file ");
little_more(fname);
little_more("...");
retval = send_request(fs_phone, FS_SEEK, params, share);
if (retval < 0) {
little_more("\n");
return -1;
}
little_more("OK\n");
little_more("New file position is: ");
little_more("\n");
params->nbytes = 100;
little_more("Request for reading ");
little_more(" bytes from file ");
little_more(fname);
little_more("...");
retval = send_request(fs_phone, FS_READ, params, share);
if (retval < 0) {
little_more("\n");
return -1;
}
little_more("OK\n");
little_more(" bytes was read into buffer\n");
little_more("\nContent of the buffer:\n");
little_more(share);
little_more("\n\n");
params->offset = 0;
params->whence = 0; /* from beginning of the file */
little_more("Request for seeking after ");
little_more(" bytes inside file ");
little_more(fname);
little_more("...");
retval = send_request(fs_phone, FS_SEEK, params, share);
if (retval < 0) {
little_more("\n");
return -1;
}
little_more("OK\n");
little_more("New file position is: ");
little_more("\n");
params->fd = file_handle;
params->nbytes = 50;
little_more("Another request for reading ");
little_more(" bytes from file ");
little_more(fname);
little_more("...");
retval = send_request(fs_phone, FS_READ, params, share);
if (retval < 0) {
little_more("\n");
return -1;
}
little_more("OK\n");
little_more(" bytes was read into buffer\n");
little_more("\nContent of the buffer:\n");
little_more(share);
little_more("\n\n");
little_more("Request for closing file ");
little_more(fname);
little_more("...");
retval = send_request(fs_phone, FS_CLOSE, params, share);
if (retval < 0) {
little_more("\n");
return -1;
}
little_more("OK\n");
/*
printf("Request for closing file %s once more...", fname);
retval = send_request(fs_phone, FS_CLOSE, params, share);
if (retval < 0) {
printf("%d\n", retval);
return -1;
}
printf("OK\n");
*/
little_more("Request for dropping the connection to the FS...");
retval = send_request(fs_phone, FS_DROP_CONSUMER, params, share);
if (retval < 0) {
little_more("\n");
return -1;
}
little_more("OK\n");
/* Unmapping share area. */
little_more("Unmapping share area...");
retval = munmap(share, size);
if (retval < 0) {
little_more("\n");
return -1;
}
little_more("OK\n");
little_more("Creating address space area...");
size = ALIGN_UP(BLOCK_SIZE * sizeof(char), PAGE_SIZE);
share = mmap(share, size, AS_AREA_READ | AS_AREA_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0);
if ((int)share < 0){
little_more("As_area_create error: ");
little_more("\n");
return -1;
}
little_more("OK\n");
/* Next connection to the FS. */
little_more("Connecting the task to FS...");
retval = async_req_2(fs_phone, FS_NEW_CONSUMER, task_get_id(), 0, NULL, NULL);
if (retval < 0) {
little_more("FS_NEW_CONSUMER error: ");
little_more("\n");
return -1;
}
little_more("OK\n");
little_more("Sending memory to FS_SERVICE...");
flags = 0;
flags = AS_AREA_READ | AS_AREA_WRITE;
retval = async_req_3(fs_phone, IPC_M_AS_AREA_SEND, (uintptr_t)share, size, flags, NULL, NULL, NULL);
if (retval < 0) {
little_more("\n");
return -1;
}
little_more("OK\n");
/* We want to work with specified file. */
memcpy(fname
, "/kernel/arch", 20);
memcpy(params
->fname
, fname
, 20);
little_more("Request for getting info about file ");
little_more(fname);
little_more("[STAT called]...");
retval = send_request(fs_phone, FS_STAT, params, share);
if (retval < 0) {
little_more("\n");
return -1;
}
little_more("OK\n");
stat_t file_info;
memcpy((void *)(&file_info
), share
, sizeof(stat_t
));
little_more("Info about file: ");
little_more(fname);
little_more("\nInode number: ");
printf("%d", file_info.
st_ino);
little_more("\nMode: ");
printf("%d", file_info.
st_mode);
little_more("\nLinks: ");
printf("%d", file_info.
st_nlink);
little_more("\nSize: ");
printf("%d", file_info.
st_size);
little_more("\n");
//==================================================================================
while(1)
{
printf("\n\n\n- <stdio.h> calls -\n\n");
printf("What do you want to do?\n");
printf("o - open some file\n");
printf("c - close some file\n");
printf("r - read some file\n");
char * choice = input_read(1);
switch (choice[0])
{
case 'o':
open_file();
break;
case 'c':
close_file();
break;
case 'r':
read_file();
break;
}
wait_for_char(SPACE_BAR);
printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
}
return 0;
}