#include <string.h>
#include <errno.h>
#include <stdbool.h>
#include "stat.h"
#include "fat.h"
#include "dir.h"
#include "debug.h"


static int get_stat_from_fat_entry(struct fat_direntry* dirent,
                                   struct stat* buf);
static int dos2unixdate(unsigned short time, unsigned short date);

int stat(char *name, struct stat *buf) {
    struct fat_direntry entry;
    char namecopy[256];
    char* filename;
    DIR* dir;
    int namelen;

    if ( name[0] != '/' ) {
        DEBUGF("Only absolute paths supported right now\n");
        errno = EINVAL;
        return -1;
    }

    strncpy(namecopy,name,sizeof(namecopy));
    namecopy[sizeof(namecopy)-1] = 0;

    filename=strrchr(namecopy,'/');
    *filename='\0';
    filename++;
    namelen=strlen(filename);

    dir=opendir(namecopy);
    if (dir==NULL) {
        /* let opendir set errno */
        return -1;
    }

    while (fat_getnext(&(dir->fatdir),&entry) >= 0) {
        if ( entry.name[0]  &&
             strncasecmp(filename,entry.name,namelen)==0) {
            /* Make sure to clean up after myself */
            closedir(dir);
            return get_stat_from_fat_entry(&entry,buf);
        }
    }
    /* Make sure to clean up after myself */
    closedir(dir);
    errno=ENOENT;
    return -1;
}

static int get_stat_from_fat_entry(struct fat_direntry* dirent,
                                  struct stat* buf) {
   memset(buf,0,sizeof(struct stat));

   buf->st_ino=dirent->firstcluster;
   if (dirent->attr&FAT_ATTR_READ_ONLY) {
       buf->st_mode=S_IRUSR|S_IRGRP|S_IROTH;
   } else {
       buf->st_mode=S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
   }

   buf->st_size=dirent->filesize;
   buf->st_rdev=S_IFREG;

   /* Fill in st_blksize and st_blocks later */

   buf->st_atime=buf->st_mtime=
       dos2unixdate(dirent->wrttime,dirent->wrtdate);
	buf->st_ctime=dos2unixdate(dirent->crttime,dirent->crtdate);
   return 0;
}

static int day_n[] = { 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0,0 };
		  /* JanFebMarApr May Jun Jul Aug Sep Oct Nov Dec */

static int dos2unixdate(unsigned short time, unsigned short date) {
    int month,year,secs;
    
    month = ((date >> 5) & 15)-1;
    year = date >> 9;
    secs = (time & 31)*2+60*((time >> 5) & 63)+(time >> 11)*3600+86400*
        ((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 &&
                                                       month < 2 ? 1 : 0)+3653);
    return secs;
}

/*
 * local variables:
 * eval: (load-file "../rockbox-mode.el")
 * end:
 */

