XV6: pwd implementation - xv6

I was trying to implement pwd command in xv6 system. But i am getting a error in sysfile.c execution. The function is as follows showing the error:-
int sys_getcwd(void) {
char *p;
int n;
if(argint(1, &n) < 0 || argptr(0, &p, n) < 0)
return -1;
return name_for_inode(p, n, proc->cwd);
}
I get error as follows:
error: ‘proc’ undeclared (first use in this function)
return name_for_inode(p, n, proc->cwd);
But I also included proc.h in this file.

proc is not defined, and warning, it's a struct name.
You have to query the current process, you can do it with myproc() function
int sys_getcwd(void) {
char *p;
int n;
struct proc *curproc = myproc();
if(argint(1, &n) < 0 || argptr(0, &p, n) < 0)
return -1;
return name_for_inode(p, n, curproc->cwd);
}

Yes proc is not global variable so initialize it with current process on which cpu is working.
struct proc *proc = myproc();
return name_for_inode(p, n, proc->cwd);

Related

Queue implementation throws incompatible pointer type error

I think I'm missing general concepts on structs and pointers. Hence, below code is producing 2 warnings/errors and I don't understand why.
Why is "queue->head = temp" producing following warning:
warning: assignment from incompatible pointer type [enabled by default]
Why is "queue->tail->next = temp" producing following error:
error: dereferencing pointer to incomplete type.
Note: The line "Node *temp = newNode(data)" does not throw any error/warnings so it's successful.
typedef struct {
int data;
struct Node *next;
} Node;
typedef struct {
struct Node *head;
struct Node *tail;
} Queue;
void enQueue(Queue *queue, int data)
{
// Create a new node
Node *temp = newNode(data);
// If queue is empty, then new node is both head and tail
if (queue->tail == NULL)
{
queue->head = temp;
queue->tail = temp;
return;
}
// Add the new node at the end of queue and change tail
queue->tail->next = temp;
queue->tail = temp;
}
How did you get this code to compile?
Your Node structure contains a pointer to another Node. In the way you declared your structure, the compiler does not know Node while parsing your structure definition. Hence, you must write:
1 typedef struct Node{
2 int data;
3 struct Node *next;
4 } Node;
In this way, the compiler knows how to handle your structure when parsing it. In line 3 it already knows that Nodeis structure. Since some of your code is missing, I created a minimal example that implements a super simple queue:
#include <stdlib.h>
#include <stdio.h>
#define MAX 5
typedef struct Node{
int data;
struct Node *next;
} Node;
typedef struct {
struct Node *head;
struct Node *tail;
} Queue;
Node* newNode(const int nodeData){
Node* tmp = malloc(sizeof(*tmp));
if (NULL == tmp){
printf("Could not allocate Node ... exiting");
exit(EXIT_FAILURE);
}
tmp->data = nodeData;
tmp->next = NULL;
return tmp;
}
void enQueue(Queue *queue, int data)
{
// Create a new node
Node *temp = newNode(data);
// If queue is empty, then new node is both head and tail
if (queue->tail == NULL)
{
printf("Queue is empty\n");
queue->head = temp;
queue->tail = temp;
return;
}
// Add the new node at the end of queue and change tail
queue->tail->next = temp;
queue->tail = temp;
}
void printQueue(Queue* q){
Node* tmp = q->head;
while (tmp != NULL){
printf("Value: %d\n", tmp->data);
tmp = tmp->next;
}
}
int main(void){
Queue q;
q.head = q.tail = NULL;
int i;
for (i = 0; i < MAX; ++i){
printf("%d is entered into the queue\n", i);
enQueue(&q, i);
}
printQueue(&q);
}

timerfd mysteriously set int to 0 when read()

I am doing an timerfd hello world in ubuntu 14.04, but got a strange situation: the int count is reset after read timerfd but uint64_int not.
int main(int agrc, char **argv) {
unsigned int heartbeat_interval = 1;
struct itimerspec next_timer;
struct timespec now;
if (clock_gettime(CLOCK_REALTIME, &now) == -1)
err_sys((WHERE + std::string("timer error")).c_str());
next_timer.it_value.tv_sec = now.tv_sec;
next_timer.it_value.tv_nsec = 0;
next_timer.it_interval.tv_sec = heartbeat_interval;
next_timer.it_interval.tv_nsec = 0;
int timefd = timerfd_create(CLOCK_REALTIME, 0);
if (timerfd_settime(timefd, TFD_TIMER_ABSTIME, &next_timer, NULL) == -1) {
err_sys((WHERE).c_str());
}
uint64_t s;
int exp;
int count = 1;
uint64_t count1=0;
while (1) {
s = read(timefd, &exp, sizeof(uint64_t));
if (s != sizeof(uint64_t)) {
err_sys((WHERE).c_str());
}
}
}
int exp;
^^^
s = read(timefd, &exp, sizeof(uint64_t));
^^^ ^^^^^^^^
Unless your int and uint64_t types are the same size, this is a very bad idea. What's most likely happening is that the 64 bits you're reading are overwriting exp and whatever else happens to be next to it on the stack.
Actually, even if they are the same size, it's a bad idea. What you should have is something like:
s = read(timefd, &exp, sizeof(exp));
That way, you're guaranteed to never overwrite the data and your next line would catch the problem for you:
if (s != sizeof(uint64_t)) {
It won't solve the problem that an unsigned integral type and an integral type will be treated differently but you can fix that just by using the right type for exp.

Pointer back and next for a node

I'm new to C++. I'm now trying to create a class with back and forth pointer. My code is listed below:
#include<iostream>
using namespace std;
class Node
{
public:
Node(int d, Node*k = NULL, Node*q = NULL) :data(d), back(k), next(q){};
int data;
Node*next; // point to next value on the list
Node*back; // point to back value on the list
};
int main()
{
int n;
Node*p = NULL;
Node*k = NULL; //k is back
while (cin >> n)
{
p = new Node(n,k);
p->back->next = p;
k = p;
}
for (; p; p = p->back)
cout << p->data << "->";
cout << "*\n";
system("pause");
}
However, I always have this error: "Access violation writing location"
I wonder if anybody have a solution ? Thanks
In the first iteration of the loop p->back is NULL. You get the access violation because you dereference it. Write this instead:
while (cin >> n)
{
p = new Node(n,k);
if (p->back != NULL) // p->back == NULL in the first iteration
p->back->next = p;
k = p;
}

Base case condition in quick sort algorithm

For the quick sort algorithm(recursive), every time when it calls itself, it have the condition if(p < r). Please correct me if I am wrong: as far as I know, for every recursive algorithm, it has a condition as the time when it entered the routine, and this condition is used to get the base case. But I still cannot understand how to correctly set and test this condition ?
void quickSort(int* arr, int p, int r)
{
if(p < r)
{
int q = partition(arr,p,r);
quickSort(arr,p,q-1);
quickSort(arr,q+1,r);
}
}
For my entire code, please refer to the following:
/*
filename : main.c
description: quickSort algorithm
*/
#include<iostream>
using namespace std;
void exchange(int* val1, int* val2)
{
int temp = *val1;
*val1 = *val2;
*val2 = temp;
}
int partition(int* arr, int p, int r)
{
int x = arr[r];
int j = p;
int i = j-1;
while(j<=r-1)
{
if(arr[j] <= x)
{
i++;
// exchange arr[r] with arr[j]
exchange(&arr[i],&arr[j]);
}
j++;
}
exchange(&arr[i+1],&arr[r]);
return i+1;
}
void quickSort(int* arr, int p, int r)
{
if(p < r)
{
int q = partition(arr,p,r);
quickSort(arr,p,q-1);
quickSort(arr,q+1,r);
}
}
// driver program to test the quick sort algorithm
int main(int argc, const char* argv[])
{
int arr1[] = {13,19,9,5,12,8,7,4,21,2,6,11};
cout <<"The original array is: ";
for(int i=0; i<12; i++)
{
cout << arr1[i] << " ";
}
cout << "\n";
quickSort(arr1,0,11);
//print out the sorted array
cout <<"The sorted array is: ";
for(int i=0; i<12; i++)
{
cout << arr1[i] << " ";
}
cout << "\n";
cin.get();
return 0;
}
Your question is not quite clear, but I will try to answer.
Quicksort works by sorting smaller and smaller arrays. The base case is an array with less than 2 elements because no sorting would be required.
At each step it finds a partition value and makes it true that all the values to the left of the partition value are smaller and all values to the right of the partition value are larger. In other words, it puts the partition value in the correct place. Then it recursively sorts the array to the left of the partition and the array to right of the partition.
The base case of quicksort is an array with one element because a one element array requires no sorting. In your code, p is the index of the first element and r is the index of the last element. The predicate p < r is only true for an array of at least size 2. In other words, if p >= r then you have an array of size 1 (or zero, or nonsense) and there is no work to do.

How do I read ext2 root directory from mapped memory?

I'm making a Remote Filesystem Server for my university and I'm having some trouble with reading the root directory... Here's the thing:
I've read the root inode (inode 2) and it has consistent data, I mean that, for example, owner user Id field is set at '1000'. Then I proceed to read the contents of the inode data blocks, but when I try to access to the data block in question (the only one that is addressed in the inode i_block array, 240 on my debugging) all bytes are set to '0'. Can anyone help me with this? It's really important. Note: I cannot make it another way than with mapped memory and I'm not opening a real disk, but rather opening a .disk linux file. It has been created with the command-line
mkfs.ext2 -F -r 0 -b 1024 ext2.disk 30000
Here's my code:
#include <linux/ext2_fs.h>
typedef struct s_inode *pinode; /* Pointer to inode struct */
typedef struct s_direct *pdir; /* Pointer to direct struct */
int main(int argv, char *argc[]){
int *data;
pdir root = malloc(sizeof(struct s_direct));
/* Code for mpping .disk file, fetching supernode, and other ext2 data */
/* fsys is a global variable that holds general ext2 system data */
fsys->root = get_inode(2);
data = get_cont(fsys->root);
root = (pdir)getblock(data[0]);
}
pinode get_inode(int idx){
pinode inod;
int grp, offs;
grp = (idx-1)/fsys->superblock->s_inodes_per_group;
offs = (idx-1)%fsys->superblock->s_inodes_per_group;
inod = (pinode)&fsys->diskmap[(fsys->group[grp]->itab)+offs*sizeof(struct s_inode)];
return inod;
}
int *get_cont(pinode inod){
int *cont;
int *idx;
int i=0;
int *block;
idx = malloc(sizeof(int));
cont = malloc(sizeof(int));
while(i < inod->i_blocks && i<13) {
realloc(cont, i*sizeof(int));
cont[i]=inod->i_block[i];
i++;
}
if(i < inod->i_blocks){
*idx=13;
block=(int*)getblock(inod->i_block[*idx]);
fetchcont(block, idx, cont, inod->i_blocks, 0);
}
if(i < inod->i_blocks){
block=(int*)getblock(inod->i_block[*idx]);
fetchcont(block, idx, cont, inod->i_blocks, 1);
}
if(i < inod->i_blocks){
block=(int*)getblock(inod->i_block[*idx]);
fetchcont(block, idx, cont, inod->i_blocks, 2);
}
return cont;
}
int fetchcont(int *block, int *idx, int *cont, int lim, int lvl){
int i=0;
if(lvl == 0){
while((*idx) < lim && i<fsys->bsize){
realloc(cont, (*idx)*sizeof(int));
cont[*idx]=block[i];
(*idx)++;
i++;
}
if(i>=fsys->bsize){
return 1;
}else{
return 0;
}
}else{
lvl--;
while(i<fsys->bsize){
if(!fetchcont((int*)getblock(block[i]), idx, cont, lim, lvl)){
return 0;
}
i++;
}
}
}
void *getblock(int idx){
char *block;
int grp, offs;
grp = (idx-1)/fsys->superblock->s_blocks_per_group;
offs = (idx-1)%fsys->superblock->s_blocks_per_group;
block = &fsys->diskmap[fsys->group[grp]->blocks+offs*fsys->bsize];
return block;
}
Solved the problem. I assumed that block n was the n data block, but the offset included ALL the blocks. I've changed my getblock function to
void *getblock(int idx){
return &fsys->diskmap[fsys->bsize*idx];
}
and worked!

Resources