/****************************************************************************** Put one pixel (Pixel) into GIF file. ******************************************************************************/ int EGifPutPixel(GifFileType *GifFile, GifPixelType Pixel) { GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; if (!IS_WRITEABLE(Private)) { /* This file was NOT open for writing: */ GifFile->Error = E_GIF_ERR_NOT_WRITEABLE; return GIF_ERROR; } if (Private->PixelCount == 0) { GifFile->Error = E_GIF_ERR_DATA_TOO_BIG; return GIF_ERROR; } --Private->PixelCount; /* Make sure the code is not out of bit range, as we might generate * wrong code (because of overflow when we combine them) in this case: */ Pixel &= CodeMask[Private->BitsPerPixel]; return EGifCompressLine(GifFile, &Pixel, 1); }
/****************************************************************************** This routine should be called before any attempt to dump an image - any call to any of the pixel dump routines. ******************************************************************************/ int EGifPutImageDesc(GifFileType *GifFile, const int Left, const int Top, const int Width, const int Height, const bool Interlace, const ColorMapObject *ColorMap) { GifByteType Buf[3]; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; if (Private->FileState & FILE_STATE_IMAGE && Private->PixelCount > 0xffff0000UL) { /* If already has active image descriptor - something is wrong! */ GifFile->Error = E_GIF_ERR_HAS_IMAG_DSCR; return GIF_ERROR; } if (!IS_WRITEABLE(Private)) { /* This file was NOT open for writing: */ GifFile->Error = E_GIF_ERR_NOT_WRITEABLE; return GIF_ERROR; } GifFile->Image.Left = Left; GifFile->Image.Top = Top; GifFile->Image.Width = Width; GifFile->Image.Height = Height; GifFile->Image.Interlace = Interlace; if (ColorMap) { if (GifFile->Image.ColorMap != NULL) { GifFreeMapObject(GifFile->Image.ColorMap); GifFile->Image.ColorMap = NULL; } GifFile->Image.ColorMap = GifMakeMapObject(ColorMap->ColorCount, ColorMap->Colors); if (GifFile->Image.ColorMap == NULL) { GifFile->Error = E_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } } else { GifFile->Image.ColorMap = NULL; } /* Put the image descriptor into the file: */ Buf[0] = DESCRIPTOR_INTRODUCER; /* Image separator character. */ InternalWrite(GifFile, Buf, 1); (void)EGifPutWord(Left, GifFile); (void)EGifPutWord(Top, GifFile); (void)EGifPutWord(Width, GifFile); (void)EGifPutWord(Height, GifFile); Buf[0] = (ColorMap ? 0x80 : 0x00) | (Interlace ? 0x40 : 0x00) | (ColorMap ? ColorMap->BitsPerPixel - 1 : 0); InternalWrite(GifFile, Buf, 1); /* If we have Global color map - dump it also: */ if (ColorMap != NULL) { int i; for (i = 0; i < ColorMap->ColorCount; i++) { /* Put the ColorMap out also: */ Buf[0] = ColorMap->Colors[i].Red; Buf[1] = ColorMap->Colors[i].Green; Buf[2] = ColorMap->Colors[i].Blue; if (InternalWrite(GifFile, Buf, 3) != 3) { GifFile->Error = E_GIF_ERR_WRITE_FAILED; return GIF_ERROR; } } } if (GifFile->SColorMap == NULL && GifFile->Image.ColorMap == NULL) { GifFile->Error = E_GIF_ERR_NO_COLOR_MAP; return GIF_ERROR; } /* Mark this file as has screen descriptor: */ Private->FileState |= FILE_STATE_IMAGE; Private->PixelCount = (long)Width *(long)Height; /* Reset compress algorithm parameters. */ (void)EGifSetupCompress(GifFile); return GIF_OK; }
/****************************************************************************** This routine should be called before any other EGif calls, immediately following the GIF file opening. ******************************************************************************/ int EGifPutScreenDesc(GifFileType *GifFile, const int Width, const int Height, const int ColorRes, const int BackGround, const ColorMapObject *ColorMap) { GifByteType Buf[3]; GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; const char *write_version; if (Private->FileState & FILE_STATE_SCREEN) { /* If already has screen descriptor - something is wrong! */ GifFile->Error = E_GIF_ERR_HAS_SCRN_DSCR; return GIF_ERROR; } if (!IS_WRITEABLE(Private)) { /* This file was NOT open for writing: */ GifFile->Error = E_GIF_ERR_NOT_WRITEABLE; return GIF_ERROR; } write_version = EGifGetGifVersion(GifFile); /* First write the version prefix into the file. */ if ((unsigned int)InternalWrite(GifFile, (unsigned char *)write_version, strlen(write_version)) != strlen(write_version)) { GifFile->Error = E_GIF_ERR_WRITE_FAILED; return GIF_ERROR; } GifFile->SWidth = Width; GifFile->SHeight = Height; GifFile->SColorResolution = ColorRes; GifFile->SBackGroundColor = BackGround; if (ColorMap) { GifFile->SColorMap = GifMakeMapObject(ColorMap->ColorCount, ColorMap->Colors); if (GifFile->SColorMap == NULL) { GifFile->Error = E_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } } else GifFile->SColorMap = NULL; /* * Put the logical screen descriptor into the file: */ /* Logical Screen Descriptor: Dimensions */ (void)EGifPutWord(Width, GifFile); (void)EGifPutWord(Height, GifFile); /* Logical Screen Descriptor: Packed Fields */ /* Note: We have actual size of the color table default to the largest * possible size (7+1 == 8 bits) because the decoder can use it to decide * how to display the files. */ Buf[0] = (ColorMap ? 0x80 : 0x00) | /* Yes/no global colormap */ ((ColorRes - 1) << 4) | /* Bits allocated to each primary color */ (ColorMap ? ColorMap->BitsPerPixel - 1 : 0x07 ); /* Actual size of the color table. */ if (ColorMap != NULL && ColorMap->SortFlag) Buf[0] |= 0x08; Buf[1] = BackGround; /* Index into the ColorTable for background color */ Buf[2] = GifFile->AspectByte; /* Pixel Aspect Ratio */ InternalWrite(GifFile, Buf, 3); /* If we have Global color map - dump it also: */ if (ColorMap != NULL) { int i; for (i = 0; i < ColorMap->ColorCount; i++) { /* Put the ColorMap out also: */ Buf[0] = ColorMap->Colors[i].Red; Buf[1] = ColorMap->Colors[i].Green; Buf[2] = ColorMap->Colors[i].Blue; if (InternalWrite(GifFile, Buf, 3) != 3) { GifFile->Error = E_GIF_ERR_WRITE_FAILED; return GIF_ERROR; } } } /* Mark this file as has screen descriptor, and no pixel written yet: */ Private->FileState |= FILE_STATE_SCREEN; return GIF_OK; }
// make a node (regular files only at this time) int fs_entry_mknod( struct fs_core* core, char const* path, mode_t mode, dev_t dev, uint64_t user, uint64_t vol ) { // only regular files at this time... if( ! ( S_ISREG( mode ) || S_ISFIFO( mode ) ) ) { return -ENOTSUP; } // revalidate this path int rc = fs_entry_revalidate_path( core, path ); if( rc != 0 && rc != -ENOENT ) { // consistency cannot be guaranteed SG_error("fs_entry_revalidate_path(%s) rc = %d\n", path, rc ); return rc; } int err = 0; // get the parent directory and lock it char* path_dirname = md_dirname( path, NULL ); struct fs_entry* parent = fs_entry_resolve_path( core, path_dirname, user, vol, true, &err ); free( path_dirname ); if( !IS_DIR_READABLE( parent->mode, parent->owner, parent->volume, user, vol ) ) { // not searchable fs_entry_unlock( parent ); return -EACCES; } if( !IS_WRITEABLE( parent->mode, parent->owner, parent->volume, user, vol ) ) { // not writeable fs_entry_unlock( parent ); return -EACCES; } uint64_t parent_id = parent->file_id; char* parent_name = strdup( parent->name ); char* path_basename = md_basename( path, NULL ); // make sure it doesn't exist already (or isn't in the process of being deleted, since we might have to re-create it if deleting it fails) if( fs_entry_set_find_name( parent->children, path_basename ) != NULL ) { free( path_basename ); fs_entry_unlock( parent ); free( parent_name ); return -EEXIST; } struct fs_entry* child = (struct fs_entry*)calloc( sizeof(struct fs_entry), 1 ); struct timespec ts; clock_gettime( CLOCK_REALTIME, &ts ); int mmode = 0; if (S_ISFIFO(mode)) { mmode = ( mode & 0777 ) | S_IFIFO; err = fs_entry_init_fifo( core, child, path_basename, 0, fs_entry_next_file_version(), user, core->gateway, vol, mmode, 0, ts.tv_sec, ts.tv_nsec, 0, 0 ); } if (S_ISREG(mode)) { mmode = ( mode & 0777 ); err = fs_entry_init_file( core, child, path_basename, 0, fs_entry_next_file_version(), user, core->gateway, vol, mmode, 0, ts.tv_sec, ts.tv_nsec, 0, 0 ); } if( err == 0 ) { // mark it as created in this session child->created_in_session = true; // we're creating, so this manifest is initialized (to zero blocks) child->manifest->initialize_empty( child->version ); fs_entry_wlock( child ); // call the driver err = driver_create_file( core, core->closure, path, child ); if( err != 0 ) { // undo SG_error("driver_create_file(%s) rc = %d\n", path, err ); child->open_count = 0; fs_entry_unlock( child ); fs_entry_destroy( child, false ); free( child ); } else { // attach the file fs_entry_attach_lowlevel( core, parent, child ); struct md_entry data; fs_entry_to_md_entry( core, &data, child, parent_id, parent_name ); // create the child on the MS, obtaining its file ID and write nonce err = ms_client_create( core->ms, &child->file_id, &child->write_nonce, &data ); md_entry_free( &data ); if( err != 0 ) { SG_error( "ms_client_create(%s) rc = %d\n", path, err ); err = -EREMOTEIO; child->open_count = 0; fs_entry_unlock( child ); fs_entry_detach_lowlevel( core, parent, child ); free( child ); } else { fs_entry_unlock( child ); } } } fs_entry_unlock( parent ); free( parent_name ); free( path_basename ); return err; }
// carry out the create locally. // check permissions, initialize the child, and add it as a child of parent. // return the initialized child (which will NOT be locked) via *ret_child // return 0 on success // return -EACCES on permission failure // parent MUST be write locked int fs_entry_do_create( struct fs_core* core, char const* path, struct fs_entry* parent, struct fs_entry** ret_child, uint64_t user, uint64_t vol, mode_t mode ) { int rc = 0; struct fs_entry* child = NULL; if( !IS_WRITEABLE(parent->mode, parent->owner, parent->volume, user, vol) ) { // can't create return -EACCES; } else { struct timespec ts; clock_gettime( CLOCK_REALTIME, &ts ); // can create--initialize the child child = SG_CALLOC( struct fs_entry, 1 ); char* path_basename = md_basename( path, NULL ); rc = fs_entry_init_file( core, child, path_basename, 0, fs_entry_next_file_version(), user, core->gateway, vol, mode, 0, ts.tv_sec, ts.tv_nsec, 0, 0 ); free( path_basename ); if( rc != 0 ) { SG_error("fs_entry_init_file(%s) rc = %d\n", path, rc ); fs_entry_destroy( child, false ); free( child ); return rc; } else { // mark it as created in this session child->created_in_session = true; // we're creating, so this manifest is initialized (to zero blocks) child->manifest->initialize_empty( child->version ); // run the driver int driver_rc = driver_create_file( core, core->closure, path, child ); if( driver_rc != 0 ) { SG_error("driver_create_file(%s) rc = %d\n", path, driver_rc ); fs_entry_destroy( child, false ); free( child ); return driver_rc; } // insert it into the filesystem fs_entry_wlock( child ); // open it child->open_count++; fs_entry_setup_working_data( core, child ); fs_entry_attach_lowlevel( core, parent, child ); fs_entry_unlock( child ); *ret_child = child; } } return 0; }