// pj1.c - Princeton CS 318 2001 fall
// Project 1 supporting file
//         By
//    Brian J. Lai
// Starting: Sep 13, 2001

//////////////////////////////////////////////////////////////
//                       Warning!
// You are not supposed to read this file :-)
//////////////////////////////////////////////////////////////

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <netdb.h>
#include <dirent.h>
#include <errno.h>

#include "pj1.h"

//////////////////////////////////////////////////////////////

static void fill_in_addr(struct sockaddr_in *addr, u16_t portNum){
  memset(addr, 0, sizeof(addr));
  addr->sin_family = AF_INET;
  addr->sin_port = htons(portNum);
  addr->sin_addr.s_addr = htonl(INADDR_ANY);
}//fill_in_addr

//////////////////////////////////////////////////////////////

int setup_server(int portNum){
  struct sockaddr_in addr;
  int                sock;
  int                val, ret;

  fill_in_addr(&addr, portNum);
  
  sock = socket(PF_INET, SOCK_STREAM, 0);
  os_assert(sock >= 0);

  val = 1;
  ret = setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&val,sizeof(val));
  os_assert(ret == 0);

  ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
  os_assert(ret == 0);

  ret = listen(sock, 20);
  os_assert(ret == 0);
  
  return sock;
}//setup_server

//////////////////////////////////////////////////////////////

int get_next_connection(int fd){
  struct sockaddr_in addr;
  int                ret;
  int                len;
  
  len = sizeof(addr);
  ret = accept(fd, (struct sockaddr *)&addr, &len);

  return ret;
}//get_next_connection

//////////////////////////////////////////////////////////////

int get_file_info(const char *fileName, SDirEntry *entry){
  struct stat st;
  int         ret;

  ret = stat(fileName, &st);
  if(ret < 0){
    if(errno == ENOENT || errno == ENOTDIR)
      return FILE_INFO_ERR_NOT_EXIST;
    if(errno == EACCES)
      return FILE_INFO_ERR_ACCESS_DENIED;
    return FILE_INFO_ERR_UNKNOWN;
  }//if
  else{ // operation normal
    strncpy(entry->fileName, fileName, 1024);
    if(S_ISREG(st.st_mode)) entry->fileType = FILE_NORMAL;
    else if(S_ISDIR(st.st_mode)) entry->fileType = FILE_DIR;
    else entry->fileType = FILE_OTHER;

    entry->fileSize = st.st_size;
    entry->lastModifyTime =st.st_mtime;
    return 0;
  }//else
  
}//get_file_info

//////////////////////////////////////////////////////////////

static DIR *dir = NULL;

//////////////////////////////////////////////////////////////
int open_directory(const char *dirName){
  if(dir) close_directory();
  dir = opendir(dirName);
  if(dir) return 0;
  else    return -1;
}//open_directory

//////////////////////////////////////////////////////////////

char * read_an_entry(void){
  static char   fname[1024];
  struct dirent *de;
  int           ret;
  int           len;

  if(!dir){
    fprintf(stderr,"call open_directory() first\n");
    os_assert(dir);
  }//if
  de = readdir(dir);
  if(!de) return NULL;
  strncpy(fname, de->d_name, 1024);
  return fname;
}//read_an_entry

//////////////////////////////////////////////////////////////

void close_directory(void){
  if(dir) closedir(dir);
  dir = NULL;
}//close_directory

//////////////////////////////////////////////////////////////




