making tree function in xv6 - unix

I want to make tree command in xv6, if you don't know the tree is to list out directories on the terminal. I know this is probably easy for you but the code is so far
#include "types.h"
#include "stat.h"
#include "user.h"
#include "fcntl.h"
#include "fs.h"
#include "file.h"
int
main(int argc, char *argv[])
{
if(argc < 2){
printf(2, "Usage: tree [path]...\n");
exit();
}
tree(argv[1]);
int fd = open(argv[1],O_RDONLY);
if(fd<0)
return -1;
struct dirent dir;
while(read(fd,&dir,sizeof(dir))!=0){
printf(1,"|_ %d,%d",dir.name,dir.inum);
//struct stat *st;
struct inode ip;
ip= getinode(dir.inum);
if(ip.type==T_DIR){
int i;
for(i=0;i<NDIRECT;i++ ){
uint add=ip.addrs[i];
printf(1,"%d",add);
}
}
}
return 0;
}
and it has been giving me numerous error on the terminal the first being file.h:17:20: error: field ‘lock’ has incomplete type
struct sleeplock lock; // protects everything below here
^~~~
I'm searching for sleeplock and there is nothing like that in the code. What is wrong with the code? Thank you for your help

You cannot use kernel headers (like file.h) in a user code. To use kernel functionnalities in your code, you must use system calls.
To achieve what you want, you could start from ls function and make it recursive.
One example made quickly:
I added a parameter to the ls function to display the depth of crawling
and call itself on each directory elements but two first which are . and ..
void
ls(char *path, int decal)
{
char buf[512], *p;
int fd, i, skip = 2;
struct dirent de;
struct stat st;
if((fd = open(path, 0)) < 0){
printf(2, "tree: cannot open %s\n", path);
return;
}
if(fstat(fd, &st) < 0){
printf(2, "tree: cannot stat %s\n", path);
close(fd);
return;
}
switch(st.type){
case T_FILE:
for (i = 0; i < decal; i++)
printf(1, " ");
printf(1, "%s %d %d %d\n", fmtname(path), st.type, st.ino, st.size);
break;
case T_DIR:
if(strlen(path) + 1 + DIRSIZ + 1 > sizeof buf){
printf(1, "tree: path too long\n");
break;
}
strcpy(buf, path);
p = buf+strlen(buf);
*p++ = '/';
while(read(fd, &de, sizeof(de)) == sizeof(de)){
if(de.inum == 0)
continue;
memmove(p, de.name, DIRSIZ);
p[DIRSIZ] = 0;
if(stat(buf, &st) < 0){
printf(1, "tree: cannot stat %s\n", buf);
continue;
}
for (i = 0; i < decal; i++)
printf(1, " ");
printf(1, "%s %d %d %d\n", fmtname(buf), st.type, st.ino, st.size);
if (skip)
skip--;
else
ls(buf, decal+1);
}
break;
}
close(fd);
}

Related

Downloading Image to a specific folder using gp_filesystem_get_file()

Trying my hands on libgphoto2 library examples and while going through simple-capture.c file. Can i download foo.jpg captured image to a specified folder on my computer?
As far as i understood, in capture_to_file() camera_file_path.folder is the folder in which the file can be found on the camera. So open() should specify the host(computer) location. But nothing worked, i get following error:
You need to specify a folder starting with /store_xxxxxxxxx/
Am i missing something here? Any help would be appreciated, thanks!
I got this working.
Written small application for multiple cameras. Including main() for about question.
int main(int argc, char **argv)
{
CameraList *list;
Camera **cams;
int retval, count, i;
GPContext *context;
FILE *f;
char *data;
unsigned long size;
const char *name, *value;
/*
* Create context
*/
context = sample_create_context();
/*
* Setup Images DB directory.
*/
char* home = getenv("HOME");
if (home == NULL)
{
printf("Error: Unable to fetch home env! \n");
exit(1);
}
char* path = "/Desktop/mw/";
size_t len = strlen(home) + strlen(path) + 1;
char* imgdb = malloc(len);
if (imgdb == NULL)
{
printf("Error: Unable to malloc(). \n");
exit(1);
}
strcpy(imgdb, home);
strcat(imgdb, path);
directory_exists_or_create(imgdb);
/*
* Logs
*/
gp_log_add_func(GP_LOG_ERROR, errordumper, NULL);
/*
* Detect all the cameras that can be autodetected
*/
retval = gp_list_new(&list);
if (retval < GP_OK)
{
printf("Unable to create camera list.\n");
return 1;
}
count = sample_autodetect(list, context);
if (count < GP_OK)
{
printf("No cameras detected.\n");
return 1;
}
/*
* Now open all the cameras we autodetected for usage.
*/
printf("Number of cameras: %d\n", count);
cams = calloc(sizeof(Camera*), count);
for (i = 0; i < count; i++)
{
gp_list_get_name(list, i, &name);
gp_list_get_value(list, i, &value);
retval = sample_open_camera(&cams[i], name, value, context);
if (retval < GP_OK)
{
fprintf(stderr, "Camera %s on port %s failed to open\n", name, value);
}
}
if (argc > 0)
{
while ((++argv)[0])
{
if (argv[0][0] == '-')
{
switch (argv[0][1])
{
case 'h':
case 'H':
{
/* Now call a simple function in each of those cameras. */
for (i = 0; i < count; i++)
{
CameraText text;
char *owner;
retval = gp_camera_get_summary (cams[i], &text, context);
if (retval < GP_OK)
{
fprintf (stderr, "Failed to get summary.\n");
continue;
}
gp_list_get_name (list, i, &name);
gp_list_get_value (list, i, &value);
printf("%-30s %-16s\n", name, value);
printf("Summary:\n%s\n", text.text);
/* Query a simple string configuration variable. */
retval = get_config_value_string (cams[i], "owner", &owner, context);
if (retval >= GP_OK)
{
printf("Owner: %s\n", owner);
free (owner);
}
else
{
printf("Owner: No owner found.\n");
}
}
}
/* Graceful exit from the program */
goto exit_;;
default:
printf("Unknown option -%c\n\n", argv[0][1]);
break;
}
}
}
}
/* When I set GP_LOG_DEBUG instead of GP_LOG_ERROR above, I noticed that the
* init function seems to traverse the entire filesystem on the camera. This
* is partly why it takes so long.
* (Marcus: the ptp2 driver does this by default currently.)
*/
printf("Cameras init. Takes about 10 seconds each.\n");
for (i = 0; i < count; i++)
{
retval = gp_camera_init(cams[i], context);
if (retval != GP_OK)
{
printf(" Camera [%d] init failed with retval %d\n", i, retval);
exit (1);
}
}
printf(" ----------------\n");
printf(" Sampler is ready \n");
printf(" ----------------\n");
printf("Usage : \n");
printf(" ESC - Exit the program\n");
printf(" i/I - Insert new product barcode manually\n");
#if defined(BARCODE_ENABLED)
printf(" b/B - Insert new product barcode using barcode-scanner\n");
#endif
char get_key;
char exit_key = 0;
char bcr_buf[128] = {0};
int hemispheres_counts = 0;
int rotar_steps = 0;
do
{
get_key = getchar();
switch (get_key)
{
// Gracefull Exit
case _ESC_:
exit_key = 1;
break;
// Manual insert mode
case 'i':
case 'I':
printf("ACTION: Type in the name.\n");
scanf("%128s", bcr_buf);
process:
press_enter();
printf("ACTION: Shall we start? press return key.\n");
press_enter();
hemispheres_counts = 0;
rotar_steps = 0;
char product_filename[256] = {0};
strcpy(product_filename, imgdb);
strcat(product_filename, bcr_buf);
if (directory_exists_or_create(product_filename))
{
printf("\n\n!!! ATTENTION: The product already exists !!!\n\n");
printf("\nEnter options:\n");
printf(" ESC - Exit the program\n");
printf(" i/I - Insert new product barcode manually\n");
#if defined(BARCODE_ENABLED)
printf(" b/B - Insert new product barcode using barcode-scanner\n");
#endif
break;
}
while (hemispheres_counts < MAX_HEMISPHERES)
{
while (rotar_steps < MAX_ROTAR_STEPS)
{
for (i = 0; i < count; i++)
{
capture_to_memory(cams[i], context, (const char**)&data, &size);
char fname[64] = {0};
char mk_filename[256] = {0};
strcpy(mk_filename, product_filename);
snprintf(fname, sizeof(fname), "/%d-%d-%d.jpg", i, hemispheres_counts, rotar_steps);
strcat(mk_filename, fname);
printf("file name %s\n", mk_filename);
f = fopen(mk_filename, "wb");
if (f)
{
retval = fwrite (data, size, 1, f);
if (retval != size)
{
printf(" fwrite size %ld, written %d\n", size, retval);
}
fclose(f);
}
else
{
printf(" fopen *.jpg failed. %s\n", strerror(errno));
}
usleep(500*1000);
}
rotar_steps++;
}
rotar_steps = 0;
hemispheres_counts++;
if (hemispheres_counts < MAX_HEMISPHERES)
{
printf("Flip the product and hit 'RETURN' key\n");
press_enter(); // This expect some input from user, thats it.
printf("Started capturing other hemisphere!\n");
} else {
printf("Sampling Done for barcode: %s\n", bcr_buf);
printf(" -------------------------------------\n");
printf("\nEnter options:\n");
printf(" ESC - Exit the program\n");
printf(" i/I - Insert new product barcode manually\n");
#if defined(BARCODE_ENABLED)
printf(" b/B - Insert new product barcode using barcode-scanner\n");
#endif
break;
}
}
break;
}
} while (exit_key != 1);
exit_:
/*
* Release all the resources.
*/
printf("\nReleasing all the resources ... \n");
for (i = 0; i < count; i++)
{
gp_camera_exit(cams[i], context);
}
if (cams) {
free(cams);
}
free(imgdb);
#if defined(BARCODE_ENABLED)
close_bcr();
#endif
printf("Done.\n");
return 0;
}

reason for runtime error in my c program &?

#include<stdio.h>
main()
{char *names[4];
int i,a;
printf("ënter the guests names\n");
for(i=0;i<=3;i++)
{
scanf("%s",names[i]);
}
char *yourname;
printf("\nenter your name ");
scanf("%c",yourname);
for(i=0;i<=3;i++)
{a=strcmp(names[i],yourname);
if(a==0)
printf("\nwelcome");
break;
}
if(a!=0)
printf("\naccess denied");
return 0;
}
this is a program to check your entry in a show. first we give permitted names & then it asks your name ,it compares your name with the names in the guest list.
i m getting runtime error, plz tell me the correction.i want to use pointers to string so plz suggest correction in the existing program
when i run this program in devc++ after entering first name it gives program.exe stopped working.
The code will be like this:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char *names[4];
int i,a;
printf("ënter the guests names\n");
for(i=0;i<=3;i++) {
names[i] = (char*) malloc(100 * sizeof(char));
scanf("%s", names[i]);
}
char yourname[100];
printf("\nenter your name ");
scanf("%s",yourname);
for(i=0;i<=3;i++) {
a = strcmp(names[i], yourname);
if (a == 0) break;
}
if (a==0)
printf("\nwelcome");
else printf("\naccess denied");
for(i=0;i<=3;i++)
free(names[i]);
return 0;
}
Your code have to be formated so we can give you a better answer.
Now, use gets to take your input, verify the guest match with your name inside the for loop, stop the loop when a match is found.
#include<stdio.h>
#include<string.h>
int main()
{
char names[4][20];
int i = 0;
int a = 0;
printf("Enter guests names: \n");
for(i=0; i<3; i++)
{
gets(names[i]);
}
char yourname[20];
printf("\n Enter your name ");
gets(yourname);
printf("\n Verify access right:");
for(i=0; i<3; i++)
{
a=strcmp(names[i], yourname);
if(a==0)
{
printf("\n welcome");
break;
}
else
{
printf("\n access denied");
}
}
return 0;
}
Although this looks like a homework assignment.

Trouble with creating an empty file using C programming language in UNIX environment

I have recently started programming in UNIX environment. I need to write a program which creates an empty file with name and size given in the terminal using this commands
gcc foo.c -o foo.o
./foo.o result.txt 1000
Here result.txt means the name of the newly created file, and 1000 means the size of the file in bytes.
I know for sure that lseek function moves the file offset, but the trouble is that whenever I run the program it creates a file with a given name, however the size of the file is 0.
Here is the code of my small program.
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
int main(int argc, char **argv)
{
int fd;
char *file_name;
off_t bytes;
mode_t mode;
if (argc < 3)
{
perror("There is not enough command-line arguments.");
//return 1;
}
file_name = argv[1];
bytes = atoi(argv[2]);
mode = S_IWUSR | S_IWGRP | S_IWOTH;
if ((fd = creat(file_name, mode)) < 0)
{
perror("File creation error.");
//return 1;
}
if (lseek(fd, bytes, SEEK_SET) == -1)
{
perror("Lseek function error.");
//return 1;
}
close(fd);
return 0;
}
If you aren't allowed to use any other functions to assist in creating a "blank" text file, why not change your file mode on creat() then loop-and-write:
int fd = creat(file_name, 0666);
for (int i=0; i < bytes; i++) {
int wbytes = write(fd, " ", 1);
if (wbytes < 0) {
perror("write error")
return 1;
}
}
You'll want to have some additional checks here but, that would be the general idea.
I don't know whats acceptable in your situation but, possibly adding just the write() call after lseek() even:
// XXX edit to include write
if ((fd = creat(file_name, 0666)) < 0) {
perror("File creation error");
//return 1;
}
// XXX seek to bytes - 1
if (lseek(fd, bytes - 1, SEEK_SET) == -1) {
perror("lseek() error");
//return 1;
}
// add this call to write a single byte # position set by lseek
if (write(fd, " ", 1) == -1) {
perror("write() error");
//return 1;
}
close(fd);
return 0;

Creating multiple child processes with a single pipe

I need to create three child processes, each of which reads a string from the command line arguments and writes the string to a single pipe. The parent would then read the strings from the pipe and display all three of them on the screen. I tried doing it for two processes to test and it is printing one of the strings twice as opposed to both of them.
#include <stdio.h>
#include <unistd.h>
int main (int argc, char *argv[]) {
char *character1 = argv[1];
char *character2 = argv[2];
char inbuf[100]; //creating an array with a max size of 100
int p[2]; // Pipe descriptor array
pid_t pid1; // defining pid1 of type pid_t
pid_t pid2; // defining pid2 of type pid_t
if (pipe(p) == -1) {
fprintf(stderr, "Pipe Failed"); // pipe fail
}
pid1 = fork(); // fork
if (pid1 < 0) {
fprintf(stderr, "Fork Failed"); // fork fail
}
else if (pid1 == 0){ // if child process 1
close(p[0]); // close the read end
write(p[1], character1, sizeof(&inbuf[0])); // write character 1 to the pipe
}
else { // if parent, create a second child process, child process 2
pid2 = fork();
if (pid2 < 0) {
fprintf(stderr, "Fork Failed"); // fork fail
}
if (pid2 = 0) { // if child process 2
close(p[0]); // close the read end
write(p[1], character2, sizeof(&inbuf[0])); // write character 2 to the pipe
}
else { // if parent process
close(p[1]); // close the write end
read(p[0], inbuf, sizeof(&inbuf[0])); // Read the pipe that both children write to
printf("%s\n", inbuf); // print
read(p[0], inbuf, sizeof(&inbuf[0])); // Read the pipe that both children write to
printf("%s\n", inbuf); // print
}
}
}
Your code doesn't keep looping until there's no more data to read. It does a single read. It also doesn't check the value returned by read(), but it should.
I've abstracted the fork() and write() (and error check) code into a function. This seems to work:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static void child(int fd, const char *string)
{
pid_t pid = fork();
int len = strlen(string);
if (pid < 0)
{
fprintf(stderr, "%.5d: failed to fork (%d: %s)\n",
(int)getpid(), errno, strerror(errno));
exit(1);
}
else if (pid > 0)
return;
else if (write(fd, string, len) != len)
{
fprintf(stderr, "%.5d: failed to write on pipe %d (%d: %s)\n",
(int)getpid(), fd, errno, strerror(errno));
exit(1);
}
else
exit(0);
}
int main (int argc, char *argv[])
{
char inbuf[100]; //creating an array with a max size of 100
int p[2]; // Pipe descriptor array
if (argc != 4)
{
fprintf(stderr, "Usage: %s str1 str2 str3\n", argv[0]);
return 1;
}
if (pipe(p) == -1)
{
fprintf(stderr, "Pipe Failed"); // pipe fail
return 1;
}
for (int i = 0; i < 3; i++)
child(p[1], argv[i+1]);
int nbytes;
close(p[1]); // close the write end
while ((nbytes = read(p[0], inbuf, sizeof(inbuf))) > 0)
printf("%.*s\n", nbytes, inbuf); // print
return 0;
}
I ran the command multiple times, each time using the command line:
./p3 'message 1' 'the second message' 'a third message for the third process'
On one run, the output was:
the second messagemessage 1
a third message for the third process
On another, I got:
the second messagemessage 1a third message for the third process
And on another, I got:
message 1
the second messagea third message for the third process
(This is on a MacBook Pro with Intel Core i7, running Mac OS X 10.8.3, and using GCC 4.7.1.)

Unix Client and Server Stuck in an Infinite Loop After Reading a File to the Client

I am currently making a simple client and server but I have run into an issue. Part of the system is for the client to query about a local file on the server. The contents of that file must be then sent to the client. I am able to send all the text within a file to the client however it seems to be stuck in the read loop on the client. Below are the code spits for both the client and server that are meant to deal with this:
Client Code That Reads The Loop
else if(strcmp(commandCopy, get) == 0)
{
char *ptr;
int total = 0;
char *arguments[1024];
char copy[2000];
char * temp;
int rc;
strcpy(copy, command);
ptr = strtok(copy," ");
while (ptr != NULL)
{
temp = (char *)malloc(sizeof(ptr));
temp = ptr;
arguments[total] = temp;
total++;
ptr = strtok (NULL, " ");
}
if(total == 4)
{
if (strcmp(arguments[2], "-f") == 0)
{
printf("1111111111111");
send(sockfd, command, sizeof(command), 0 );
printf("sent %s\n", command);
memset(&command, '\0', sizeof(command));
cc = recv(sockfd, command, 2000, 0);
if (cc == 0)
{
exit(0);
}
}
else
{
printf("Here");
strcpy(command, "a");
send(sockfd, command, sizeof(command), 0 );
printf("sent %s\n", command);
memset(&command, '\0', sizeof(command));
cc = recv(sockfd, command, 2000, 0);
}
}
else
{
send(sockfd, command, sizeof(command), 0 );
printf("sent %s\n", command);
memset(&command, '\0', sizeof(command));
while ((rc = read(sockfd, command, 1000)) > 0)
{
printf("%s", command);
}
if (rc)
perror("read");
}
}
Server Code That Reads the File
char* getRequest(char buf[], int fd)
{
char * ptr;
char results[1000];
int total = 0;
char *arguments[1024];
char data[100];
FILE * pFile;
pFile = fopen("test.txt", "r");
ptr = strtok(buf," ");
while (ptr != NULL)
{
char * temp;
temp = (char *)malloc(sizeof(ptr));
temp = ptr;
arguments[total] = temp;
total++;
ptr = strtok (NULL, " ");
}
if(total < 2)
{
strcpy(results, "Invaild Arguments \n");
return results;
}
if(pFile != NULL)
{
while(fgets(results, sizeof(results), pFile) != NULL)
{
//fputs(mystring, fd);
write(fd,results,strlen(results));
}
}
else
{
printf("Invalid File or Address \n");
}
fclose(pFile);
return "End of File \0";
}
Server Code to execute the command
else if(strcmp(command, "get") == 0)
{
int pid = fork();
if (pid ==-1)
{
printf("Failed To Fork...\n");
return-1;
}
if (pid !=0)
{
wait(NULL);
}
else
{
char* temp;
temp = getRequest(buf, newsockfd);
strcpy(buf, temp);
send(newsockfd, buf, sizeof(buf), 0 );
exit(1);
}
}
The whole else if clause in the client code is a bit large for a function, let alone a part of a function as it presumably is. The logic in the code is ... interesting. Let us dissect the first section:
else if (strcmp(commandCopy, get) == 0)
{
char *ptr;
int total = 0;
char *arguments[1024];
char *temp;
ptr = strtok(copy, " ");
while (ptr != NULL)
{
temp = (char *)malloc(sizeof(ptr));
temp = ptr;
arguments[total] = temp;
total++;
ptr = strtok(NULL, " ");
}
I've removed immaterial declarations and some code. The use of strtok() is fine in context, but the memory allocation is leaky. You allocate enough space for a character pointer, and then copy the pointer from strtok() over the only pointer to the allocated space (thus leaking it). Then the pointer is copied to arguments[total]. The code could, therefore, be simplified to:
else if (strcmp(commandCopy, get) == 0)
{
char *ptr;
int total = 0;
char *arguments[1024];
ptr = strtok(copy, " ");
while (ptr != NULL)
{
arguments[total++] = ptr;
ptr = strtok(NULL, " ");
}
Nominally, there should be a check that you don't overflow the arguments list, but since the original limits the string to 2000 characters, you can't have more than 1000 arguments (all single characters separated by single spaces).
What you have works - it achieves the same assignment the long way around, but it leaks memory prodigiously.
The main problem seems to be that the server sends all the contents, but it doesn't close the socket, so the client has no way of knowing the server's done. If you close the socket after you finish sending the data (or just call shutdown()), then the client's read() will return 0 when it finishes reading the data.
FWIW, there are lots of other problems with this code:
getRequest: you call malloc but never free. In fact, the return value is thrown away.
Why bother forking if you're just going to wait() on the child?
You probably want to use strlcpy instead of strpcy to avoid buffer overruns.

Resources