struct lafs_ino *lafs_lookup_path(struct lafs_ino *root, struct lafs_ino *cwd,
char *path, char **remainder);
int lafs_imap_alloc(struct lafs_ino *imap);
+int lafs_dir_add(struct lafs_ino *dir, char *name, u32 inum, int type);
virt += dv->segment_offset;
*sectp = virt;
}
+
+#include <dirent.h>
+
+static inline int lafs_dt_type(struct lafs_ino *ino)
+{
+ if (ino->type < TypeBase)
+ return 0;
+ switch(ino->type) {
+ default: return 0;
+ case TypeFile: return DT_REG;
+ case TypeDir: return DT_DIR;
+ case TypeSymlink: return DT_LNK;
+ case TypeSpecial: return ino->md.file.mode >> 12;
+ }
+}
--- /dev/null
+#include <string.h>
+#include <lafs/lafs.h>
+#include "internal.h"
+
+static inline int space_needed(int len, int chainoffset, int psz)
+{
+ int space;
+ space = len + (chainoffset > 255 ? 4 : chainoffset > 1 ? 1 : 0);
+ space += offsetof(struct dirpiece, name);
+ space = DIV_ROUND_UP(space, 1<<psz);
+ return space;
+}
+
+
+int lafs_dir_add(struct lafs_ino *dir, char *name, u32 inum, int type)
+{
+ /* lookup a name and return ino number, or 0 if not found */
+ struct lafs_dblk *db, *new;
+ u32 hash, newhash;
+ int chainoffset = 0;
+ int len = strlen(name);
+ int rv;
+ struct dirheader *dh;
+ char *n1, *n2;
+
+ hash = lafs_hash_name(dir->md.file.seed, len, name);
+
+ while (1) {
+ u32 bnum;
+ int found;
+ u8 piece;
+ struct dir_ent de;
+ bnum = lafs_find_next(dir, hash+1);
+ if (bnum == LAFS_NOBLOCK)
+ bnum = 0;
+
+ db = lafs_dblk(dir, bnum);
+ if (!db ||
+ lafs_load_dblk(db))
+ return 0;
+
+ found = lafs_dir_find(db->b.data, dir->fs->blockbits-8,
+ dir->md.file.seed,
+ hash, &piece);
+ if (found) {
+ lafs_dir_extract(db->b.data, dir->fs->blockbits-8,
+ &de, piece, NULL);
+ if (de.target &&
+ de.nlen == len &&
+ strncmp(de.name, name, len) == 0)
+ return 0; /* already exists */
+ if (de.target) {
+ /* chain forwards */
+ hash++;
+ chainoffset++;
+ continue;
+ }
+ }
+ /* This hash value is free. */
+ break;
+ }
+ rv = lafs_dir_add_ent(db->b.data, dir->fs->blockbits-8,
+ name, len, inum, type,
+ dir->md.file.seed,
+ hash, chainoffset);
+ BUG_ON(rv < 0);
+ if (rv == 1) {
+ lafs_sched_blk(&db->b);
+ return 1;
+ }
+ /* didn't fit - need to split */
+ dh = (struct dirheader*)(db->b.data);
+ if (dh->freepieces >= space_needed(len, chainoffset,
+ dir->fs->blockbits-8)) {
+ char *tmp = malloc(dir->fs->blocksize);
+ lafs_dir_repack(db->b.data, dir->fs->blockbits-8,
+ tmp, dir->md.file.seed, 0);
+ rv = lafs_dir_add_ent(tmp, dir->fs->blockbits-8,
+ name, len, inum, type,
+ dir->md.file.seed,
+ hash, chainoffset);
+ if (rv == 1) {
+ memcpy(db->b.data, tmp, dir->fs->blocksize);
+ free(tmp);
+ lafs_sched_blk(&db->b);
+ return 1;
+ }
+ free(tmp);
+ }
+ /* Really doesn't fit, need to split */
+ n1 = malloc(dir->fs->blocksize);
+ n2 = malloc(dir->fs->blocksize);
+ lafs_dir_split(db->b.data, dir->fs->blockbits-8, n1, n2,
+ name, inum, type, &newhash,
+ dir->md.file.seed, hash, chainoffset);
+ memcpy(db->b.data, n2, dir->fs->blocksize);
+ new = lafs_dblk(dir, newhash+1);
+ memcpy(new->b.data, n1, dir->fs->blocksize);
+ free(n1);
+ free(n2);
+ lafs_sched_blk(&db->b);
+ lafs_sched_blk(&new->b);
+ return 1;
+}
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
+#include <fcntl.h>
#include <stdio.h>
#include <getopt.h>
#include <stdio.h>
+#include <errno.h>
#include <readline/readline.h>
#include <readline/history.h>
#include <lafs/lafs.h>
{
char *from = args[1];
char *to = args[2];
- if (!from)
+ struct lafs_ino *dir, *fs, *imfile, *inode;
+ char *tail = NULL;
+ int fd;
+ loff_t bnum;
+ u32 inum;
+
+ if (!from) {
printf("ERROR: Source file is missing\n");
- else if (!to)
+ return;
+ }
+ if (!to) {
printf("ERROR: destination file name is missing\n");
- else
- printf("Oh how I wish I could copy %s to %s\n", from, to);
+ return;
+ }
+
+ fs = lafs_get_itable(st->lafs);
+ dir = lafs_get_inode(fs, 2);
+ dir = lafs_lookup_path(dir, dir, to, &tail);
+ if (!dir) {
+ printf("store: lookup error in %s\n",to);
+ return;
+ }
+ if (tail == NULL) {
+ printf("store: %s already exists\n", to);
+ return;
+ }
+ if (dir->type != TypeDir) {
+ *tail = 0;
+ printf("store: non-directory found at %s\n", to);
+ return;
+ }
+ if (strchr(tail, '/') != NULL) {
+ printf("store: non-final name does not exist: %s\n", tail);
+ return;
+ }
+
+ fd = open(from, O_RDONLY);
+ if (fd < 0) {
+ printf("store: Cannot open %s: %s\n", from, strerror(errno));
+ return;
+ }
+
+ imfile = lafs_get_inode(fs, 1);
+ inum = lafs_imap_alloc(imfile);
+ inode = lafs_add_inode(fs, inum, TypeFile);
+ lafs_dir_add(dir, tail, inum, lafs_dt_type(inode));
+
+ bnum = 0;
+ while(1) {
+ struct lafs_dblk *db = lafs_dblk(inode, bnum);
+ int n = read(fd, db->b.data, st->lafs->blocksize);
+ if (n <= 0)
+ break;
+ inode->md.file.size = (bnum << st->lafs->blockbits) + n;
+ db->b.flags |= B_Valid;
+ lafs_dirty_blk(db);
+ bnum++;
+ }
+ printf("Created %s as inode %d in %d\n", tail, inum, dir->inum);
}
/****** LS ******/