/* Copyright 1995 David C. Niemi * Copyright 1996-2002,2008,2009 Alain Knaff. * This file is part of mtools. * * Mtools is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Mtools is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Mtools. If not, see . */ #include "sysincludes.h" #include "stream.h" #include "mtools.h" #include "file.h" #include "fs.h" #include "file_name.h" /* #define DEBUG */ /* * Read a directory entry into caller supplied buffer */ struct directory *dir_read(direntry_t *entry, int *error) { ssize_t n; *error = 0; if((n=force_pread(entry->Dir, (char *) (&entry->dir), (mt_off_t) entry->entry * MDIR_SIZE, MDIR_SIZE)) != MDIR_SIZE) { if (n < 0) { *error = -1; } return NULL; } return &entry->dir; } /* * Make a subdirectory grow in length. Only subdirectories (not root) * may grow. Returns a 0 on success, 1 on failure (disk full), or -1 * on error. */ int dir_grow(Stream_t *Dir, unsigned int size) { Stream_t *Stream = GetFs(Dir); DeclareThis(Fs_t); ssize_t ret; unsigned int buflen; char *buffer; if (!getfreeMinClusters(Dir, 1)) return -1; buflen = getClusterBytes(This); if(! (buffer=malloc(buflen)) ){ perror("dir_grow: malloc"); return -1; } memset((char *) buffer, '\0', buflen); ret = force_pwrite(Dir, buffer, (mt_off_t) size * MDIR_SIZE, buflen); free(buffer); if(ret < (int) buflen) return -1; return 0; } void low_level_dir_write(direntry_t *entry) { force_pwrite(entry->Dir, (char *) (&entry->dir), (mt_off_t) entry->entry * MDIR_SIZE, MDIR_SIZE); } void low_level_dir_write_end(Stream_t *Dir, int entry) { char zero = ENDMARK; force_pwrite(Dir, &zero, (mt_off_t) entry * MDIR_SIZE, 1); } /* * Make a directory entry. Builds a directory entry based on the * name, attribute, starting cluster number, and size. Returns a pointer * to a static directory structure. */ struct directory *mk_entry(const dos_name_t *dn, unsigned char attr, unsigned int fat, uint32_t size, time_t date, struct directory *ndir) { struct tm *now; time_t date2 = date; uint8_t hour, min_hi, min_low, sec; uint8_t year, month_hi, month_low, day; now = localtime(&date2); dosnameToDirentry(dn, ndir); ndir->attr = attr; ndir->ctime_ms = 0; hour = (uint8_t) (now->tm_hour << 3); min_hi = (uint8_t) (now->tm_min >> 3); min_low = (uint8_t) (now->tm_min << 5); sec = (uint8_t) (now->tm_sec / 2); ndir->ctime[1] = ndir->time[1] = hour + min_hi; ndir->ctime[0] = ndir->time[0] = min_low + sec; year = (uint8_t) ((now->tm_year - 80) << 1); month_hi = (uint8_t) ((now->tm_mon + 1) >> 3); month_low = (uint8_t) ((now->tm_mon + 1) << 5); day = (uint8_t) (now->tm_mday); ndir -> adate[1] = ndir->cdate[1] = ndir->date[1] = year + month_hi; ndir -> adate[0] = ndir->cdate[0] = ndir->date[0] = month_low + day; set_word(ndir->start, fat & 0xffff); set_word(ndir->startHi, fat >> 16); set_dword(ndir->size, size); return ndir; } /* * Make a directory entry from base name. This is supposed to be used * from places such as mmd for making special entries (".", "..", "/", ...) * Thus it doesn't bother with character set conversions */ struct directory *mk_entry_from_base(const char *base, unsigned char attr, unsigned int fat, uint32_t size, time_t date, struct directory *ndir) { struct directory *entry; struct dos_name_t dn; strncpy(dn.base, base, 8); strncpy(dn.ext, " ", 3); entry = mk_entry(&dn, attr, fat, size, date, ndir); entry->Case = 0; return entry; }