Code Search for Developers
 
 
  

storage_server.c from EmStar at Krugle


Show storage_server.c syntax highlighted

/*
 *
 * Copyright (c) 2006 The Regents of the University of California.  All 
 * rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Neither the name of the University nor the names of its
 *   contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

/*
 *  server to save to a remote device
 */

#include <include/remote.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <syslog.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <libgen.h>
#include <signal.h>
#include <sys/wait.h>

#define DEBUG(args...)
//#define DEBUG(args...) syslog(args)

#define OPTS_DELIM ",\n:"

static
void sig_child(int signal)
{
  int status;
  int pid = waitpid(-1, &status, WNOHANG);
  if (pid > 0) {
    DEBUG(LOG_NOTICE, "child process %d completed: %d", 
	  pid, status);
  }
}

void handle_connection(int sock)
{
  int append = 0;
  int wavpack = 0;

  FILE *f = fdopen(sock, "w+");
  
  /* OK, read in the filename to save to */
  char filename[512];
  filename[0] = 0;
  if (fgets(filename, sizeof(filename), f) == NULL ||
      filename[strlen(filename)-1] != '\n') {
    syslog(LOG_WARNING, "filename read failed (%s): %m", filename);
    exit(1);
  }

  char opts[512];
  opts[0] = 0;
  if (fgets(opts, sizeof(opts), f) == NULL ||
      opts[strlen(opts)-1] != '\n') {
    syslog(LOG_WARNING, "opts read failed (%s): %m", opts);
    exit(1);
  }

  /* parse options */
  char *tmp = opts;
  char *item;
  while ((item = strtok(tmp, OPTS_DELIM))) {
    tmp = NULL;
    if (strcmp(item, "append") == 0)
      append = 1;
    if (strcmp(item, "wavpack") == 0)
      wavpack = 1;
  }

  if (strncmp(filename, "/remote/", 8)) {
    syslog(LOG_NOTICE, "Expected fn to start with remote: '%s'", filename);
    exit(1);
  }

  memmove(filename, "/mnt/cf/", 8);
  filename[strlen(filename)-1] = 0;
  if (append)
    DEBUG(LOG_NOTICE, "Writing to new file %s", filename);
  else
    syslog(LOG_NOTICE, "Writing to new file %s", filename);
 
  char rpath[512];
  realpath(filename, rpath);
  char *rpath2 = strdup(rpath);
  char *path = dirname(rpath2);

  /* create dir if needed */
  char cmd[512];
  sprintf(cmd, "mkdir -p %s", path);
  system(cmd);

  /* open the file */
  FILE *out = fopen(rpath, append ? "a" : "w");
  if (out == NULL) {
    syslog(LOG_CRIT, "unable to open new file %s", rpath);
    exit(1);
  }

  DEBUG(LOG_NOTICE, "opened file");

  while (1) {
    char chunk[16384];
    int status = fread(chunk, 1, sizeof(chunk), f);
    if (status == sizeof(chunk)) {
      int stat2 = fwrite(chunk, 1, status, out);
      if (stat2 != status) {
	if (ferror(out)) {
	  syslog(LOG_CRIT, "error writing file '%s': %m", rpath);
	  break;
	}	
	syslog(LOG_CRIT, "eof writing file '%s'??: %m", rpath);
	break;
      }
      
      /* $$ write back progress report?? */

    }
    else {
      if (ferror(f)) {
	syslog(LOG_CRIT, "error reading file '%s': %m", rpath);
      }
      break;
    }
  }

  fclose(out);  
  fclose(f);  	
  if (append) 
    DEBUG(LOG_NOTICE, "completed write of file '%s': %m", rpath);
  else
    syslog(LOG_NOTICE, "completed write of file '%s': %m", rpath);
  sync();
  DEBUG(LOG_NOTICE, "synced");
}


int main(int argc, char *argv[])
{
  signal(SIGCHLD, sig_child);

  /* address to bind to */
  struct sockaddr_in saddr = {
    sin_family: AF_INET,
    sin_port: htons(STORAGE_SERVER_PORT),
    sin_addr: {
      s_addr: INADDR_ANY
    }
  };
  int status;
  int sock;
  int val = 1;
  int lq;

  openlog("remote_save", LOG_PERROR, LOG_DAEMON);
  syslog(LOG_NOTICE, "Starting up");

  /* get a socket */
  sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (sock < 0) {
    syslog(LOG_CRIT, "Socket call failed: %m");
    exit(1);
  }

  /* configure the socket */
  if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
    syslog(LOG_WARNING, "Unable to set SO_REUSEADDR on server socket, continuing: %m");
  }
  
  /* try to bind */
  status = bind(sock, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in));
  if (status < 0) {
    syslog(LOG_CRIT, "Unable to bind to port %d: %m", STORAGE_SERVER_PORT);
    exit(1);
  }

  /* listen */
  lq = 100;
  if (listen(sock, lq) < 0) {
    syslog(LOG_CRIT, "Unable to listen, queue %d: %m", lq);
    exit(1);
  }

  while (1) {
    /* now wait for a connection */
    DEBUG(LOG_NOTICE, "Waiting for a connection.");
    
    struct sockaddr_in saddr;
    size_t size = sizeof(saddr);
    int sock2 = accept(sock, (struct sockaddr *)&saddr, &size);
    
    if (sock2 < 0) {
      syslog(LOG_CRIT, "Accept returned error: %m");
      exit(1);
    }

    /* ok, now fork */
    int childpid = fork();
    if (childpid < 0) {
      syslog(LOG_CRIT, "Fork failed: %m");
      exit(1);
    }
    
    if (childpid) {
      close(sock2);
    }

    else {
      handle_connection(sock2);
      exit(0);
    }
  }
}




See more files for this project here

EmStar

EmStar is a software system for developing and deploying wireless sensor networks involving Linux-based platforms. As the wireless sensor network community has attempted to deploy more complex designs---large-scale, long-lived systems that need self-organization and adaptivity---a number of difficult software design issues have arisen. Advances in software design have not kept pace with the capabilities of hardware. This is because designing for an adaptive, efficient, and useful sensor network has turned out to be surprisingly complex and difficult. EmStar is a Linux-based software framework, whose goal is to dramatically reduce this complexity, enabling work to be shared and reused, and simplifying and speeding the design of new sensor network applications.

Project homepage: http://cvs.cens.ucla.edu/emstar/
Programming language(s): C,Shell Script
License: other

  include/
    remote.h
  BUILD
  remote.c
  storage_lib.c
  storage_server.c