int startup() { unsigned char c; int i,ack,ret; dsyslog(LOG_INFO,"startup...\n"); c = X10_PL_START; for (i = 0; i < retries; i++) { dsyslog(LOG_INFO,"sending 0x%x\n",X10_PL_START); ret = write(serial,&c,1); ack = waitforack(timeout); if (ack == 1) break; else if (ack != -1) return -1; } if (i > retries){ dsyslog(LOG_INFO,"Error: timeout exceeded for startup\n"); return -1; } return 0; }
/* * -- _csmap * * this function provides an interface similar to mmap. * it maps in memory a region of the file. before doing so, informs * the server of this intentions and makes sure that it can do it. * * the acknowledgement from the server carries two pieces of information: * . offset, that is set to the start offset of the file that * contains the block. * . size, that indicates the size of the region that can be memory mapped. * (different only if the region overlaps multiple files). * * this function returns a pointer to the memory mapped region and the size * of the region. * * _csmap is the back-end for csmap, csreadp, csseek. * */ static void * _csmap(int fd, off_t ofs, ssize_t * sz, int method) { csfile_t * cf; csmsg_t out, in; int flags; int diff; cf = files[fd]; /* Package the request and send it to the server */ out.id = cf->id; if (method == S_REGION) { out.arg = 0; out.type = method; out.size = *sz; out.ofs = ofs; /* the map offset */ } else { /* all the seek variants */ out.type = S_SEEK; out.arg = CS_SEEK_FILE_NEXT; out.size = 0; out.ofs = 0; } /* send the request out */ if (write(cf->sd, &out, sizeof(out)) < 0) { logmsg(LOGWARN, "message to storage: %s\n", strerror(errno)); *sz = -1; return NULL; } /* block waiting for the acknowledgment */ waitforack(cf->sd, &in); switch (in.type) { case S_ERROR: logmsg(LOGWARN, "csmap error in %s: %s\n", cf->name, strerror(in.arg)); errno = in.arg; *sz = -1; return NULL; case S_ACK: /* * The server acknowledged our request, * unmap the current block (both for csmap and csseek) */ if (cf->addr) munmap(cf->addr, cf->size); if (method == S_REGION) { /* * A zero sized block indicates end-of-bytestream. If so, close * the current file and return an EOF as well. */ if (in.size == 0) { close(cf->fd); *sz = 0; return NULL; } } else { /* seek variants */ /* the current file is not valid anymore */ close(cf->fd); cf->off_file = in.ofs; cf->fd = -1; *sz = (size_t)in.ofs; /* return value */ return NULL; /* we are done */ } break; default: panic("unknown msg type %d from storage\n", in.type); break; } if ((ssize_t)in.size == -1) panic("unexpected return from storage process"); /* * now check if the requested block is in the same file (i.e., * the server replied with an offset that is the first offset of * the currently open file. if not, close the current file and * open a new one. */ if (cf->fd < 0 || in.ofs != cf->off_file) { char * nm; if (cf->fd >= 0) close(cf->fd); #ifdef linux flags = (cf->mode == CS_READER)? O_RDWR : O_RDWR|O_APPEND; #else flags = (cf->mode == CS_READER)? O_RDONLY : O_WRONLY|O_APPEND; #endif asprintf(&nm, "%s/%016llx", cf->name, in.ofs); cf->fd = open(nm, flags, 0666); if (cf->fd < 0) panic("opening file %s acked! (%s)\n", nm, strerror(errno)); cf->off_file = in.ofs; free(nm); } /* * mmap the new block */ flags = (cf->mode == CS_READER)? PROT_READ : PROT_WRITE; cf->offset = ofs; cf->size = *sz = in.size; /* * align the mmap to the memory pagesize */ diff = (cf->offset - cf->off_file) % getpagesize(); cf->offset -= diff; cf->size += diff; cf->addr = mmap(0, cf->size, flags, MAP_NOSYNC|MAP_SHARED, cf->fd, cf->offset - cf->off_file); if (cf->addr == MAP_FAILED || cf->addr == NULL) panic("mmap got NULL (%s)\n", strerror(errno)); assert(cf->addr + diff != NULL); return (cf->addr + diff); }
/* * -- csopen * * csopen() opens a file managed by the storage process. It * uses the unix socket to communicate its intentions. The function * returns an integer used as file descriptor, or -1 on error. * Obviously the descriptor is not select()-able. */ int csopen(const char * name, int mode, off_t size, int sd) { csfile_t * cf; csmsg_t m; int fd; if (mode != CS_READER && mode != CS_WRITER) { logmsg(LOGWARN, "csopen: [%s] bad mode %d\n", name, mode); return -1; } logmsg(LOGSTORAGE, "csopen: [%s] %s\n", name, mode == CS_READER ? "CS_READER" : "CS_WRITER" ); /* look for an empty file descriptor */ for (fd = 0; fd < CS_MAXCLIENTS && files[fd] != NULL; fd++) ; if (fd == CS_MAXCLIENTS) { logmsg(LOGWARN, "Too many open files, cannot open %s\n", name); return -1; } /* * file descriptor found, prepare and send the request * message to the storage process */ bzero(&m, sizeof(m)); m.type = S_OPEN; m.id = 0; m.arg = mode; m.size = size; strncpy(m.name, name, FILENAME_MAX); if (write(sd, (char *) &m, sizeof(m)) < 0) panic("sending message to storage: %s\n", strerror(errno)); /* wait for the acknowledgment */ waitforack(sd, &m); if (m.type == S_ERROR) { logmsg(LOGWARN, "error opening file %s: %s\n", name, strerror(m.arg)); return -1; } /* * allocate a new file descriptor and initialize it with * the information in the message. */ cf = safe_calloc(1, sizeof(csfile_t)); cf->fd = -1; cf->sd = sd; cf->name = strdup(name); cf->mode = mode; cf->id = m.id; cf->off_file = m.ofs; /* store current offset. m.size is set to 0 by the server if this client * is a reader. otherwise it is equal to the size of the bytestream so * that writes are append only. */ cf->offset = m.ofs + m.size; files[fd] = cf; return fd; }