/** Des de l'inode del directori i el camí parcial obté l'inode del directori * i de l'entrada. Recorda que a la primera crida recursiva sempre li haurem * d'indicar p_inode_dir l'inode del directori arrel. * Convé usar extract_path per obtenir els subcamins. * @path: ruta, parcial o completa, del fitxer que buscam. * @p_inode_dir: l'inode del directori. * @p_inode: l'inode del fitxer. * @p_entry: entrada del fitxer dins el directori. * @return: 0 si èxit. */ int emofs_find_entry(const char *path, int *p_inode_dir, int *p_inode, int *p_entry) { int found; int is_dir; char target [MAX_FILENAME_LEN]; char tail [MAX_PATH_LEN]; emofs_inode inode; emofs_dir_entry *dir_entry; int dir_entry_count; int i; emofs_superblock sb; /* Cas trivial del directori root */ if(!strcmp(path, "/")) { sbread(&sb); *p_inode_dir = sb.root_inode; *p_inode = sb.root_inode; *p_entry = 0; return 0; } emofs_extract_path(path, target, tail); read_inode(*p_inode_dir, &inode); /* Cal recordar que no tenim desada enlloc la quantitat d'entrades que * tenim dins el directori. Amb la divisió tamany_escrit/tamany_dades * obtindrem quants d'elements tenim. */ dir_entry_count = inode.size / sizeof(emofs_dir_entry); /* p_inode_dir -> inode del pare * dir_entry -> l'entrada de directori: nom+inode * dir_entry_count -> nombre de l'entrada dins el directori pare */ found = 0; for (i = 0; i < dir_entry_count; i++) { read_file(*p_inode_dir, (void *)&dir_entry, i*sizeof(emofs_dir_entry), \ sizeof(emofs_dir_entry)); found = !strcmp(target, dir_entry->name); if (found) { break; } } if (!found) { return -1; } *p_entry = i; *p_inode = dir_entry->inode; /* Si encara queda camí seguim amb les crides recursives */ if (strcmp(tail, "")) { *p_inode_dir = dir_entry->inode; free(dir_entry); return emofs_find_entry(tail, p_inode_dir, p_inode, p_entry); } free(dir_entry); /* Si arribam aqui s'aturen les crides recursives. */ return 0; }
/** Posa el contingut del directori en un buffer de memòria. * el nom de cada entrava ve separat per ':'. * Es ell qui reserva la memoria de buf i l'ha d'alliberar * la funcio que l'empri en haver acabat. * @path: Cami al directori * @buf: llistat de les entrades de directori separades per ':' * @return: numero de d'entrades llistades, -1 error, -2 era un fitxer. */ int emofs_dir(const char *path, char **buf) { int p_inode; emofs_inode inode; emofs_superblock sb; int p_entry; /* No s'empra pero es necessari per cridar find_entry */ int p_inode_dir; int dir_entry_count; emofs_dir_entry *dir_entry; int error; int i, j, k; int used_entry_count = 0; int buffer_size = 0; sbread(&sb); p_inode_dir = sb.root_inode; error = emofs_find_entry(path, &p_inode_dir, &p_inode, &p_entry); if (error < 0) { return error; } read_inode(p_inode, &inode); dir_entry_count = inode.size/sizeof(emofs_dir_entry); *buf = malloc(sizeof(char)); k = 0; for (i = 0; i < dir_entry_count; i++) { read_file(p_inode, (void *) &dir_entry, \ i*sizeof(emofs_dir_entry), sizeof(emofs_dir_entry)); if (dir_entry->inode != NULL_POINTER) { buffer_size += strlen(dir_entry->name)+1; /*Mes les ':'*/ /*Memòria dinàmica, el que faltava per fer*/ *buf = realloc(*buf, buffer_size*sizeof(char)); if (*buf == NULL) { puts("Error redimensionant tamany de buffer."); } for(j = 0; dir_entry->name[j] != '\0'; j++) { (*buf)[k] = dir_entry->name[j]; k++; } (*buf)[k] = ':'; /* separadors de nom de fitxer */ k++; used_entry_count++; } } free(dir_entry); if (used_entry_count > 0) { /* Posam el final d'string substituint el separador */ (*buf)[k-1] = '\0'; } else { *buf = malloc(sizeof(char)); (*buf)[k] = '\0'; /* k sera 0 */ } return used_entry_count; }
/** Llegeix un cert nombre de bits d'un fitxer. * @path: Camí al destí * @buf: punter al buffer de sortida, la funcio s'encarrega de reservar l'espai. * @offset: determinam el primer byte del fitxer. * @n_bytes: nombre de bytes a llegir * @return: el nombre de bytes llegits. */ int emofs_read(const char *path, void **buf, int offset, int n_bytes) { int inode; emofs_superblock sb; int p_entry; /* No s'empra pero es necessari per cridar find_entry */ int p_inode_dir; sbread(&sb); p_inode_dir = sb.root_inode; emofs_find_entry(path, &p_inode_dir, &inode, &p_entry); return read_file(inode, buf, offset, n_bytes); }
int ufs_disk_fillout(struct uufsd *disk, const char *name) { if (ufs_disk_fillout_blank(disk, name) == -1) { return (-1); } if (sbread(disk) == -1) { ERROR(disk, "could not read superblock to fill out disk"); return (-1); } return (0); }
static SPWAW_ERROR load_oobp_list (SBR *sbr, USHORT cnt, SPWAW_SNAP_OOB_RAW *oob, STRTAB *stab) { ULONG i; SNAP_OOB_PEL p; for (i=0; i<cnt; i++) { if (sbread (sbr, (char *)&p, sizeof (p)) != sizeof (p)) RWE (SPWERR_FRFAILED, "sbread(position data)"); load_oobp (&p, &(oob->positions.raw[i]), stab); } return (SPWERR_OK); }
static SPWAW_ERROR load_oobl_list (SBR *sbr, USHORT cnt, SPWAW_SNAP_OOB_RAW *oob, STRTAB *stab) { ULONG i; SNAP_OOB_LEL l; for (i=0; i<cnt; i++) { if (sbread (sbr, (char *)&l, sizeof (l)) != sizeof (l)) RWE (SPWERR_FRFAILED, "sbread(leader data)"); load_oobl (&l, &(oob->leaders.raw[i]), stab); } return (SPWERR_OK); }
static SPWAW_ERROR load_oobf_list (SBR *sbr, USHORT cnt, SPWAW_SNAP_OOB_RAW *oob, STRTAB *stab) { ULONG i; SNAP_OOB_FEL f; for (i=0; i<cnt; i++) { if (sbread (sbr, (char *)&f, sizeof (f)) != sizeof (f)) RWE (SPWERR_FRFAILED, "sbread(formation data)"); load_oobf (&f, &(oob->formations.raw[i]), stab); } return (SPWERR_OK); }
/** Escriu un cert nombre de bits d'un fitxer. Té control de concurrència. * @path: Camí al destí * @buf: buffer de entrada. * @offset: determinam el primer byte del fitxer. * @n_bytes: nombre de bytes a escriure * @return: el nombre de bytes escriure. */ int emofs_write(const char *path, const void *buf, int offset, int n_bytes) { int inode, error; emofs_superblock sb; /* No s'empra pero es necessari per cridar find_entry */ int p_entry; int p_inode_dir; if(!mutex){ emofs_sem_get(&mutex); } emofs_sem_wait(mutex); sbread(&sb); p_inode_dir = sb.root_inode; emofs_find_entry(path, &p_inode_dir, &inode, &p_entry); error = write_file(inode, buf, offset, n_bytes); emofs_sem_signal(mutex); return error; }
static SPWAW_ERROR load_oobu_list (SBR *sbr, USHORT cnt, SPWAW_SNAP_OOB_RAW *oob, STRTAB *stab, ULONG version) { ULONG i; SNAP_OOB_UEL u; for (i=0; i<cnt; i++) { /* We are now backwards compatible with version 10 */ if (version == SNAP_VERSION_V10) { snapshot_load_v10_oob_uel (sbr, &u); } else { if (sbread (sbr, (char *)&u, sizeof (u)) != sizeof (u)) RWE (SPWERR_FRFAILED, "sbread(unit data)"); } load_oobu (&u, &(oob->units.raw[i]), stab); } return (SPWERR_OK); }
/** Obté la informació d'un fitxer o directori * @path: Cami al fitxer/directori. * @stat: el punter de sortida de les dades. * @return: 0 si èxit. */ int emofs_stat(const char *path, emofs_inode_stat *stat) { int inode = 0; emofs_superblock sb; int p_entry = 0; /* No s'empra pero es necessari per cridar find_entry */ int p_inode_dir = 0; int error = 0; sbread(&sb); p_inode_dir = sb.root_inode; error = emofs_find_entry(path, &p_inode_dir, &inode, &p_entry); if(error < 0) { puts("emofs_stat: no s'ha trobat entrada"); return error; } if(inode < 0) { puts("emofs_stat: inode negatiu"); return -1; } error = stat_file(inode, stat); return error; }
/* * Read information about /boot's inode, then put this and filesystem * parameters from the superblock into pbr_symbols. */ static int getbootparams(char *boot, int devfd, struct disklabel *dl) { int fd; struct stat statbuf, sb; struct statfs statfsbuf; struct partition *pp; struct fs *fs; char *buf; u_int blk, *ap; struct ufs1_dinode *ip1; struct ufs2_dinode *ip2; int ndb; int mib[3]; size_t size; dev_t dev; int skew; /* * Open 2nd-level boot program and record enough details about * where it is on the filesystem represented by `devfd' * (inode block, offset within that block, and various filesystem * parameters essentially taken from the superblock) for biosboot * to be able to load it later. */ /* Make sure the (probably new) boot file is on disk. */ sync(); sleep(1); if ((fd = open(boot, O_RDONLY)) < 0) err(1, "open: %s", boot); if (fstatfs(fd, &statfsbuf) != 0) err(1, "statfs: %s", boot); if (strncmp(statfsbuf.f_fstypename, "ffs", MFSNAMELEN) && strncmp(statfsbuf.f_fstypename, "ufs", MFSNAMELEN) ) errx(1, "%s: not on an FFS filesystem", boot); #if 0 if (read(fd, &eh, sizeof(eh)) != sizeof(eh)) errx(1, "read: %s", boot); if (!IS_ELF(eh)) { errx(1, "%s: bad magic: 0x%02x%02x%02x%02x", boot, eh.e_ident[EI_MAG0], eh.e_ident[EI_MAG1], eh.e_ident[EI_MAG2], eh.e_ident[EI_MAG3]); } #endif if (fsync(fd) != 0) err(1, "fsync: %s", boot); if (fstat(fd, &statbuf) != 0) err(1, "fstat: %s", boot); if (fstat(devfd, &sb) != 0) err(1, "fstat: %s", realdev); /* Check devices. */ mib[0] = CTL_MACHDEP; mib[1] = CPU_CHR2BLK; mib[2] = sb.st_rdev; size = sizeof(dev); if (sysctl(mib, 3, &dev, &size, NULL, 0) >= 0) { if (statbuf.st_dev / MAXPARTITIONS != dev / MAXPARTITIONS) errx(1, "cross-device install"); } pp = &dl->d_partitions[DISKPART(statbuf.st_dev)]; close(fd); sbread(devfd, DL_SECTOBLK(dl, DL_GETPOFFSET(pp)), &fs); /* Read inode. */ if ((buf = malloc(fs->fs_bsize)) == NULL) err(1, NULL); blk = fsbtodb(fs, ino_to_fsba(fs, statbuf.st_ino)); /* * Have the inode. Figure out how many filesystem blocks (not disk * sectors) there are for biosboot to load. */ devread(devfd, buf, DL_SECTOBLK(dl, pp->p_offset) + blk, fs->fs_bsize, "inode"); if (fs->fs_magic == FS_UFS2_MAGIC) { ip2 = (struct ufs2_dinode *)(buf) + ino_to_fsbo(fs, statbuf.st_ino); ndb = howmany(ip2->di_size, fs->fs_bsize); ap = (u_int *)ip2->di_db; skew = sizeof(u_int32_t); } else { ip1 = (struct ufs1_dinode *)(buf) + ino_to_fsbo(fs, statbuf.st_ino); ndb = howmany(ip1->di_size, fs->fs_bsize); ap = (u_int *)ip1->di_db; skew = 0; } if (ndb <= 0) errx(1, "No blocks to load"); /* * Now set the values that will need to go into biosboot * (the partition boot record, a.k.a. the PBR). */ sym_set_value(pbr_symbols, "_fs_bsize_p", (fs->fs_bsize / 16)); sym_set_value(pbr_symbols, "_fs_bsize_s", (fs->fs_bsize / dl->d_secsize)); /* * fs_fsbtodb is the shift to convert fs_fsize to DEV_BSIZE. The * ino_to_fsba() return value is the number of fs_fsize units. * Calculate the shift to convert fs_fsize into physical sectors, * which are added to p_offset to get the sector address BIOS * will use. * * N.B.: ASSUMES fs_fsize is a power of 2 of d_secsize. */ sym_set_value(pbr_symbols, "_fsbtodb", ffs(fs->fs_fsize / dl->d_secsize) - 1); if (pp->p_offseth != 0) errx(1, "partition offset too high"); sym_set_value(pbr_symbols, "_p_offset", pp->p_offset); sym_set_value(pbr_symbols, "_inodeblk", ino_to_fsba(fs, statbuf.st_ino)); sym_set_value(pbr_symbols, "_inodedbl", ((((char *)ap) - buf) + INODEOFF)); sym_set_value(pbr_symbols, "_nblocks", ndb); sym_set_value(pbr_symbols, "_blkskew", skew); if (verbose) { fprintf(stderr, "%s is %d blocks x %d bytes\n", boot, ndb, fs->fs_bsize); fprintf(stderr, "fs block shift %u; part offset %llu; " "inode block %lld, offset %u\n", ffs(fs->fs_fsize / dl->d_secsize) - 1, DL_GETPOFFSET(pp), ino_to_fsba(fs, statbuf.st_ino), (unsigned int)((((char *)ap) - buf) + INODEOFF)); fprintf(stderr, "expecting %d-bit fs blocks (skew %d)\n", skew ? 64 : 32, skew); } return 0; }
/* * Creacio del fitxer on es te el sistema de fitxers. * mi_mkfs <cantidad_bloques> * codis de retorn: * 0: correcte * -1: nombre de parametres incorrecte */ int main(int argc, char **argv) { int i = 0; int nombre_blocs; int n_inode; emofs_superblock sb; emofs_inode inode; /* Some fun */ char author[][20] = { AUTHOR_B, AUTHOR_P }; char buf[80]; char path[MAX_PATH_LEN]; int ascii_art; /* ASCII art, descriptor de fitxer */ int pos; int read_bytes; emofs_block bloc_zero = block_of_zero(); if (argc != 2) { nombre_blocs = DEFAULT_BLOCKS; } else { nombre_blocs = atoi(argv[1]); } bmount(); /* Inicialitzam tot el sistema de fitxers */ for (i = 0; i < nombre_blocs; i++) { bwrite(i, &bloc_zero); } init_superblock(nombre_blocs); init_bitmap(); init_inode_array(); /* Problema de bootstrap. Es necessita una ruta per crear un fitxer. */ n_inode = alloc_inode(DIRECTORY_INODE); sbread(&sb); sb.root_inode = n_inode; sbwrite(&sb); /* JUST FOR FUN */ /* Cream directori /authors */ if (fork() == 0) { execl("mi_mkdir", "mi_mkdir", "/authors", (char *)0); } else { wait3(NULL, 0, NULL); } /* Cream i omplim /authors/author[i].ascii" */ for (i = 0; i < AUTHOR_COUNT; i++) { ascii_art = open(author[i], O_RDONLY, S_IRUSR); strcpy(path, "/authors/"); strcat(path, author[i]); emofs_create(path); pos = 0; read_bytes = 1; /* per entrar al bucle */ while (read_bytes > 0) { /* Sortira amb el break */ lseek(ascii_art, pos, SEEK_SET); read_bytes = read(ascii_art, buf, 80); if (!read_bytes) break; emofs_write(path, buf, pos, read_bytes); pos += read_bytes; } close(ascii_art); } /* ending fun */ bumount(); return 0; }
/** Crea un fitxer o directori i la seva entrada de directori. * Princpipalment empra les funcoons find_entry, alloc_inode, write_file * @path: ruta del fitxer a crear * @return: 0 si es crea correctament. * -1 en cas d'error. */ int emofs_create(const char *path) { emofs_superblock sb; int i = 0; int p_inode_dir; int p_inode; int p_new_inode; int p_entry; emofs_inode inode; int type; char partial_path[MAX_PATH_LEN]; char new_dir_file[MAX_FILENAME_LEN]; int error = 0; int dir_entry_count; emofs_dir_entry dir_entry; if(!mutex){ emofs_sem_get(&mutex); } emofs_sem_wait(mutex); sbread(&sb); if (emofs_file_exists(path)) { /* Existeix, per tant no el podem crear */ puts("emofs_create: El fitxer o directori ja existeix"); emofs_sem_signal(mutex); return -1; } type = emofs_get_partial_path(path, partial_path, new_dir_file); /* Comprovam que existeixi la ruta on crear el fitxer o directori */ p_inode_dir = sb.root_inode; if (emofs_find_entry(partial_path, \ &p_inode_dir, &p_inode, &p_entry) == -1) { puts("emofs_create: El directori on es preten fer " \ "la creació no existeix"); printf("partial_path %s\n", partial_path); printf("p_inode_dir: %d, p_inode: %d, p_entry: %d\n", \ p_inode_dir, p_inode, p_entry); emofs_sem_signal(mutex); return error; } /* Obtenim el directori on volem crear l'entrada */ p_inode_dir = sb.root_inode; emofs_find_entry(path, &p_inode_dir, &p_inode, &p_entry); dir_entry.inode = alloc_inode(type); /* Aqui reservam l'inode */ if (dir_entry.inode == -1) { emofs_sem_signal(mutex); return -1; } for(i = 0; i < MAX_FILENAME_LEN; i++) { dir_entry.name[i] = ' '; } strcpy(dir_entry.name, new_dir_file); /* Llegim inode del directori del pare per saber el seu tamany i poder * escriure al final. */ read_inode(p_inode_dir, &inode); error = write_file(p_inode_dir, &dir_entry, inode.size, \ sizeof(emofs_dir_entry)); if ( error < 0) { puts("emofs_create: Error d'escriptura"); emofs_sem_signal(mutex); return error; } emofs_sem_signal(mutex); return error; }