Fill file ASCII values - c

I want to create a file filled with 0 or other letters. Here's my function
int fill(const int d, struct aiocb *aiorp, void *buf, const int count){
int rv = 0;
memset( (void *)aiorp, 0, sizeof( struct aiocb ) ); // <-here second paramether is 0
aiorp->aio_fildes = d;
aiorp->aio_buf = buf;
aiorp->aio_nbytes = count;
aiorp->aio_offset = 0;
rv = aio_write( aiorp );
return rv;
}
Here's my main
int main(int argc, char * argv[]){
int des;
int rv;
struct aiocb aior;
char buffer[1000];
if(argc == 3){
printf("just %s\n", argv[1]);
des = createFile(argv[1]);
rv = fill(des, &aior, buffer, sizeof(buffer));
}
return 0;
}
So my output should be file filled with zero values, but my fle is filled with garbage
^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#$
y▒^X^#^#^#^#^#^#^#
s|▒^#^#^#^#^#^#^#^#^#^#^#^#▒r|▒^#^#^#^#▒▒^?▒(▒▒▒▒▒{▒▒
y▒^P^#^#^#▒
y▒^A^#^#^#d^Cy▒^#^#^#^#▒
y▒^T
y▒^P▒▒▒^#^#^#^#^#^#^#^
...
Why? What's wrong?
Here's the code :
sukurti - create new file if that file don't exist and
fill - fill created file
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <aio.h>
#define MB 1024
int sukurti(char *name);
int fill(const int d, struct aiocb *aiorp, void *buf, const int count);
int sukurti(char *name){
int dskr;
dskr = open( name, O_RDONLY );
if( dskr == -1 ){
printf("Failas sukurtas, nes jo nebuvo\n");
dskr = open( name, O_WRONLY | O_CREAT, 0644);
}else{
printf("Jau yra toks failas!\n");
exit(1);
}
return dskr;
}
int fill(const int d, struct aiocb *aiorp, void *buf, const int count){
int rv = 0;
memset( (void *)aiorp, 'A', sizeof( struct aiocb ) );
aiorp->aio_fildes = d;
aiorp->aio_buf = buf;
aiorp->aio_nbytes = count;
aiorp->aio_offset = 0;
rv = aio_write( aiorp );
return rv;
}
int main(int argc, char * argv[]){
int des;
int rv;
struct aiocb aior;
int x = atoi(argv[2]);
printf("%d\n", x);
int size = MB * MB * x;
char buffer[size];
if(argc == 3){
printf("just %s\n", argv[1]);
des = sukurti(argv[1]);
rv = fill(des, &aior, buffer, sizeof(buffer));
}else{
printf("Blogas\n");
}
return 0;
}
EDIT:
I know that my writting to file ends

Three ssues here:
buffer is not initalised. Do this using
memset(buffer,
<what ever 8bit value you want the file to be filled with>,
sizeof buffer);
right after defining it in main().
aior is initialise wrongly. Initialise it to all 0 using
memset(aiorb, 0, sizeof aior);
right after defining it in main() and remove the call to memset() in fill().
Finally the program most likely ends before the buffer had been asynchronously written to disk.
To fix this define a notification method as mentioned under man 7 aio. And make the program wait for this notification to be received before ending the program.
This for example can be done by asking for completion notification via signal and wait for this signal.
To do so modify your code as follows:
Add the following two lines to the intialisation of what aiorp is pointing to in fill():
aiorp->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
aiorp->aio_sigevent.sigev_signo = SIGUSR1;
To be able to handle the notifying signal sent (without ending the program) a signal handler needs to be setup:
void handler(int sig)
{
/* Do nothing. */
}
Install this handler by calling
signal(handler, SIGUSR1);
right at the beginning of the program.
Before returning from main() call wait_for_completion(SIGUSR1) which might look like this:
void wait_for_completion(int sig)
{
sigset_t set;
sigemptyset(&set);
sigaddset(&set, sig);
sigwait(&set, &sig); /* This blocks until sig had
been received by the program. */
printf("Completion notification for asynchronous 'write'-operation received.\n");
}
Add error handling as appropriate. I left it out for the sake of readability.

memset( (void *)aiorp, '0', sizeof( struct aiocb ) );
0 is not '0', you need to actually use the ASCII value (48 if i recall correctly.)

Related

Weird Malloc Error (and other problems involving this shell)

I am working on a Shell for a C Project I am working on, and I keep encountering this strange Malloc Error whenever I interact directly with the list that stores all of the jobs and processes, I always get a weird Malloc Error that looks someething like this:
What's going on here?
Can you please help me figure out what's going on with this thing? And if possible, perhaps you could maybe give me other suggestions for how to improve it as well? Cuz I would really appreciate it.
Here's the code below:
*
* $ gcc shell.c csapp.c -lpthread -o shell
*
*
* $ ./shell
*/
#include "csapp.h"
#define TRUE 1
#define FALSE 0
#define MAXARGS 128
#define MAXCHARS 64
pid_t fg_pid = 0;
int next_jid = 1;
typedef struct list_t
{
pid_t pid;
int jid;
char *runstat;
char *cmdline;
struct list_t *next;
} list_t;
list_t *jobs_list = NULL;
void add_element(list_t **list, pid_t pid, int jid, char *runstat, char *cmdline)
{
list_t *e;
if (*list == NULL) // New empty list.
{
*list = (list_t *) malloc(sizeof(list_t));
(*list)->pid = pid;
(*list)->jid = jid;
(*list)->runstat = strndup(runstat, MAXCHARS);
(*list)->cmdline = strndup(cmdline, MAXCHARS);
(*list)->next = NULL;
}
else // List with at least one element.
{
// Loop through elements, so that e is left
// pointing to the last one in the list.
for (e = *list; e->next != NULL; e = e->next)
; // (Do nothing.)
e->next = (list_t *) malloc(sizeof(list_t));
e = e->next;
e->pid = pid;
e->jid = jid;
e->runstat = strndup(runstat, MAXCHARS);
e->cmdline = strndup(cmdline, MAXCHARS);
e->next = NULL;
}
}
void fg_list_handler(list_t ** list, pid_t pid, int jid) {
}
void change_running_status(list_t **list, pid_t pid, char *runstat) {
//THe code I wrote with changing statuses in the list for programs.
list_t *e;
e = *list;
if (e->next == NULL) {
strncpy(e->runstat, runstat, MAXCHARS);
} else {
for (e; e != NULL; e->next) {
if (pid == e->pid) {
strncpy(e->runstat, runstat, MAXCHARS);
break;
}
}
}
}
void sigint_handler(int signal) {
// Restore default behavior for next SIGINT (which will likely
// come from call to raise at the end of this function).
Signal(SIGINT, SIG_DFL);
if (fg_pid != 0) {
Kill(-fg_pid, SIGINT); //Exits out of the child process (- = Send to group).
printf("Job %d has been terminated by: User Interrupt (SIGINT) \n", fg_pid);
Signal(SIGINT, sigint_handler);
} else {
// Send SIGINT to self. (This time won't be caught be handler,
// will instead cause process to terminate.)
raise(SIGINT);
}
}
void sigtstp_handler(int signal) {
//Restores SIGSTOP to normal behavior.
Signal(SIGTSTP, SIG_DFL);
//Stops the process.
if (fg_pid != 0) {
kill(-fg_pid, SIGTSTP);
printf("Job %d has been stopped by: User Stop (SIGTSTP)\n", fg_pid);
Signal(SIGTSTP, sigtstp_handler);
} else {
raise(SIGTSTP);
}
}
/*
* Populate argv with pointers to places in line where arguments
* begin (and put \0 in buf where arguments end), so that argv[0] is
* pointer to first argument, argv[1] pointer to second, etc.
*
* (You should't need to make any changes to this function.)
*/
int parseline(char *line, char **argv) {
char *cp;
int in_arg = FALSE;
int argc = 0;
int bg = FALSE;
// Go through line, one character at a time, until reaching the
// newline character at the end.
for (cp = line; *cp != '\n'; cp++) {
if (in_arg) {
// If at the end of an argument...
if (*cp == ' ') {
*cp = '\0'; // Mark end of argument.
in_arg = FALSE;
}
} else if (*cp != ' ') { // If at beginning of new argument...
argv[argc++] = cp; // Set argv array element to point to
// new argument.
in_arg = TRUE;
}
}
*cp = '\0'; // Mark end of last argument (which was probably
// followed by \n, not space).
// If at least one argument, and last argument is &, process is
// to be run in background.
if (argc > 0 && *argv[argc - 1] == '&') {
bg = TRUE;
argv[argc - 1] = NULL; // Overwrite address of "&" to mark
// end of argv.
} else { // (Process should run in foreground.)
argv[argc] = NULL; // Mark end of argv.
}
return bg;
}
/*
* If argv[0] is a builtin command, run it and return TRUE. If it's
* not, return FALSE.
*/
int builtin_command(char **argv) {
if (strcmp(argv[0], "quit") == 0) {
// (Don't bother to return, just end the program.)
exit(0);
} else if (strcmp(argv[0], "&") == 0) {
// (Ignore & if it isn't preceded by a command.)
return TRUE;
} else if (strcmp(argv[0], "jobs") == 0) {
// Prints list of background and stopped jobs.
list_t *e;
char *runstat[MAXLINE];
for (e = jobs_list; e != NULL; e = e->next) {
strncpy(runstat, e->runstat, MAXCHARS);
//Eventually going to add an additional argument to allow it to print different lists depending on the argument.
//Prints the process only if it's currently running in the system.
if (strncmp(e->runstat, "running", MAXCHARS) == 0) {
printf("[%d], %d, %s, %s", e->jid, e->pid, e->runstat, e->cmdline);
}
}
return TRUE;
} else if (strcmp(argv[0], "bg")) {
}
return FALSE;
}
/*
* Evaluate command (a line of arguments).
*/
void eval(char *cmdline, char **envp) {
char *argv[MAXARGS];
char buf[MAXLINE];
int bg;
pid_t pid;
int jid;
char *runstat[MAXLINE];
//Used for my current implementation of status checking.
int status;
// Copy cmdline to buf, use parseline to populate argv based
// on what's in buf (and set bg based on value returned from
// parseline).
strcpy(buf, cmdline);
bg = parseline(buf, argv);
// If at least one argument, and it's not a builtin command...
// (If it is a builtin command the builtin_command function will
// run it too, not just check whether it's builtin.)
if (argv[0] != NULL && !builtin_command(argv)) {
pid = Fork();
if (pid == 0) { // In child.
//Added to work with child processes and groups of processes.
pid = getpid();
setpgid(pid, pid);
if (execve(argv[0], argv, envp) < 0) {
printf("%s is an invalid command.\n", argv[0]);
exit(0);
}
} else if (!bg) { // In parent, child running in foreground.
fg_pid = pid;
strncpy(runstat, "running", MAXCHARS);
jid = next_jid++;
//Testing Print.
printf("[%d] %d %s %s", jid, pid, runstat, cmdline);
add_element(&jobs_list, pid, jid, runstat, cmdline);
if (waitpid(pid, &status, WUNTRACED) != 0)
{
if (fg_pid != 0) {
//added check due to the first if executing down here for no reason.
if (WIFEXITED(status) >= 1) {
strncpy(runstat, "exited", MAXCHARS);
//change_running_status(&jobs_list, pid, runstat);
printf("[%d] %d %s %s", jid, pid, runstat, cmdline);
} else if (WIFSIGNALED(status) >= 1) {
strncpy(runstat, "interrupted", MAXCHARS);
//change_running_status(&jobs_list, pid, runstat);
printf("[%d] %d %s %s", jid, pid, runstat, cmdline);
} else if (WIFSTOPPED(status) >= 1) {
strncpy(runstat, "stopped", MAXCHARS);
change_running_status(&jobs_list, pid, runstat);
printf("[%d] %d %s %s", jid, pid, runstat, cmdline);
}
}
}
fg_pid = 0;
} else { // In parent, child running in background.
//Implemented the whole running thing in my usual crude methods of doing so.
strncpy(runstat, "running", MAXCHARS);
jid = next_jid++;
//runstat = 'Running';
//printf("[%d] %d %s %s", jid, pid, runstat, cmdline);
add_element(&jobs_list, pid, jid, runstat, cmdline);
}
}
}
int main(int argc, char **argv, char **envp) {
char cmdline[MAXLINE];
Signal(SIGINT, sigint_handler);
Signal(SIGTSTP, sigtstp_handler);
while (TRUE) { // exit(0) will be called from builtin_command
// if user enters "quit" command.
printf("> ");
Fgets(cmdline, MAXLINE, stdin);
eval(cmdline, envp);
}
}
dont use strndup() or strncpy() before you have read their man pages
[after using the man pages you would not use them anyway]
dont use printf() and friends in signal handlers; they are not signal-safe.
Sleeper.c:
/*
* sleeper.c
*/
/*
* Get csapp.h and csapp.c from http://csapp.cs.cmu.edu/3e/code.html
*
* $ gcc sleeper.c csapp.c -o sleeper
*
* (Ignore any compliation warnings related to code in csapp.c.)
*
* $ ./sleeper
*
* ... CTRL-C to terminate and see message indicating sleeper
* caught SIGINT. CTRL-Z to stop and see message indicating
* sleeper caught SIGTSTP. "jobs" to see list of stopped jobs
* with numerical IDs (including ./sleeper). "fg %1" to restart
* job with ID 1 (i.e., sleeper) and see message indicating
* sleeper caught SIGCONT.
*/
#include "csapp.h"
int pid;
pid_t fg_pid;
void sigint_handler(int signal) {
// Restore default behavior for next SIGINT (which will likely
// come from call to raise at the end of this function).
Signal(SIGINT, SIG_DFL);
printf("\nsleeper (%d) caught SIGINT\n", pid);
// Send SIGINT to self. (This time won't be caught be handler,
// will instead cause process to terminate.)
raise(SIGINT);
}
void sigtstp_handler(int signal) {
// Restore default behavior for next SIGTSTP ...
Signal(SIGTSTP, SIG_DFL);
printf("\nsleeper (%d) caught SIGTSTP\n", pid);
// Send SIGTSTP to self ...
raise(SIGTSTP);
}
void sigcont_handler(int signal) {
// Don't need to restore default behavior of SIGCONT, because
// default (for already running process) is to ignore it.
// Prepare for next SIGTSTP signal.
Signal(SIGTSTP, sigtstp_handler);
printf("\nsleeper (%d) caught SIGCONT\n", pid);
// Don't need to raise SIGCONT, because process is already
// running (and would ignore it).
}
// First command line argument is number of times to sleep. (0
// or no argument means to continue indefinitely.) Second argument
// -q for quiet sleeper.
int main(int argc, char **argv) {
int i, n, q;
n = argc > 1 ? atoi(argv[1]) : 0;
q = argc > 2 && strcmp("-q", argv[2]) == 0;
pid = getpid();
// Override default behavior for SIGINT, SIGTSTP and SIGCONT.
Signal(SIGINT, sigint_handler);
Signal(SIGTSTP, sigtstp_handler);
Signal(SIGCONT, sigcont_handler);
// Sleep 1 second, wake up, go back to sleep...
for (i = 0; n == 0 || i < n; i++) {
Sleep(1);
if (!q) {
printf("sleeper (%d) slept %d second(s)\n", pid, i + 1);
}
}
return 0;
}
Oh, and that's not all the code. There are several other files (ignore the errors with CSAPP.c. They resolve themselves when you use lpthread in compiling).
* csapp.h
*/
/* $begin csapp.h */
#ifndef __CSAPP_H__
#define __CSAPP_H__
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <setjmp.h>
#include <signal.h>
#include <dirent.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <errno.h>
#include <math.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
/* Default file permissions are DEF_MODE & ~DEF_UMASK */
/* $begin createmasks */
#define DEF_MODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH
#define DEF_UMASK S_IWGRP|S_IWOTH
/* $end createmasks */
/* Simplifies calls to bind(), connect(), and accept() */
/* $begin sockaddrdef */
typedef struct sockaddr SA;
/* $end sockaddrdef */
/* Persistent state for the robust I/O (Rio) package */
/* $begin rio_t */
#define RIO_BUFSIZE 8192
typedef struct {
int rio_fd; /* Descriptor for this internal buf */
int rio_cnt; /* Unread bytes in internal buf */
char *rio_bufptr; /* Next unread byte in internal buf */
char rio_buf[RIO_BUFSIZE]; /* Internal buffer */
} rio_t;
/* $end rio_t */
/* External variables */
extern int h_errno; /* Defined by BIND for DNS errors */
extern char **environ; /* Defined by libc */
/* Misc constants */
#define MAXLINE 8192 /* Max text line length */
#define MAXBUF 8192 /* Max I/O buffer size */
#define LISTENQ 1024 /* Second argument to listen() */
/* Our own error-handling functions */
void unix_error(char *msg);
void posix_error(int code, char *msg);
void dns_error(char *msg);
void gai_error(int code, char *msg);
void app_error(char *msg);
/* Process control wrappers */
pid_t Fork(void);
void Execve(const char *filename, char *const argv[], char *const envp[]);
pid_t Wait(int *status);
pid_t Waitpid(pid_t pid, int *iptr, int options);
void Kill(pid_t pid, int signum);
unsigned int Sleep(unsigned int secs);
void Pause(void);
unsigned int Alarm(unsigned int seconds);
void Setpgid(pid_t pid, pid_t pgid);
pid_t Getpgrp();
/* Signal wrappers */
typedef void handler_t(int);
handler_t *Signal(int signum, handler_t *handler);
void Sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
void Sigemptyset(sigset_t *set);
void Sigfillset(sigset_t *set);
void Sigaddset(sigset_t *set, int signum);
void Sigdelset(sigset_t *set, int signum);
int Sigismember(const sigset_t *set, int signum);
int Sigsuspend(const sigset_t *set);
/* Sio (Signal-safe I/O) routines */
ssize_t sio_puts(char s[]);
ssize_t sio_putl(long v);
void sio_error(char s[]);
/* Sio wrappers */
ssize_t Sio_puts(char s[]);
ssize_t Sio_putl(long v);
void Sio_error(char s[]);
/* Unix I/O wrappers */
int Open(const char *pathname, int flags, mode_t mode);
ssize_t Read(int fd, void *buf, size_t count);
ssize_t Write(int fd, const void *buf, size_t count);
off_t Lseek(int fildes, off_t offset, int whence);
void Close(int fd);
int Select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
struct timeval *timeout);
int Dup2(int fd1, int fd2);
void Stat(const char *filename, struct stat *buf);
void Fstat(int fd, struct stat *buf) ;
/* Directory wrappers */
DIR *Opendir(const char *name);
struct dirent *Readdir(DIR *dirp);
int Closedir(DIR *dirp);
/* Memory mapping wrappers */
void *Mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);
void Munmap(void *start, size_t length);
/* Standard I/O wrappers */
void Fclose(FILE *fp);
FILE *Fdopen(int fd, const char *type);
char *Fgets(char *ptr, int n, FILE *stream);
FILE *Fopen(const char *filename, const char *mode);
void Fputs(const char *ptr, FILE *stream);
size_t Fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
void Fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
/* Dynamic storage allocation wrappers */
void *Malloc(size_t size);
void *Realloc(void *ptr, size_t size);
void *Calloc(size_t nmemb, size_t size);
void Free(void *ptr);
/* Sockets interface wrappers */
int Socket(int domain, int type, int protocol);
void Setsockopt(int s, int level, int optname, const void *optval, int optlen);
void Bind(int sockfd, struct sockaddr *my_addr, int addrlen);
void Listen(int s, int backlog);
int Accept(int s, struct sockaddr *addr, socklen_t *addrlen);
void Connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
/* Protocol independent wrappers */
void Getaddrinfo(const char *node, const char *service,
const struct addrinfo *hints, struct addrinfo **res);
void Getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host,
size_t hostlen, char *serv, size_t servlen, int flags);
void Freeaddrinfo(struct addrinfo *res);
void Inet_ntop(int af, const void *src, char *dst, socklen_t size);
void Inet_pton(int af, const char *src, void *dst);
/* DNS wrappers */
struct hostent *Gethostbyname(const char *name);
struct hostent *Gethostbyaddr(const char *addr, int len, int type);
/* Pthreads thread control wrappers */
void Pthread_create(pthread_t *tidp, pthread_attr_t *attrp,
void * (*routine)(void *), void *argp);
void Pthread_join(pthread_t tid, void **thread_return);
void Pthread_cancel(pthread_t tid);
void Pthread_detach(pthread_t tid);
void Pthread_exit(void *retval);
pthread_t Pthread_self(void);
void Pthread_once(pthread_once_t *once_control, void (*init_function)());
/* POSIX semaphore wrappers */
void Sem_init(sem_t *sem, int pshared, unsigned int value);
void P(sem_t *sem);
void V(sem_t *sem);
/* Rio (Robust I/O) package */
ssize_t rio_readn(int fd, void *usrbuf, size_t n);
ssize_t rio_writen(int fd, void *usrbuf, size_t n);
void rio_readinitb(rio_t *rp, int fd);
ssize_t rio_readnb(rio_t *rp, void *usrbuf, size_t n);
ssize_t rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen);
/* Wrappers for Rio package */
ssize_t Rio_readn(int fd, void *usrbuf, size_t n);
void Rio_writen(int fd, void *usrbuf, size_t n);
void Rio_readinitb(rio_t *rp, int fd);
ssize_t Rio_readnb(rio_t *rp, void *usrbuf, size_t n);
ssize_t Rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen);
/* Reentrant protocol-independent client/server helpers */
int open_clientfd(char *hostname, char *port);
int open_listenfd(char *port);
/* Wrappers for reentrant protocol-independent client/server helpers */
int Open_clientfd(char *hostname, char *port);
int Open_listenfd(char *port);
#endif /* __CSAPP_H__ */
/* $end csapp.h */```
csapp.c:
* csapp.c
*/
/* $begin csapp.c */
#include "csapp.h"
/**************************
* Error-handling functions
**************************/
/* $begin errorfuns */
/* $begin unixerror */
void unix_error(char *msg) /* Unix-style error */
{
fprintf(stderr, "%s: %s\n", msg, strerror(errno));
exit(0);
}
/* $end unixerror */
void posix_error(int code, char *msg) /* Posix-style error */
{
fprintf(stderr, "%s: %s\n", msg, strerror(code));
exit(0);
}
void gai_error(int code, char *msg) /* Getaddrinfo-style error */
{
fprintf(stderr, "%s: %s\n", msg, gai_strerror(code));
exit(0);
}
void app_error(char *msg) /* Application error */
{
fprintf(stderr, "%s\n", msg);
exit(0);
}
/* $end errorfuns */
void dns_error(char *msg) /* Obsolete gethostbyname error */
{
fprintf(stderr, "%s\n", msg);
exit(0);
}
/*********************************************
* Wrappers for Unix process control functions
********************************************/
/* $begin forkwrapper */
pid_t Fork(void)
{
pid_t pid;
if ((pid = fork()) < 0)
unix_error("Fork error");
return pid;
}
/* $end forkwrapper */
void Execve(const char *filename, char *const argv[], char *const envp[])
{
if (execve(filename, argv, envp) < 0)
unix_error("Execve error");
}
/* $begin wait */
pid_t Wait(int *status)
{
pid_t pid;
if ((pid = wait(status)) < 0)
unix_error("Wait error");
return pid;
}
/* $end wait */
pid_t Waitpid(pid_t pid, int *iptr, int options)
{
pid_t retpid;
if ((retpid = waitpid(pid, iptr, options)) < 0)
unix_error("Waitpid error");
return(retpid);
}
/* $begin kill */
void Kill(pid_t pid, int signum)
{
int rc;
if ((rc = kill(pid, signum)) < 0)
unix_error("Kill error");
}
/* $end kill */
void Pause()
{
(void)pause();
return;
}
unsigned int Sleep(unsigned int secs)
{
unsigned int rc;
if ((rc = sleep(secs)) < 0)
unix_error("Sleep error");
return rc;
}
unsigned int Alarm(unsigned int seconds) {
return alarm(seconds);
}
void Setpgid(pid_t pid, pid_t pgid) {
int rc;
if ((rc = setpgid(pid, pgid)) < 0)
unix_error("Setpgid error");
return;
}
pid_t Getpgrp(void) {
return getpgrp();
}
/************************************
* Wrappers for Unix signal functions
***********************************/
/* $begin sigaction */
handler_t *Signal(int signum, handler_t *handler)
{
struct sigaction action, old_action;
action.sa_handler = handler;
sigemptyset(&action.sa_mask); /* Block sigs of type being handled */
action.sa_flags = SA_RESTART; /* Restart syscalls if possible */
if (sigaction(signum, &action, &old_action) < 0)
unix_error("Signal error");
return (old_action.sa_handler);
}
/* $end sigaction */
void Sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
{
if (sigprocmask(how, set, oldset) < 0)
unix_error("Sigprocmask error");
return;
}
void Sigemptyset(sigset_t *set)
{
if (sigemptyset(set) < 0)
unix_error("Sigemptyset error");
return;
}
void Sigfillset(sigset_t *set)
{
if (sigfillset(set) < 0)
unix_error("Sigfillset error");
return;
}
void Sigaddset(sigset_t *set, int signum)
{
if (sigaddset(set, signum) < 0)
unix_error("Sigaddset error");
return;
}
void Sigdelset(sigset_t *set, int signum)
{
if (sigdelset(set, signum) < 0)
unix_error("Sigdelset error");
return;
}
int Sigismember(const sigset_t *set, int signum)
{
int rc;
if ((rc = sigismember(set, signum)) < 0)
unix_error("Sigismember error");
return rc;
}
int Sigsuspend(const sigset_t *set)
{
int rc = sigsuspend(set); /* always returns -1 */
if (errno != EINTR)
unix_error("Sigsuspend error");
return rc;
}
/*************************************************************
* The Sio (Signal-safe I/O) package - simple reentrant output
* functions that are safe for signal handlers.
*************************************************************/
/* Private sio functions */
/* $begin sioprivate */
/* sio_reverse - Reverse a string (from K&R) */
static void sio_reverse(char s[])
{
int c, i, j;
for (i = 0, j = strlen(s)-1; i < j; i++, j--) {
c = s[i];
s[i] = s[j];
s[j] = c;
}
}
/* sio_ltoa - Convert long to base b string (from K&R) */
static void sio_ltoa(long v, char s[], int b)
{
int c, i = 0;
int neg = v < 0;
if (neg)
v = -v;
do {
s[i++] = ((c = (v % b)) < 10) ? c + '0' : c - 10 + 'a';
} while ((v /= b) > 0);
if (neg)
s[i++] = '-';
s[i] = '\0';
sio_reverse(s);
}
/* sio_strlen - Return length of string (from K&R) */
static size_t sio_strlen(char s[])
{
int i = 0;
while (s[i] != '\0')
++i;
return i;
}
/* $end sioprivate */
/* Public Sio functions */
/* $begin siopublic */
ssize_t sio_puts(char s[]) /* Put string */
{
return write(STDOUT_FILENO, s, sio_strlen(s)); //line:csapp:siostrlen
}
ssize_t sio_putl(long v) /* Put long */
{
char s[128];
sio_ltoa(v, s, 10); /* Based on K&R itoa() */ //line:csapp:sioltoa
return sio_puts(s);
}
void sio_error(char s[]) /* Put error message and exit */
{
sio_puts(s);
_exit(1); //line:csapp:sioexit
}
/* $end siopublic */
/*******************************
* Wrappers for the SIO routines
******************************/
ssize_t Sio_putl(long v)
{
ssize_t n;
if ((n = sio_putl(v)) < 0)
sio_error("Sio_putl error");
return n;
}
ssize_t Sio_puts(char s[])
{
ssize_t n;
if ((n = sio_puts(s)) < 0)
sio_error("Sio_puts error");
return n;
}
void Sio_error(char s[])
{
sio_error(s);
}
/********************************
* Wrappers for Unix I/O routines
********************************/
int Open(const char *pathname, int flags, mode_t mode)
{
int rc;
if ((rc = open(pathname, flags, mode)) < 0)
unix_error("Open error");
return rc;
}
ssize_t Read(int fd, void *buf, size_t count)
{
ssize_t rc;
if ((rc = read(fd, buf, count)) < 0)
unix_error("Read error");
return rc;
}
ssize_t Write(int fd, const void *buf, size_t count)
{
ssize_t rc;
if ((rc = write(fd, buf, count)) < 0)
unix_error("Write error");
return rc;
}
off_t Lseek(int fildes, off_t offset, int whence)
{
off_t rc;
if ((rc = lseek(fildes, offset, whence)) < 0)
unix_error("Lseek error");
return rc;
}
void Close(int fd)
{
int rc;
if ((rc = close(fd)) < 0)
unix_error("Close error");
}
int Select(int n, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout)
{
int rc;
if ((rc = select(n, readfds, writefds, exceptfds, timeout)) < 0)
unix_error("Select error");
return rc;
}
int Dup2(int fd1, int fd2)
{
int rc;
if ((rc = dup2(fd1, fd2)) < 0)
unix_error("Dup2 error");
return rc;
}
void Stat(const char *filename, struct stat *buf)
{
if (stat(filename, buf) < 0)
unix_error("Stat error");
}
void Fstat(int fd, struct stat *buf)
{
if (fstat(fd, buf) < 0)
unix_error("Fstat error");
}
/*********************************
* Wrappers for directory function
*********************************/
DIR *Opendir(const char *name)
{
DIR *dirp = opendir(name);
if (!dirp)
unix_error("opendir error");
return dirp;
}
struct dirent *Readdir(DIR *dirp)
{
struct dirent *dep;
errno = 0;
dep = readdir(dirp);
if ((dep == NULL) && (errno != 0))
unix_error("readdir error");
return dep;
}
int Closedir(DIR *dirp)
{
int rc;
if ((rc = closedir(dirp)) < 0)
unix_error("closedir error");
return rc;
}
/***************************************
* Wrappers for memory mapping functions
***************************************/
void *Mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset)
{
void *ptr;
if ((ptr = mmap(addr, len, prot, flags, fd, offset)) == ((void *) -1))
unix_error("mmap error");
return(ptr);
}
void Munmap(void *start, size_t length)
{
if (munmap(start, length) < 0)
unix_error("munmap error");
}
/***************************************************
* Wrappers for dynamic storage allocation functions
***************************************************/
void *Malloc(size_t size)
{
void *p;
if ((p = malloc(size)) == NULL)
unix_error("Malloc error");
return p;
}
void *Realloc(void *ptr, size_t size)
{
void *p;
if ((p = realloc(ptr, size)) == NULL)
unix_error("Realloc error");
return p;
}
void *Calloc(size_t nmemb, size_t size)
{
void *p;
if ((p = calloc(nmemb, size)) == NULL)
unix_error("Calloc error");
return p;
}
void Free(void *ptr)
{
free(ptr);
}
/******************************************
* Wrappers for the Standard I/O functions.
******************************************/
void Fclose(FILE *fp)
{
if (fclose(fp) != 0)
unix_error("Fclose error");
}
FILE *Fdopen(int fd, const char *type)
{
FILE *fp;
if ((fp = fdopen(fd, type)) == NULL)
unix_error("Fdopen error");
return fp;
}
char *Fgets(char *ptr, int n, FILE *stream)
{
char *rptr;
if (((rptr = fgets(ptr, n, stream)) == NULL) && ferror(stream))
app_error("Fgets error");
return rptr;
}
FILE *Fopen(const char *filename, const char *mode)
{
FILE *fp;
if ((fp = fopen(filename, mode)) == NULL)
unix_error("Fopen error");
return fp;
}
void Fputs(const char *ptr, FILE *stream)
{
if (fputs(ptr, stream) == EOF)
unix_error("Fputs error");
}
size_t Fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
size_t n;
if (((n = fread(ptr, size, nmemb, stream)) < nmemb) && ferror(stream))
unix_error("Fread error");
return n;
}
void Fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
{
if (fwrite(ptr, size, nmemb, stream) < nmemb)
unix_error("Fwrite error");
}
/****************************
* Sockets interface wrappers
****************************/
int Socket(int domain, int type, int protocol)
{
int rc;
if ((rc = socket(domain, type, protocol)) < 0)
unix_error("Socket error");
return rc;
}
void Setsockopt(int s, int level, int optname, const void *optval, int optlen)
{
int rc;
if ((rc = setsockopt(s, level, optname, optval, optlen)) < 0)
unix_error("Setsockopt error");
}
void Bind(int sockfd, struct sockaddr *my_addr, int addrlen)
{
int rc;
if ((rc = bind(sockfd, my_addr, addrlen)) < 0)
unix_error("Bind error");
}
void Listen(int s, int backlog)
{
int rc;
if ((rc = listen(s, backlog)) < 0)
unix_error("Listen error");
}
int Accept(int s, struct sockaddr *addr, socklen_t *addrlen)
{
int rc;
if ((rc = accept(s, addr, addrlen)) < 0)
unix_error("Accept error");
return rc;
}
void Connect(int sockfd, struct sockaddr *serv_addr, int addrlen)
{
int rc;
if ((rc = connect(sockfd, serv_addr, addrlen)) < 0)
unix_error("Connect error");
}
/*******************************
* Protocol-independent wrappers
*******************************/
/* $begin getaddrinfo */
void Getaddrinfo(const char *node, const char *service,
const struct addrinfo *hints, struct addrinfo **res)
{
int rc;
if ((rc = getaddrinfo(node, service, hints, res)) != 0)
gai_error(rc, "Getaddrinfo error");
}
/* $end getaddrinfo */
void Getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host,
size_t hostlen, char *serv, size_t servlen, int flags)
{
int rc;
if ((rc = getnameinfo(sa, salen, host, hostlen, serv,
servlen, flags)) != 0)
gai_error(rc, "Getnameinfo error");
}
void Freeaddrinfo(struct addrinfo *res)
{
freeaddrinfo(res);
}
void Inet_ntop(int af, const void *src, char *dst, socklen_t size)
{
if (!inet_ntop(af, src, dst, size))
unix_error("Inet_ntop error");
}
void Inet_pton(int af, const char *src, void *dst)
{
int rc;
rc = inet_pton(af, src, dst);
if (rc == 0)
app_error("inet_pton error: invalid dotted-decimal address");
else if (rc < 0)
unix_error("Inet_pton error");
}
/*******************************************
* DNS interface wrappers.
*
* NOTE: These are obsolete because they are not thread safe. Use
* getaddrinfo and getnameinfo instead
***********************************/
/* $begin gethostbyname */
struct hostent *Gethostbyname(const char *name)
{
struct hostent *p;
if ((p = gethostbyname(name)) == NULL)
dns_error("Gethostbyname error");
return p;
}
/* $end gethostbyname */
struct hostent *Gethostbyaddr(const char *addr, int len, int type)
{
struct hostent *p;
if ((p = gethostbyaddr(addr, len, type)) == NULL)
dns_error("Gethostbyaddr error");
return p;
}
/************************************************
* Wrappers for Pthreads thread control functions
************************************************/
void Pthread_create(pthread_t *tidp, pthread_attr_t *attrp,
void * (*routine)(void *), void *argp)
{
int rc;
if ((rc = pthread_create(tidp, attrp, routine, argp)) != 0)
posix_error(rc, "Pthread_create error");
}
void Pthread_cancel(pthread_t tid) {
int rc;
if ((rc = pthread_cancel(tid)) != 0)
posix_error(rc, "Pthread_cancel error");
}
void Pthread_join(pthread_t tid, void **thread_return) {
int rc;
if ((rc = pthread_join(tid, thread_return)) != 0)
posix_error(rc, "Pthread_join error");
}
/* $begin detach */
void Pthread_detach(pthread_t tid) {
int rc;
if ((rc = pthread_detach(tid)) != 0)
posix_error(rc, "Pthread_detach error");
}
/* $end detach */
void Pthread_exit(void *retval) {
pthread_exit(retval);
}
pthread_t Pthread_self(void) {
return pthread_self();
}
void Pthread_once(pthread_once_t *once_control, void (*init_function)()) {
pthread_once(once_control, init_function);
}
/*******************************
* Wrappers for Posix semaphores
*******************************/
void Sem_init(sem_t *sem, int pshared, unsigned int value)
{
if (sem_init(sem, pshared, value) < 0)
unix_error("Sem_init error");
}
void P(sem_t *sem)
{
if (sem_wait(sem) < 0)
unix_error("P error");
}
void V(sem_t *sem)
{
if (sem_post(sem) < 0)
unix_error("V error");
}
/****************************************
* The Rio package - Robust I/O functions
****************************************/
/*
* rio_readn - Robustly read n bytes (unbuffered)
*/
/* $begin rio_readn */
ssize_t rio_readn(int fd, void *usrbuf, size_t n)
{
size_t nleft = n;
ssize_t nread;
char *bufp = usrbuf;
while (nleft > 0) {
if ((nread = read(fd, bufp, nleft)) < 0) {
if (errno == EINTR) /* Interrupted by sig handler return */
nread = 0; /* and call read() again */
else
return -1; /* errno set by read() */
}
else if (nread == 0)
break; /* EOF */
nleft -= nread;
bufp += nread;
}
return (n - nleft); /* Return >= 0 */
}
/* $end rio_readn */
/*
* rio_writen - Robustly write n bytes (unbuffered)
*/
/* $begin rio_writen */
ssize_t rio_writen(int fd, void *usrbuf, size_t n)
{
size_t nleft = n;
ssize_t nwritten;
char *bufp = usrbuf;
while (nleft > 0) {
if ((nwritten = write(fd, bufp, nleft)) <= 0) {
if (errno == EINTR) /* Interrupted by sig handler return */
nwritten = 0; /* and call write() again */
else
return -1; /* errno set by write() */
}
nleft -= nwritten;
bufp += nwritten;
}
return n;
}
/* $end rio_writen */
/*
* rio_read - This is a wrapper for the Unix read() function that
* transfers min(n, rio_cnt) bytes from an internal buffer to a user
* buffer, where n is the number of bytes requested by the user and
* rio_cnt is the number of unread bytes in the internal buffer. On
* entry, rio_read() refills the internal buffer via a call to
* read() if the internal buffer is empty.
*/
/* $begin rio_read */
static ssize_t rio_read(rio_t *rp, char *usrbuf, size_t n)
{
int cnt;
while (rp->rio_cnt <= 0) { /* Refill if buf is empty */
rp->rio_cnt = read(rp->rio_fd, rp->rio_buf,
sizeof(rp->rio_buf));
if (rp->rio_cnt < 0) {
if (errno != EINTR) /* Interrupted by sig handler return */
return -1;
}
else if (rp->rio_cnt == 0) /* EOF */
return 0;
else
rp->rio_bufptr = rp->rio_buf; /* Reset buffer ptr */
}
/* Copy min(n, rp->rio_cnt) bytes from internal buf to user buf */
cnt = n;
if (rp->rio_cnt < n)
cnt = rp->rio_cnt;
memcpy(usrbuf, rp->rio_bufptr, cnt);
rp->rio_bufptr += cnt;
rp->rio_cnt -= cnt;
return cnt;
}
/* $end rio_read */
/*
* rio_readinitb - Associate a descriptor with a read buffer and reset buffer
*/
/* $begin rio_readinitb */
void rio_readinitb(rio_t *rp, int fd)
{
rp->rio_fd = fd;
rp->rio_cnt = 0;
rp->rio_bufptr = rp->rio_buf;
}
/* $end rio_readinitb */
/*
* rio_readnb - Robustly read n bytes (buffered)
*/
/* $begin rio_readnb */
ssize_t rio_readnb(rio_t *rp, void *usrbuf, size_t n)
{
size_t nleft = n;
ssize_t nread;
char *bufp = usrbuf;
while (nleft > 0) {
if ((nread = rio_read(rp, bufp, nleft)) < 0)
return -1; /* errno set by read() */
else if (nread == 0)
break; /* EOF */
nleft -= nread;
bufp += nread;
}
return (n - nleft); /* return >= 0 */
}
/* $end rio_readnb */
/*
* rio_readlineb - Robustly read a text line (buffered)
*/
/* $begin rio_readlineb */
ssize_t rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen)
{
int n, rc;
char c, *bufp = usrbuf;
for (n = 1; n < maxlen; n++) {
if ((rc = rio_read(rp, &c, 1)) == 1) {
*bufp++ = c;
if (c == '\n') {
n++;
break;
}
} else if (rc == 0) {
if (n == 1)
return 0; /* EOF, no data read */
else
break; /* EOF, some data was read */
} else
return -1; /* Error */
}
*bufp = 0;
return n-1;
}
/* $end rio_readlineb */
/**********************************
* Wrappers for robust I/O routines
**********************************/
ssize_t Rio_readn(int fd, void *ptr, size_t nbytes)
{
ssize_t n;
if ((n = rio_readn(fd, ptr, nbytes)) < 0)
unix_error("Rio_readn error");
return n;
}
void Rio_writen(int fd, void *usrbuf, size_t n)
{
if (rio_writen(fd, usrbuf, n) != n)
unix_error("Rio_writen error");
}
void Rio_readinitb(rio_t *rp, int fd)
{
rio_readinitb(rp, fd);
}
ssize_t Rio_readnb(rio_t *rp, void *usrbuf, size_t n)
{
ssize_t rc;
if ((rc = rio_readnb(rp, usrbuf, n)) < 0)
unix_error("Rio_readnb error");
return rc;
}
ssize_t Rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen)
{
ssize_t rc;
if ((rc = rio_readlineb(rp, usrbuf, maxlen)) < 0)
unix_error("Rio_readlineb error");
return rc;
}
/********************************
* Client/server helper functions
********************************/
/*
* open_clientfd - Open connection to server at <hostname, port> and
* return a socket descriptor ready for reading and writing. This
* function is reentrant and protocol-independent.
*
* On error, returns:
* -2 for getaddrinfo error
* -1 with errno set for other errors.
*/
/* $begin open_clientfd */
int open_clientfd(char *hostname, char *port) {
int clientfd, rc;
struct addrinfo hints, *listp, *p;
/* Get a list of potential server addresses */
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_socktype = SOCK_STREAM; /* Open a connection */
hints.ai_flags = AI_NUMERICSERV; /* ... using a numeric port arg. */
hints.ai_flags |= AI_ADDRCONFIG; /* Recommended for connections */
if ((rc = getaddrinfo(hostname, port, &hints, &listp)) != 0) {
fprintf(stderr, "getaddrinfo failed (%s:%s): %s\n", hostname, port, gai_strerror(rc));
return -2;
}
/* Walk the list for one that we can successfully connect to */
for (p = listp; p; p = p->ai_next) {
/* Create a socket descriptor */
if ((clientfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0)
continue; /* Socket failed, try the next */
/* Connect to the server */
if (connect(clientfd, p->ai_addr, p->ai_addrlen) != -1)
break; /* Success */
if (close(clientfd) < 0) { /* Connect failed, try another */ //line:netp:openclientfd:closefd
fprintf(stderr, "open_clientfd: close failed: %s\n", strerror(errno));
return -1;
}
}
/* Clean up */
freeaddrinfo(listp);
if (!p) /* All connects failed */
return -1;
else /* The last connect succeeded */
return clientfd;
}
/* $end open_clientfd */
/*
* open_listenfd - Open and return a listening socket on port. This
* function is reentrant and protocol-independent.
*
* On error, returns:
* -2 for getaddrinfo error
* -1 with errno set for other errors.
*/
/* $begin open_listenfd */
int open_listenfd(char *port)
{
struct addrinfo hints, *listp, *p;
int listenfd, rc, optval=1;
/* Get a list of potential server addresses */
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_socktype = SOCK_STREAM; /* Accept connections */
hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; /* ... on any IP address */
hints.ai_flags |= AI_NUMERICSERV; /* ... using port number */
if ((rc = getaddrinfo(NULL, port, &hints, &listp)) != 0) {
fprintf(stderr, "getaddrinfo failed (port %s): %s\n", port, gai_strerror(rc));
return -2;
}
/* Walk the list for one that we can bind to */
for (p = listp; p; p = p->ai_next) {
/* Create a socket descriptor */
if ((listenfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0)
continue; /* Socket failed, try the next */
/* Eliminates "Address already in use" error from bind */
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, //line:netp:csapp:setsockopt
(const void *)&optval , sizeof(int));
/* Bind the descriptor to the address */
if (bind(listenfd, p->ai_addr, p->ai_addrlen) == 0)
break; /* Success */
if (close(listenfd) < 0) { /* Bind failed, try the next */
fprintf(stderr, "open_listenfd close failed: %s\n", strerror(errno));
return -1;
}
}
/* Clean up */
freeaddrinfo(listp);
if (!p) /* No address worked */
return -1;
/* Make it a listening socket ready to accept connection requests */
if (listen(listenfd, LISTENQ) < 0) {
close(listenfd);
return -1;
}
return listenfd;
}
/* $end open_listenfd */
/****************************************************
* Wrappers for reentrant protocol-independent helpers
****************************************************/
int Open_clientfd(char *hostname, char *port)
{
int rc;
if ((rc = open_clientfd(hostname, port)) < 0)
unix_error("Open_clientfd error");
return rc;
}
int Open_listenfd(char *port)
{
int rc;
if ((rc = open_listenfd(port)) < 0)
unix_error("Open_listenfd error");
return rc;
}
/* $end csapp.c */

Using multithreads to copy a single file at the same time, outputting the same file down to the MD5 check sum

The problem I'm running into is that when the file tries to copy, it only copies part of the file and the other part is a bunch of unreadable characters. This is for an academic assignment that wants us to use barrier synchronization so we need to use open, write, and read.
I've reworked the thread function many times but if it's the problem I can change it again, I haven't changed the for loop in main at all so even that might be the problem but I don't know what it could be. Lastly, I don't really know what to do with the barrier; my professor was very vague and I can't really ask him questions, maybe the barrier is the part that I'm truly missing.
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <semaphore.h>
#include <pthread.h>
#include <unistd.h>
typedef struct args {
int fd;
int copy;
long int start;
long int size;
}threadarg;
int barrier = 0;
int main(int argc, char *argv[])
{
void usage(char *progname);
int chkdst(char **argv);
void die(char *why);
long int filesize(char *srcpath);
void buildpath(char *src, char *dst, char **dstpath);
int isvalid(char *path, char *dst);
void *dowork(void *arg);
if (argc < 4) usage("a8");
int workers, i;
char *check;
workers = strtol(argv[3], &check, 10);
if (!check) usage("a8");
else if (!chkdst(&argv[2])) die ("DST not valid!");
long int size = filesize(argv[1]);
if (size == -1) die ("Could not find file size");
char *dstpath; buildpath(argv[1], argv[2], &dstpath);
if (!isvalid(argv[1], dstpath)) die ("scr not valid!");
long int chunksize = size / workers;
long int remainder = size % workers;
int fd = open(argv[1], O_RDONLY);
int copy = open(dstpath, O_CREAT | O_RDWR, 0644);
if (fd < 0 || copy < 0) die("Fail to access or create files");
barrier = workers;
threadarg threadargs[workers];
pthread_t threads[workers];
for (i = 0; i < workers; i++)
{
threadargs[i].fd = fd;
threadargs[i].copy = copy;
threadargs[i].start = i * chunksize;
if (i == workers - 1)
threadargs[i].size = chunksize + remainder;
else
threadargs[i].size = chunksize;
if (pthread_create(&threads[i], NULL, dowork, (void *) &threadargs[i]))
die("Thread Creation Failure");
}
for (i = 0; i < workers; i++)
pthread_join(threads[i], NULL);
}
void usage(char *progname)
{
fprintf(stderr, "./%s srcpath dstpath workercount\n", progname);
exit(0);
}
void die(char *why)
{
fprintf(stderr, "Program Killed...\nReason: %s\n", why);
exit(1);
}
long int filesize(char *srcpath)
{
struct stat st;
if(stat(srcpath, &st) != 0) return 0;
return st.st_size;
}
/*
void domd5(char *path)
{
}
*/
void *dowork(void *arg)
{
threadarg *args = (threadarg *)arg;
int fd = args->fd,
copy = args->copy, rd;
long int start = args->start,
size = args->size;
char bufs[2048], *remains;
lseek(fd, start, SEEK_SET);
lseek(copy, start, SEEK_SET);
printf("%d thread with offset %ldKB, reached barrier\n", (int) pthread_self(), start);
barrier--;
while (barrier > 0);
long int count = 0, remainder = 0, i;
for (i = 0; i < size; i += 2048)
{
if (i + 2048 > size)
{
remainder = size - count;
remains = malloc(remainder * sizeof(char));
rd = read (fd, remains, sizeof(remains));
if (write(copy, remains, rd) != rd)
die("Error accessing files during copy");
count += remainder;
}
else
{
rd = read(fd, bufs, sizeof(bufs));
if (write(copy, bufs, rd) != rd)
die("Error accessing files during copy");
count += 2048;
}
}
pthread_exit(NULL);
}
/* Takes a single pointer, *argv, and passes it to isdir()
to check if the directory exists. If isdir returns a 1 a
1 is returned from this module. Otherwise, an error message
is printed and a 0 is returned.
Calls isdir().
Called by main().
*/
int chkdst(char **argv)
{
int isdir(char *path);
if (isdir(*argv)) return 1;
return 0;
}
/* Uses the Stat struct to construct a struct, sbuf,
and uses stat() to obtain information from the file and
write it to sbuf. Uses S_ISDIR() on sbuf.st_mode to see
the mode of the file. A 1 is returned if the file is a
directory otherwise a 0 is returned.
Called by isvalid().
*/
int isdir(char *path)
{
struct stat sbuf;
if (stat(path, &sbuf)) return 0;
return S_ISDIR(sbuf.st_mode);
}
/* Uses the Stat struct to construct a struct, sbuf,
and uses stat() to obtain information from the file and
write it to sbuf. Uses S_ISREG on sbuf.st_mode to see if
the file is regular. A 1 is returned if the S_ISREG is true
otherwise a 0 is returned.
Called by isvalid().
*/
int isregular(char *path)
{
struct stat sbuf;
if (stat(path, &sbuf)) return 0;
return S_ISREG(sbuf.st_mode);
}
/* Checks if the source path is a directory first, then if its
a regular file return 0 if it is dir and if it isn't a regular
file, then checks if the destionation path was created or if
the file exist at the destination if either return 0, if none
of these return 1.
Calls isdir() and isregular().
Called by copyfiles().
*/
int isvalid(char *path, char *dst)
{
if (isdir(path))
{
return 0;
}
else if (!isregular(path))
{
return 0;
}
else if (dst == NULL)
{
return 0;
}
else if (isregular(dst))
{
return 0;
}
return 1;
}
/* Builds destination-path using strrchr() function from library,
dstpath is null on error and defined otherwise. The src file has
its original destination removed and replaced with the new one if
it has a original destination on it otherwise it is just added to
the end of the existing name of the file.
Called by copyfiles().
*/
void buildpath(char *src, char *dst, char **dstpath)
{
char *ptr;
int n;
ptr = strrchr(src, '/');
if (ptr) n = strlen(dst) + strlen(ptr) + 2;
else n = strlen(dst) + strlen(src) + 2;
*dstpath = malloc(n);
if (!dstpath) return;
if (ptr)
{
strcpy(*dstpath, dst);
strcat(*dstpath, ptr);
}
else
{
strcpy(*dstpath, dst);
strcat(*dstpath, "/");
strcat(*dstpath, src);
}
}

Filing file with zeroes

My file should be filled with 0. I want to do that using aio_write As a result my file should look like 000000000.... but as a result I get that my file is filled with garbage
^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#
s|▒^#^#^#^#^#^#^#^#^#^#^#^#▒r|▒^#^#^#^#▒▒^?▒(▒▒▒▒s|▒▒
y▒^P^#^#^#^X▒▒▒
s|▒^X^#^#^#▒.....
I don't even imagine what's wrong. First of all I'm using asynchronous write so I need to wait when da_aio_write is completed
int da_test_wait( struct aiocb *aiorp ){
const struct aiocb *aioptr[1];
int rv;
aioptr[0] = aiorp;
rv = aio_suspend( aioptr, 1, NULL );
if( rv != 0 ){
perror( "aio_suspend failed" );
abort();
}
rv = aio_return( aiorp );
printf( "AIO complete, %d bytes write.\n", rv );
return 1;
}
Also here is my writing function
int da_aio_write(const int d, struct aiocb *aiorp, void *buf, const int count){
int rv = 0;
memset( (void *)aiorp, 0, sizeof( struct aiocb ) );
aiorp->aio_fildes = d;
aiorp->aio_buf = buf;
aiorp->aio_nbytes = count;
aiorp->aio_offset = 0;
rv = aio_write( aiorp );
if( rv == -1) {
perror("Error da_aio_write\n");
exit(1);
return rv;
}
return rv;
}
and my main
int main(int argc, char *argv[] ){
int sk;
int d;
struct aiocb aior;
if(argc == 3){
sk = atoi(argv[2]);
char buffer[MB * MB * sk];
//memset(&aior, 0, sizeof( struct aiocb ));
d = da_open(argv[1]);
da_aio_write( d, &aior, buffer, sizeof(buffer) );
da_test_wait( &aior );
da_close( d );
}
return 0;
}
Any ideas what I'm doing wrong?
EDIT:
I know that my da_aio write ends after main because ehen I compile I get
File created
dskr1 = 3
AIO complete, 1048576 bytes write.
closed
EDIT My full updated code
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <string.h>
#include <aio.h>
#include <errno.h>
#define MB 1024
int da_open(const char *name);
int da_aio_write(const int d, struct aiocb *aiorp, void *buf, const int count);
int da_test_wait( struct aiocb *aiorp );
int da_close(int fd);
int da_open(const char *name){
int dskr;
int dskr2;
dskr = open( name, O_RDWR );
if( dskr == -1 ){
printf("File created\n");
dskr2 = open( name, O_WRONLY | O_CREAT, 0644);
}else{
printf("End job!\n");
exit(1);
}
printf( "dskr1 = %d\n", dskr2 );
return dskr2;
}
int da_aio_write(const int d, struct aiocb *aiorp, void *buf, const int count){
int rv = 0;
memset( (void *)aiorp, 0, sizeof( struct aiocb ) );
aiorp->aio_fildes = d;
aiorp->aio_buf = buf;
aiorp->aio_nbytes = count;
aiorp->aio_offset = 0;
rv = aio_write( aiorp );
if( rv == -1) {
perror("Error da_aio_write\n");
exit(1);
return rv;
}
return rv;
}
int da_test_wait( struct aiocb *aiorp ){
const struct aiocb *aioptr[1];
int rv;
aioptr[0] = aiorp;
rv = aio_suspend( aioptr, 1, NULL );
if( rv != 0 ){
perror( "aio_suspend failed" );
abort();
}
rv = aio_return( aiorp );
printf( "AIO complete, %d bytes write.\n", rv );
return 1;
}
int da_close(int fd){
int rv;
rv = close( fd );
if( rv != 0 ) perror ( "close() failed" );
else puts( "closed" );
return rv;
}
int main(int argc, char *argv[] ){
int sk;
int d;
struct aiocb aior;
if(argc == 3){
sk = atoi(argv[2]);
char buffer[MB * MB * sk];
int size;
size = MB * MB * sk;
memset( buffer, '\0', size);
//memset(&aior, '\0', sizeof( struct aiocb ));
d = da_open(argv[1]);
da_aio_write( d, &aior, buffer, sizeof(buffer) );
da_test_wait( &aior );
da_close( d );
}
return 0;
}
char buffer[MB * MB * sk];
Stack variables are not automatically initialiased. So your buffer contains garbage. memset it to 0 first if that's what you want to write to file.

mmap and memcpy usage and Segmentation Fault (core dumped) error

I have two files and I want to copy one file content to other using memcpy. But I get this error Segmentation Fault (core dumped). My main
int main( int argc, char * argv[] ){
int d1;
int d2;
char *a;
char *b;
d1 = da_open_r(argv[1]); // open file READ ONLY
d2 = da_open_w(argv[2]); // open file to WRITE
a = (char*)da_mmap(d1); // map first file
b = (char*)da_mmap(d2); // map second file
memcpy(b, a, 10); // I think this line is bad
kp_test_munamp(a, 10 ); //
kp_test_munamp(b, 10 );
kp_test_close(d1); // close 1 file
kp_test_close(d2); // close 2 file
return 0;
}
and here are my da_mmap and kp_test_munamp
void *da_mmap(int d){
mmap(NULL, 10, PROT_READ|PROT_WRITE, MAP_SHARED, d, 0);
}
int kp_test_munamp( void *a, int size ){
int rv;
rv = munmap( a, size );
if( rv != 0 ){
puts( "munmap failed" );
abort();
}
return 1;
}
I have been trying to fix this almost two hours, but still I don't know what's wrong.
EDIT my full code
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <string.h>
int da_open_r(const char *name);
int da_open_w(const char *name);
void *da_mmap(int d);
int kp_test_munamp( void *a, int size );
int kp_test_close(int fd);
int da_open_r(const char *name){
int dskr;
dskr = open( name, O_RDWR );
if( dskr == -1 ){
perror( name );
exit( 255 );
}
printf( "dskr1 = %d\n", dskr );
return dskr;
}
int da_open_w(const char *name){
int dskr;
dskr = open( name, O_RDWR );
if( dskr == -1 ){
perror( name );
exit( 255 );
}
printf( "dskr2 = %d\n", dskr );
return dskr;
}
void *da_mmap(int d){
void *a = NULL;
a = mmap(NULL, 10, PROT_WRITE, MAP_SHARED, d, 0);
if( a == MAP_FAILED ){
perror( "mmap failed" );
abort();
}
return a;
}
int kp_test_munamp( void *a, int size ){
int rv;
rv = munmap( a, size );
if( rv == -1 ){
puts( "munmap failed" );
abort();
}
return 1;
}
int kp_test_close(int fd){
int rv;
rv = close( fd );
if( rv != 0 ) perror ( "close() failed" );
else puts( "closed" );
return rv;
}
int main( int argc, char * argv[] ){
int d1;
int d2;
char *a;
char *b;
d1 = da_open_r(argv[1]); // read only
d2 = da_open_w(argv[2]); // WRITE
a = (char*)da_mmap(d1);
b = (char*)da_mmap(d2);
memcpy(b, a, 10); // I think this line is bad
kp_test_munamp(a, 10 );
kp_test_munamp(b, 10 );
kp_test_close(d1);
kp_test_close(d2);
return 0;
}
da_mmap() does not return anything! Which leads to the values of a and b being garbage and with this most probably pointing to invalid memory, which in turn makes memcpy() fail when acting on it.
Add return statement
void * da_mmap(int d) {
return mmap(NULL, 10, PROT_READ|PROT_WRITE, MAP_SHARED, d, 0);
}
Also you should test the outcome of the mapping by doing:
{
void * pvtmp = da_mmap(d1); // map first file
if (MAP_FAILED == pvtmp)
{
perror("da_mmap() failed");
exit(1);
}
a = pvtmp;
}
The same for b.
Referring the wrapper around munmap(). Correct error testing here. However by convention success is indicated by returning 0 (failure by returning -1).

C file filled with garbage

I need to fill my file with same numbers for example 00000.... I want to use asynchronous aio_write function. But here what I get
^# w▒(▒▒▒▒▒l▒#^#Y▒^#^#^#^#▒▒▒▒u▒l▒#*`▒^# w▒h▒▒▒ ......
Here's my code
int main(int argc, char *argv[] ){
int sk;
int d;
struct aiocb aior;
if(argc == 3){
sk = atoi(argv[2]);
char buffer[MB * MB * sk];
memset(&aior, 0, sizeof( struct aiocb ));
d = da_open(argv[1]);
da_aio_write( d, &aior, buffer, sizeof(buffer) );
da_test_wait( &aior );
da_close( d );
}
return 0;
}
and here's my asynchronous writing function (I think this function is bad)
int da_aio_write(const int d, struct aiocb *aiorp, void *buf, const int count){
int rv = 0;
memset( (void *)aiorp, 0, sizeof( struct aiocb ) );
aiorp->aio_fildes = d;
aiorp->aio_buf = buf;
aiorp->aio_nbytes = count;
aiorp->aio_offset = 0;
rv = aio_write( aiorp );
if( rv == -1) {
perror("Error da_aio_write\n");
exit(1);
return rv;
}
return rv;
}
Also here's I wait for asyncronius function to end
int da_test_wait( struct aiocb *aiorp ){
const struct aiocb *aioptr[1];
int rv;
aioptr[0] = aiorp;
rv = aio_suspend( aioptr, 1, NULL );
if( rv != 0 ){
perror( "aio_suspend failed" );
abort();
}
rv = aio_return( aiorp );
printf( "AIO complete, %d bytes write.\n", rv );
return 1;
}
Also here's my full program
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <string.h>
#include <aio.h>
#include <errno.h>
#define MB 1024
int da_open(const char *name);
int da_aio_write(const int d, struct aiocb *aiorp, void *buf, const int count);
int da_test_wait( struct aiocb *aiorp );
int da_close(int fd);
int da_open(const char *name){
int dskr;
int dskr2;
dskr = open( name, O_RDWR );
if( dskr == -1 ){
printf("File created\n");
dskr2 = open( name, O_WRONLY | O_CREAT, 0644);
}else{
printf("End job!\n");
exit(1);
}
printf( "dskr1 = %d\n", dskr2 );
return dskr2;
}
int da_aio_write(const int d, struct aiocb *aiorp, void *buf, const int count){
int rv = 0;
memset( (void *)aiorp, 0, sizeof( struct aiocb ) );
aiorp->aio_fildes = d;
aiorp->aio_buf = buf;
aiorp->aio_nbytes = count;
aiorp->aio_offset = 0;
rv = aio_write( aiorp );
if( rv == -1) {
perror("Error da_aio_write\n");
exit(1);
return rv;
}
return rv;
}
int da_test_wait( struct aiocb *aiorp ){
const struct aiocb *aioptr[1];
int rv;
aioptr[0] = aiorp;
rv = aio_suspend( aioptr, 1, NULL );
if( rv != 0 ){
perror( "aio_suspend failed" );
abort();
}
rv = aio_return( aiorp );
printf( "AIO complete, %d bytes write.\n", rv );
return 1;
}
int da_close(int fd){
int rv;
rv = close( fd );
if( rv != 0 ) perror ( "close() failed" );
else puts( "closed" );
return rv;
}
int main(int argc, char *argv[] ){
int sk;
int d;
struct aiocb aior;
if(argc == 3){
sk = atoi(argv[2]);
char buffer[MB * MB * sk];
memset(&aior, 0, sizeof( struct aiocb ));
d = da_open(argv[1]);
da_aio_write( d, &aior, buffer, sizeof(buffer) );
da_test_wait( &aior );
da_close( d );
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <string.h>
#include <aio.h>
int da_open(const char *name);
int da_aio_read(const int d, struct aiocb *aiorp, void *buf, const int count);
int da_open(const char *name){
int dskr;
int dskr2;
dskr = open( name, O_RDWR );
if( dskr == -1 ){
dskr2 = open( name, O_WRONLY | O_CREAT, 0644);
}else{
exit(1);
}
return dskr2;
}
What is going on here? Is this an obfuscated way to make sure you don't write to a file if it already exists? It is obviously incorrect as the file could have appeared before the second open. You can use O_EXCL instead.
The code is additionaly obfuscted by not handling exit earlier.
int da_aio_read(const int d, struct aiocb *aiorp, void *buf, const int count){
int rv = 0;
memset( (void *)aiorp, 0, sizeof( struct aiocb ) );
//memset(buf, 0, sizeof( buf) );
aiorp->aio_fildes = d;
aiorp->aio_buf = buf;
aiorp->aio_nbytes = count;
aiorp->aio_offset = 0;
rv = aio_write( aiorp );
return rv;
}
First off, what the fsck. Why are you calling a writing function something_read?
What's the use of rv?
If you read any docs on aio you will see you have to explicitly wait for event completion.
int main(int argc, char *argv[] ){
int sk;
int d;
struct aiocb aior;
char buffer[100];
memset(buffer, 0, sizeof buffer);
if(argc == 3){
sk = atoi(argv[2]);
d = da_open(argv[1]);
da_aio_read( d, &aior, buffer, sizeof(buffer) );
}
return 0;
}

Resources